diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 531eb9c5179fa..3f9fbe2b357a2 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -43,3 +43,6 @@ d8f0e6caa91e230a486c948ab643174e40bdf215 # Use C++11 default member initializers in LLDB. NFC. 9494c510af56d9c8593ab69017dcaa232210b235 + +# [libc++][NFC] clang-format <__config> +ac251726f84d5b7e6533a2e3712920184435b61b diff --git a/.github/workflows/closed-issues.yml b/.github/workflows/closed-issues.yml index dba8503d57780..921bbcf786bfe 100644 --- a/.github/workflows/closed-issues.yml +++ b/.github/workflows/closed-issues.yml @@ -10,4 +10,4 @@ jobs: steps: - uses: andymckay/labeler@1.0.4 with: - remove-labels: "awaiting-review" \ No newline at end of file + remove-labels: 'awaiting-review' diff --git a/.github/workflows/issue-release-workflow.yml b/.github/workflows/issue-release-workflow.yml index e0e03a8970ad0..6a62001f9ecfe 100644 --- a/.github/workflows/issue-release-workflow.yml +++ b/.github/workflows/issue-release-workflow.yml @@ -4,7 +4,7 @@ # /cherry-pick <...> # # This comment will attempt to cherry-pick the given commits to the latest -# release branch (release/Y.x) and if successful push the result to a branch +# release branch (release/Y.x) and if successful, push the result to a branch # on github. # # /branch // @@ -31,9 +31,9 @@ jobs: name: Backport Commits runs-on: ubuntu-20.04 if: >- - (github.repository == 'llvm/llvm-project') && - !startswith(github.event.comment.body, '') && - contains(github.event.action == 'opened' && github.event.issue.body || github.event.comment.body, '/cherry-pick') + (github.repository == 'llvm/llvm-project') && + !startswith(github.event.comment.body, '') && + contains(github.event.action == 'opened' && github.event.issue.body || github.event.comment.body, '/cherry-pick') steps: - name: Fetch LLVM sources uses: actions/checkout@v2 @@ -64,16 +64,16 @@ jobs: name: Create Pull Request runs-on: ubuntu-20.04 if: >- - (github.repository == 'llvm/llvm-project') && - !startswith(github.event.comment.body, '') && - contains(github.event.comment.body, '/branch') + (github.repository == 'llvm/llvm-project') && + !startswith(github.event.comment.body, '') && + contains(github.event.comment.body, '/branch') steps: - name: Fetch LLVM sources uses: actions/checkout@v2 - name: Setup Environment - run: | + run: | pip install -r ./llvm/utils/git/requirements.txt - name: Create Pull Request diff --git a/.github/workflows/issue-subscriber.yml b/.github/workflows/issue-subscriber.yml index 43014e4ccc256..a243c75268146 100644 --- a/.github/workflows/issue-subscriber.yml +++ b/.github/workflows/issue-subscriber.yml @@ -10,20 +10,20 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'llvm/llvm-project' steps: - - name: Setup Automation Script - run: | - curl -O -L https://raw.githubusercontent.com/$GITHUB_REPOSITORY/$GITHUB_SHA/llvm/utils/git/github-automation.py - curl -O -L https://raw.githubusercontent.com/$GITHUB_REPOSITORY/$GITHUB_SHA/llvm/utils/git/requirements.txt - chmod a+x github-automation.py - pip install -r requirements.txt + - name: Setup Automation Script + run: | + curl -O -L https://raw.githubusercontent.com/$GITHUB_REPOSITORY/$GITHUB_SHA/llvm/utils/git/github-automation.py + curl -O -L https://raw.githubusercontent.com/$GITHUB_REPOSITORY/$GITHUB_SHA/llvm/utils/git/requirements.txt + chmod a+x github-automation.py + pip install -r requirements.txt - - name: Update watchers - # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable - env: - LABEL_NAME: ${{ github.event.label.name }} - run: | - ./github-automation.py \ - --token '${{ secrets.ISSUE_SUBSCRIBER_TOKEN }}' \ - issue-subscriber \ - --issue-number '${{ github.event.issue.number }}' \ - --label-name "$LABEL_NAME" + - name: Update watchers + # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable + env: + LABEL_NAME: ${{ github.event.label.name }} + run: | + ./github-automation.py \ + --token '${{ secrets.ISSUE_SUBSCRIBER_TOKEN }}' \ + issue-subscriber \ + --issue-number '${{ github.event.issue.number }}' \ + --label-name "$LABEL_NAME" diff --git a/.github/workflows/llvm-bugs.yml b/.github/workflows/llvm-bugs.yml index 3be8a3e291688..36c967e4617cd 100644 --- a/.github/workflows/llvm-bugs.yml +++ b/.github/workflows/llvm-bugs.yml @@ -19,39 +19,39 @@ jobs: MAILGUN_API_KEY: ${{ secrets.LLVM_BUGS_KEY }} with: script: | - const Mailgun = require("mailgun.js"); + const Mailgun = require('mailgun.js'); const formData = require('form-data'); - const mailgun = new Mailgun(formData); - const DOMAIN = "email.llvm.org"; + const mailgun = new Mailgun(formData); + const DOMAIN = 'email.llvm.org'; - const mg = mailgun.client({username: 'api', key: process.env.MAILGUN_API_KEY}); + const mg = mailgun.client({ username: 'api', key: process.env.MAILGUN_API_KEY }); github.rest.issues.get({ issue_number: context.issue.number, owner: context.repo.owner, - repo: context.repo.repo, + repo: context.repo.repo }) - .then(function(issue) { + .then((issue) => { const payload = { author : issue.data.user.login, issue : issue.data.number, title : issue.data.title, url : issue.data.html_url, - labels : issue.data.labels.map(label => { return label.name }), - assignee : issue.data.assignees.map(assignee => { return assignee.login }), + labels : issue.data.labels.map((label) => label.name), + assignee : issue.data.assignees.map((assignee) => assignee.login), body : issue.data.body }; - + const data = { - from: "LLVM Bugs ", - to: "llvm-bugs@lists.llvm.org", + from: 'LLVM Bugs ', + to: 'llvm-bugs@lists.llvm.org', subject: `[Bug ${issue.data.number}] ${issue.data.title}`, - template: "new-github-issue", + template: 'new-github-issue', 'o:tracking-clicks': 'no', 'h:X-Mailgun-Variables': JSON.stringify(payload) }; - return mg.messages.create(DOMAIN, data) + return mg.messages.create(DOMAIN, data); }) - .then(msg => console.log(msg)); + .then((msg) => console.log(msg)); diff --git a/.github/workflows/new-issues.yml b/.github/workflows/new-issues.yml index 5a8e79ba8874e..97dfc54a7b130 100644 --- a/.github/workflows/new-issues.yml +++ b/.github/workflows/new-issues.yml @@ -10,5 +10,5 @@ jobs: steps: - uses: andymckay/labeler@1.0.4 with: - add-labels: "new issue" + add-labels: 'new issue' ignore-if-labeled: true diff --git a/bolt/README.md b/bolt/README.md index 22bf2a65b67c2..5580eaac76955 100644 --- a/bolt/README.md +++ b/bolt/README.md @@ -180,7 +180,7 @@ Once you have `perf.fdata` ready, you can use it for optimizations with BOLT. Assuming your environment is setup to include the right path, execute `llvm-bolt`: ``` -$ llvm-bolt -o .bolt -data=perf.fdata -reorder-blocks=cache+ -reorder-functions=hfsort -split-functions=2 -split-all-cold -split-eh -dyno-stats +$ llvm-bolt -o .bolt -data=perf.fdata -reorder-blocks=ext-tsp -reorder-functions=hfsort -split-functions=2 -split-all-cold -split-eh -dyno-stats ``` If you do need an updated debug info, then add `-update-debug-sections` option diff --git a/bolt/docs/OptimizingClang.md b/bolt/docs/OptimizingClang.md index e66201b31d6d4..4bbc757d59d57 100644 --- a/bolt/docs/OptimizingClang.md +++ b/bolt/docs/OptimizingClang.md @@ -64,7 +64,7 @@ Notice that we are passing `clang-7` to `perf2bolt` which is the real binary tha the generated profile: ```bash $ llvm-bolt $CPATH/clang-7 -o $CPATH/clang-7.bolt -b clang-7.yaml \ - -reorder-blocks=cache+ -reorder-functions=hfsort+ -split-functions=3 \ + -reorder-blocks=ext-tsp -reorder-functions=hfsort+ -split-functions=3 \ -split-all-cold -dyno-stats -icf=1 -use-gnu-stack ``` The output will look similar to the one below: diff --git a/bolt/docs/doxygen.cfg.in b/bolt/docs/doxygen.cfg.in index 2913285c55cff..acdf6f66842b6 100644 --- a/bolt/docs/doxygen.cfg.in +++ b/bolt/docs/doxygen.cfg.in @@ -38,7 +38,7 @@ PROJECT_NAME = "BOLT" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = +PROJECT_NUMBER = @PACKAGE_VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h index ccd1833699548..ab5af557c8021 100644 --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -82,6 +82,13 @@ inline raw_ostream &operator<<(raw_ostream &OS, const SegmentInfo &SegInfo) { return OS; } +// AArch64-specific symbol markers used to delimit code/data in .text. +enum class MarkerSymType : char { + NONE = 0, + CODE, + DATA, +}; + enum class MemoryContentsType : char { UNKNOWN = 0, /// Unknown contents. POSSIBLE_JUMP_TABLE, /// Possibly a non-PIC jump table. @@ -232,7 +239,7 @@ class BinaryContext { Optional getDWOCU(uint64_t DWOId); /// Returns DWOContext if it exists. - DWARFContext *getDWOContext(); + DWARFContext *getDWOContext() const; /// Get Number of DWOCUs in a map. uint32_t getNumDWOCUs() { return DWOCUs.size(); } @@ -549,6 +556,9 @@ class BinaryContext { std::unique_ptr DisAsm; + /// Symbolic disassembler. + std::unique_ptr SymbolicDisAsm; + std::unique_ptr MAB; /// Indicates if relocations are available for usage. @@ -662,6 +672,11 @@ class BinaryContext { TheTriple->getArch() == llvm::Triple::x86_64; } + // AArch64-specific functions to check if symbol is used to delimit + // code/data in .text. Code is marked by $x, data by $d. + MarkerSymType getMarkerType(const SymbolRef &Symbol) const; + bool isMarker(const SymbolRef &Symbol) const; + /// Iterate over all BinaryData. iterator_range getBinaryData() const { return make_range(BinaryDataMap.begin(), BinaryDataMap.end()); diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h index 2c3ed9d35636e..58df5b999c3d0 100644 --- a/bolt/include/bolt/Core/BinaryFunction.h +++ b/bolt/include/bolt/Core/BinaryFunction.h @@ -833,6 +833,29 @@ class BinaryFunction { return make_range(JumpTables.begin(), JumpTables.end()); } + /// Return relocation associated with a given \p Offset in the function, + /// or nullptr if no such relocation exists. + const Relocation *getRelocationAt(uint64_t Offset) const { + assert(CurrentState == State::Empty && + "Relocations unavailable in the current function state."); + auto RI = Relocations.find(Offset); + return (RI == Relocations.end()) ? nullptr : &RI->second; + } + + /// Return the first relocation in the function that starts at an address in + /// the [StartOffset, EndOffset) range. Return nullptr if no such relocation + /// exists. + const Relocation *getRelocationInRange(uint64_t StartOffset, + uint64_t EndOffset) const { + assert(CurrentState == State::Empty && + "Relocations unavailable in the current function state."); + auto RI = Relocations.lower_bound(StartOffset); + if (RI != Relocations.end() && RI->first < EndOffset) + return &RI->second; + + return nullptr; + } + /// Returns the raw binary encoding of this function. ErrorOr> getData() const; @@ -959,6 +982,15 @@ class BinaryFunction { return const_cast(this)->getInstructionAtOffset(Offset); } + /// Return offset for the first instruction. If there is data at the + /// beginning of a function then offset of the first instruction could + /// be different from 0 + uint64_t getFirstInstructionOffset() const { + if (Instructions.empty()) + return 0; + return Instructions.begin()->first; + } + /// Return jump table that covers a given \p Address in memory. JumpTable *getJumpTableContainingAddress(uint64_t Address) { auto JTI = JumpTables.upper_bound(Address); @@ -1305,11 +1337,11 @@ class BinaryFunction { case ELF::R_X86_64_PC8: case ELF::R_X86_64_PC32: case ELF::R_X86_64_PC64: + case ELF::R_X86_64_GOTPCRELX: + case ELF::R_X86_64_REX_GOTPCRELX: Relocations[Offset] = Relocation{Offset, Symbol, RelType, Addend, Value}; return; case ELF::R_X86_64_PLT32: - case ELF::R_X86_64_GOTPCRELX: - case ELF::R_X86_64_REX_GOTPCRELX: case ELF::R_X86_64_GOTPCREL: case ELF::R_X86_64_TPOFF32: case ELF::R_X86_64_GOTTPOFF: @@ -1948,11 +1980,6 @@ class BinaryFunction { return ColdLSDASymbol; } - /// True if the symbol is a mapping symbol used in AArch64 to delimit - /// data inside code section. - bool isDataMarker(const SymbolRef &Symbol, uint64_t SymbolSize) const; - bool isCodeMarker(const SymbolRef &Symbol, uint64_t SymbolSize) const; - void setOutputDataAddress(uint64_t Address) { OutputDataOffset = Address; } uint64_t getOutputDataAddress() const { return OutputDataOffset; } diff --git a/bolt/include/bolt/Core/DebugData.h b/bolt/include/bolt/Core/DebugData.h index 0de5d153bf237..fad14c1c5a3ba 100644 --- a/bolt/include/bolt/Core/DebugData.h +++ b/bolt/include/bolt/Core/DebugData.h @@ -34,6 +34,30 @@ namespace llvm { namespace bolt { +struct AttrInfo { + DWARFFormValue V; + const DWARFAbbreviationDeclaration *AbbrevDecl; + uint64_t Offset; + uint32_t Size; // Size of the attribute. +}; + +/// Finds attributes FormValue and Offset. +/// +/// \param DIE die to look up in. +/// \param AbbrevDecl abbrev declaration for the die. +/// \param Index an index in Abbrev declaration entry. +Optional +findAttributeInfo(const DWARFDie DIE, + const DWARFAbbreviationDeclaration *AbbrevDecl, + uint32_t Index); + +/// Finds attributes FormValue and Offset. +/// +/// \param DIE die to look up in. +/// \param Attr the attribute to extract. +/// \return an optional AttrInfo with DWARFFormValue and Offset. +Optional findAttributeInfo(const DWARFDie DIE, dwarf::Attribute Attr); + // DWARF5 Header in order of encoding. // Types represent encodnig sizes. using UnitLengthType = uint32_t; @@ -447,23 +471,31 @@ class DebugStrWriter { BinaryContext &BC; }; +class DebugInfoBinaryPatcher; +class DebugAbbrevWriter; enum class LocWriterKind { DebugLocWriter, DebugLoclistWriter }; /// Serializes part of a .debug_loc DWARF section with LocationLists. class SimpleBinaryPatcher; class DebugLocWriter { +protected: + DebugLocWriter(uint8_t DwarfVersion, LocWriterKind Kind) + : DwarfVersion(DwarfVersion), Kind(Kind) { + init(); + } + public: - DebugLocWriter() = delete; - DebugLocWriter(BinaryContext *BC); + DebugLocWriter() { init(); }; virtual ~DebugLocWriter(){}; /// Writes out location lists and stores internal patches. - virtual void addList(uint64_t AttrOffset, uint32_t LocListIndex, - DebugLocationsVector &&LocList); + virtual void addList(AttrInfo &AttrVal, DebugLocationsVector &LocList, + DebugInfoBinaryPatcher &DebugInfoPatcher, + DebugAbbrevWriter &AbbrevWriter); /// Writes out locations in to a local buffer, and adds Debug Info patches. - virtual void finalize(uint64_t SectionOffset, - SimpleBinaryPatcher &DebugInfoPatcher); + virtual void finalize(DebugInfoBinaryPatcher &DebugInfoPatcher, + DebugAbbrevWriter &AbbrevWriter); /// Return internal buffer. virtual std::unique_ptr getBuffer(); @@ -485,13 +517,15 @@ class DebugLocWriter { std::unique_ptr LocStream; /// Current offset in the section (updated as new entries are written). /// Starts with 0 here since this only writes part of a full location lists - /// section. In the final section, the first 16 bytes are reserved for an - /// empty list. - uint32_t SectionOffset{0}; + /// section. In the final section, for DWARF4, the first 16 bytes are reserved + /// for an empty list. + static uint32_t LocSectionOffset; uint8_t DwarfVersion{4}; LocWriterKind Kind{LocWriterKind::DebugLocWriter}; private: + /// Inits all the related data structures. + void init(); struct LocListDebugInfoPatchType { uint64_t DebugInfoAttrOffset; uint64_t LocListOffset; @@ -501,36 +535,39 @@ class DebugLocWriter { /// The list of debug info patches to be made once individual /// location list writers have been filled VectorLocListDebugInfoPatchType LocListDebugInfoPatches; - - using VectorEmptyLocListAttributes = std::vector; - /// Contains all the attributes pointing to empty location list. - VectorEmptyLocListAttributes EmptyAttrLists; }; class DebugLoclistWriter : public DebugLocWriter { public: ~DebugLoclistWriter() {} DebugLoclistWriter() = delete; - DebugLoclistWriter(BinaryContext *BC, DWARFUnit &Unit, - uint32_t LocListsBaseAttrOffset, uint8_t DV, bool SD) - : DebugLocWriter(BC), CU(Unit), - LocListsBaseAttrOffset(LocListsBaseAttrOffset), IsSplitDwarf(SD) { - Kind = LocWriterKind::DebugLoclistWriter; - DwarfVersion = DV; + DebugLoclistWriter(DWARFUnit &Unit, uint8_t DV, bool SD) + : DebugLocWriter(DV, LocWriterKind::DebugLoclistWriter), CU(Unit), + IsSplitDwarf(SD) { assert(DebugLoclistWriter::AddrWriter && "Please use SetAddressWriter to initialize " "DebugAddrWriter before instantiation."); + if (DwarfVersion >= 5) { + LocBodyBuffer = std::make_unique(); + LocBodyStream = std::make_unique(*LocBodyBuffer); + } else { + // Writing out empty location list to which all references to empty + // location lists will point. + const char Zeroes[16] = {0}; + *LocStream << StringRef(Zeroes, 16); + } } static void setAddressWriter(DebugAddrWriter *AddrW) { AddrWriter = AddrW; } /// Stores location lists internally to be written out during finalize phase. - virtual void addList(uint64_t AttrOffset, uint32_t LocListIndex, - DebugLocationsVector &&LocList) override; + virtual void addList(AttrInfo &AttrVal, DebugLocationsVector &LocList, + DebugInfoBinaryPatcher &DebugInfoPatcher, + DebugAbbrevWriter &AbbrevWriter) override; /// Writes out locations in to a local buffer and applies debug info patches. - void finalize(uint64_t SectionOffset, - SimpleBinaryPatcher &DebugInfoPatcher) override; + void finalize(DebugInfoBinaryPatcher &DebugInfoPatcher, + DebugAbbrevWriter &AbbrevWriter) override; /// Returns CU ID. /// For Skelton CU it is a CU Offset. @@ -548,36 +585,21 @@ class DebugLoclistWriter : public DebugLocWriter { bool isSplitDwarf() const { return IsSplitDwarf; } constexpr static uint32_t InvalidIndex = UINT32_MAX; - constexpr static uint32_t InvalidLocListsBaseAttrOffset = UINT32_MAX; private: /// Writes out locations in to a local buffer and applies debug info patches. - void finalizeDWARFLegacy(uint64_t SectionOffset, - SimpleBinaryPatcher &DebugInfoPatcher); - - /// Writes out locations in to a local buffer and applies debug info patches. - void finalizeDWARF5(uint64_t SectionOffset, - SimpleBinaryPatcher &DebugInfoPatcher); - - struct LocPatch { - uint64_t AttrOffset{0}; - uint32_t Index; - DebugLocationsVector LocList; - }; - using LocPatchVec = SmallVector; - LocPatchVec Patches; + void finalizeDWARF5(DebugInfoBinaryPatcher &DebugInfoPatcher, + DebugAbbrevWriter &AbbrevWriter); - class Patch { - public: - Patch() = delete; - Patch(uint64_t O, uint64_t A) : Offset(O), Address(A) {} - uint64_t Offset{0}; - uint64_t Address{0}; - }; static DebugAddrWriter *AddrWriter; DWARFUnit &CU; - uint32_t LocListsBaseAttrOffset{InvalidLocListsBaseAttrOffset}; bool IsSplitDwarf{false}; + // Used for DWARF5 to store location lists before being finalized. + std::unique_ptr LocBodyBuffer; + std::unique_ptr LocBodyStream; + std::vector RelativeLocListOffsets; + uint32_t NumberOfEntries{0}; + static uint32_t LoclistBaseOffset; }; enum class PatcherKind { SimpleBinaryPatcher, DebugInfoBinaryPatcher }; @@ -1156,18 +1178,6 @@ class DwarfLineTable { // Returns DWARF Version for this line table. uint16_t getDwarfVersion() const { return DwarfVersion; } }; - -struct AttrInfo { - DWARFFormValue V; - uint64_t Offset; - uint32_t Size; // Size of the attribute. -}; - -Optional -findAttributeInfo(const DWARFDie DIE, - const DWARFAbbreviationDeclaration *AbbrevDecl, - uint32_t Index); - } // namespace bolt } // namespace llvm diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index d4f5c4202292f..c6739373ab12a 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -21,6 +21,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" #include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCDisassembler/MCSymbolizer.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrAnalysis.h" @@ -44,6 +45,7 @@ class MCSymbol; class raw_ostream; namespace bolt { +class BinaryFunction; /// Different types of indirect branches encountered during disassembly. enum class IndirectBranchType : char { @@ -286,6 +288,12 @@ class MCPlusBuilder { initAliases(); } + /// Create and return target-specific MC symbolizer for the \p Function. + virtual std::unique_ptr + createTargetSymbolizer(BinaryFunction &Function) const { + return nullptr; + } + /// Initialize a new annotation allocator and return its id AllocatorIdTy initializeNewAnnotationAllocator() { AnnotationAllocators.emplace(MaxAllocatorId, AnnotationAllocator()); diff --git a/bolt/include/bolt/Core/Relocation.h b/bolt/include/bolt/Core/Relocation.h index e0b977c5d0bbd..08bb02caac50f 100644 --- a/bolt/include/bolt/Core/Relocation.h +++ b/bolt/include/bolt/Core/Relocation.h @@ -55,7 +55,10 @@ struct Relocation { /// Return size of this relocation. size_t getSize() const { return getSizeForType(Type); } - /// Handle special cases when relocation should not be processed by bolt + /// Skip relocations that we don't want to handle in BOLT + static bool skipRelocationType(uint64_t Type); + + /// Handle special cases when relocation should not be processed by BOLT static bool skipRelocationProcess(uint64_t Type, uint64_t Contents); // Adjust value depending on relocation type (make it PC relative or not) @@ -77,6 +80,9 @@ struct Relocation { /// Return true if relocation type implies the creation of a GOT entry static bool isGOT(uint64_t Type); + /// Special relocation type that allows the linker to modify the instruction. + static bool isX86GOTPCRELX(uint64_t Type); + /// Return true if relocation type is NONE static bool isNone(uint64_t Type); diff --git a/bolt/include/bolt/Passes/BinaryPasses.h b/bolt/include/bolt/Passes/BinaryPasses.h index 8169ff68e860a..f036f99a0dff8 100644 --- a/bolt/include/bolt/Passes/BinaryPasses.h +++ b/bolt/include/bolt/Passes/BinaryPasses.h @@ -142,6 +142,8 @@ class ReorderBasicBlocks : public BinaryFunctionPass { /// LT_OPTIMIZE_CACHE piggybacks on the idea from Ispike paper (CGO '04) /// that suggests putting frequently executed chains first in the layout. LT_OPTIMIZE_CACHE, + // CACHE_PLUS and EXT_TSP are synonyms, emit warning of deprecation. + LT_OPTIMIZE_CACHE_PLUS, /// Block reordering guided by the extended TSP metric. LT_OPTIMIZE_EXT_TSP, /// Create clusters and use random order for them. diff --git a/bolt/include/bolt/Passes/CallGraph.h b/bolt/include/bolt/Passes/CallGraph.h index 72067791cc3ec..e8d53bbe383f1 100644 --- a/bolt/include/bolt/Passes/CallGraph.h +++ b/bolt/include/bolt/Passes/CallGraph.h @@ -9,9 +9,10 @@ #ifndef BOLT_PASSES_CALLGRAPH_H #define BOLT_PASSES_CALLGRAPH_H +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" #include #include -#include #include #include @@ -160,31 +161,31 @@ class CallGraph { }; template void CallGraph::printDot(char *FileName, L GetLabel) const { - FILE *File = fopen(FileName, "wt"); - if (!File) + std::error_code EC; + raw_fd_ostream OS(std::string(FileName), EC, sys::fs::OF_None); + if (EC) return; - fprintf(File, "digraph g {\n"); + OS << "digraph g {\n"; for (NodeId F = 0; F < Nodes.size(); F++) { if (Nodes[F].samples() == 0) continue; - fprintf(File, "f%lu [label=\"%s\\nsamples=%u\\nsize=%u\"];\n", F, - GetLabel(F), Nodes[F].samples(), Nodes[F].size()); + OS << "f" << F << " [label=\"" << GetLabel(F) + << "\\nsamples=" << Nodes[F].samples() << "\\nsize=" << Nodes[F].size() + << "\"];\n"; } for (NodeId F = 0; F < Nodes.size(); F++) { if (Nodes[F].samples() == 0) continue; for (NodeId Dst : Nodes[F].successors()) { ArcConstIterator Arc = findArc(F, Dst); - fprintf( - File, - "f%lu -> f%u [label=\"normWgt=%.3lf,weight=%.0lf,callOffset=%.1lf\"];" - "\n", - F, Dst, Arc->normalizedWeight(), Arc->weight(), Arc->avgCallOffset()); + OS << "f" << F << " -> f" << Dst + << " [label=\"normWgt=" << format("%.3lf", Arc->normalizedWeight()) + << ",weight=" << format("%.0lf", Arc->weight()) + << ",callOffset=" << format("%.1lf", Arc->avgCallOffset()) << "\"];\n"; } } - fprintf(File, "}\n"); - fclose(File); + OS << "}\n"; } } // namespace bolt diff --git a/bolt/include/bolt/Passes/TailDuplication.h b/bolt/include/bolt/Passes/TailDuplication.h index 2a5d4f8531f52..4121c7e28a028 100644 --- a/bolt/include/bolt/Passes/TailDuplication.h +++ b/bolt/include/bolt/Passes/TailDuplication.h @@ -46,16 +46,19 @@ namespace bolt { /// Pass for duplicating blocks that would require a jump. class TailDuplication : public BinaryFunctionPass { /// Record how many possible tail duplications there can be. - uint64_t PossibleDuplications = 0; + uint64_t ModifiedFunctions = 0; - /// Record how many times these duplications would get used. - uint64_t PossibleDuplicationsDynamicCount = 0; + /// The number of duplicated basic blocks. + uint64_t DuplicatedBlockCount = 0; + + /// The size (in bytes) of duplicated basic blocks. + uint64_t DuplicatedByteCount = 0; - /// Record the execution count of all unconditional branches. - uint64_t UnconditionalBranchDynamicCount = 0; + /// Record how many times these duplications would get used. + uint64_t DuplicationsDynamicCount = 0; /// Record the execution count of all blocks. - uint64_t AllBlocksDynamicCount = 0; + uint64_t AllDynamicCount = 0; /// Record the number of instructions deleted because of propagation uint64_t StaticInstructionDeletionCount = 0; @@ -87,25 +90,57 @@ class TailDuplication : public BinaryFunctionPass { constantAndCopyPropagate(BinaryBasicBlock &OriginalBB, std::vector &BlocksToPropagate); - /// True if Succ is in the same cache line as BB (approximately) + /// True if Tail is in the same cache line as BB (approximately) bool isInCacheLine(const BinaryBasicBlock &BB, - const BinaryBasicBlock &Succ) const; + const BinaryBasicBlock &Tail) const; /// Duplicates BlocksToDuplicate and places them after BB. - std::vector - tailDuplicate(BinaryBasicBlock &BB, - const std::vector &BlocksToDuplicate) const; - + std::vector duplicateBlocks( + BinaryBasicBlock &BB, + const std::vector &BlocksToDuplicate) const; + + /// Decide whether the tail basic blocks should be duplicated after BB. + bool shouldDuplicate(BinaryBasicBlock *BB, BinaryBasicBlock *Tail) const; + + /// Compute the cache score for a jump (Src, Dst) with frequency Count. + /// The value is in the range [0..1] and quantifies how "cache-friendly" + /// the jump is. The score is close to 1 for "short" forward jumps and + /// it is 0 for "long" jumps exceeding a specified threshold; between the + /// bounds, the value decreases linearly. For backward jumps, the value is + /// scaled by a specified factor. + double cacheScore(uint64_t SrcAddr, uint64_t SrcSize, uint64_t DstAddr, + uint64_t DstSize, uint64_t Count) const; + + /// Decide whether the cache score has been improved after duplication. + bool cacheScoreImproved(const MCCodeEmitter *Emitter, BinaryFunction &BF, + BinaryBasicBlock *Pred, BinaryBasicBlock *Tail) const; + + /// A moderate strategy for tail duplication. /// Returns a vector of BinaryBasicBlock to copy after BB. If it's empty, - /// nothing should be duplicated + /// nothing should be duplicated. std::vector - moderateCodeToDuplicate(BinaryBasicBlock &BB) const; + moderateDuplicate(BinaryBasicBlock &BB, BinaryBasicBlock &Tail) const; + + /// An aggressive strategy for tail duplication. std::vector - aggressiveCodeToDuplicate(BinaryBasicBlock &BB) const; + aggressiveDuplicate(BinaryBasicBlock &BB, BinaryBasicBlock &Tail) const; + + /// A cache-aware strategy for tail duplication. + std::vector cacheDuplicate(const MCCodeEmitter *Emitter, + BinaryFunction &BF, + BinaryBasicBlock *BB, + BinaryBasicBlock *Tail) const; void runOnFunction(BinaryFunction &Function); public: + enum DuplicationMode : char { + TD_NONE = 0, + TD_AGGRESSIVE, + TD_MODERATE, + TD_CACHE + }; + explicit TailDuplication() : BinaryFunctionPass(false) {} const char *getName() const override { return "tail duplication"; } diff --git a/bolt/include/bolt/Rewrite/DWARFRewriter.h b/bolt/include/bolt/Rewrite/DWARFRewriter.h index 82111d730504c..e94e326cac71f 100644 --- a/bolt/include/bolt/Rewrite/DWARFRewriter.h +++ b/bolt/include/bolt/Rewrite/DWARFRewriter.h @@ -16,6 +16,7 @@ #include #include #include +#include #include namespace llvm { @@ -25,8 +26,12 @@ namespace bolt { class BinaryContext; class DWARFRewriter { +public: DWARFRewriter() = delete; + using DebugTypesSignaturesPerCUMap = + std::unordered_map>; +private: BinaryContext &BC; std::mutex DebugInfoPatcherMutex; @@ -75,6 +80,9 @@ class DWARFRewriter { /// Binary patchers for DWO debug_info sections. DebugInfoDWOPatchers BinaryDWODebugInfoPatchers; + /// Stores all the Type Signatures for DWO CU. + DebugTypesSignaturesPerCUMap TypeSignaturesPerCU; + std::mutex LocListDebugInfoPatchesMutex; /// DWARFLegacy is all DWARF versions before DWARF 5. @@ -104,7 +112,7 @@ class DWARFRewriter { Optional RangesBase = None); std::unique_ptr - makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher, + makeFinalLocListsSection(DebugInfoBinaryPatcher &DebugInfoPatcher, DWARFVersion Version); /// Finalize debug sections in the main binary. diff --git a/bolt/lib/Core/BinaryBasicBlock.cpp b/bolt/lib/Core/BinaryBasicBlock.cpp index 5ff4044e72951..8a20b0ab9f795 100644 --- a/bolt/lib/Core/BinaryBasicBlock.cpp +++ b/bolt/lib/Core/BinaryBasicBlock.cpp @@ -563,7 +563,7 @@ void BinaryBasicBlock::dump() const { if (Label) outs() << Label->getName() << ":\n"; BC.printInstructions(outs(), Instructions.begin(), Instructions.end(), - getOffset()); + getOffset(), Function); outs() << "preds:"; for (auto itr = pred_begin(); itr != pred_end(); ++itr) { outs() << " " << (*itr)->getName(); diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index e9ca8129453e1..d8b55b826e99f 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -47,12 +47,9 @@ using namespace llvm; namespace opts { -cl::opt -NoHugePages("no-huge-pages", - cl::desc("use regular size pages for code alignment"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); +cl::opt NoHugePages("no-huge-pages", + cl::desc("use regular size pages for code alignment"), + cl::Hidden, cl::cat(BoltCategory)); static cl::opt PrintDebugInfo("print-debug-info", @@ -61,12 +58,10 @@ PrintDebugInfo("print-debug-info", cl::ZeroOrMore, cl::cat(BoltCategory)); -cl::opt -PrintRelocations("print-relocations", - cl::desc("print relocations when printing functions/objects"), - cl::Hidden, - cl::ZeroOrMore, - cl::cat(BoltCategory)); +cl::opt PrintRelocations( + "print-relocations", + cl::desc("print relocations when printing functions/objects"), cl::Hidden, + cl::cat(BoltCategory)); static cl::opt PrintMemData("print-mem-data", @@ -251,6 +246,14 @@ BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC, BC->HasFixedLoadAddress = !IsPIC; + BC->SymbolicDisAsm = std::unique_ptr( + BC->TheTarget->createMCDisassembler(*BC->STI, *BC->Ctx)); + + if (!BC->SymbolicDisAsm) + return createStringError( + make_error_code(std::errc::not_supported), + Twine("BOLT-ERROR: no disassembler info for target ", TripleName)); + return std::move(BC); } @@ -712,13 +715,15 @@ void BinaryContext::skipMarkedFragments() { "internal error in traversing function fragments"); if (opts::Verbosity >= 1) errs() << "BOLT-WARNING: Ignoring " << BF->getPrintName() << '\n'; - BF->setIgnored(); + BF->setSimple(false); + BF->setHasSplitJumpTable(true); + std::for_each(BF->Fragments.begin(), BF->Fragments.end(), addToWorklist); std::for_each(BF->ParentFragments.begin(), BF->ParentFragments.end(), addToWorklist); } if (!FragmentsToSkip.empty()) - errs() << "BOLT-WARNING: ignored " << FragmentsToSkip.size() << " function" + errs() << "BOLT-WARNING: skipped " << FragmentsToSkip.size() << " function" << (FragmentsToSkip.size() == 1 ? "" : "s") << " due to cold fragments\n"; FragmentsToSkip.clear(); @@ -1406,7 +1411,7 @@ Optional BinaryContext::getDWOCU(uint64_t DWOId) { return Iter->second; } -DWARFContext *BinaryContext::getDWOContext() { +DWARFContext *BinaryContext::getDWOContext() const { if (DWOCUs.empty()) return nullptr; return &DWOCUs.begin()->second->getContext(); @@ -1639,6 +1644,65 @@ void BinaryContext::printCFI(raw_ostream &OS, const MCCFIInstruction &Inst) { } } +MarkerSymType BinaryContext::getMarkerType(const SymbolRef &Symbol) const { + // For aarch64, the ABI defines mapping symbols so we identify data in the + // code section (see IHI0056B). $x identifies a symbol starting code or the + // end of a data chunk inside code, $d indentifies start of data. + if (!isAArch64() || ELFSymbolRef(Symbol).getSize()) + return MarkerSymType::NONE; + + Expected NameOrError = Symbol.getName(); + Expected TypeOrError = Symbol.getType(); + + if (!TypeOrError || !NameOrError) + return MarkerSymType::NONE; + + if (*TypeOrError != SymbolRef::ST_Unknown) + return MarkerSymType::NONE; + + if (*NameOrError == "$x" || NameOrError->startswith("$x.")) + return MarkerSymType::CODE; + + if (*NameOrError == "$d" || NameOrError->startswith("$d.")) + return MarkerSymType::DATA; + + return MarkerSymType::NONE; +} + +bool BinaryContext::isMarker(const SymbolRef &Symbol) const { + return getMarkerType(Symbol) != MarkerSymType::NONE; +} + +static void printDebugInfo(raw_ostream &OS, const MCInst &Instruction, + const BinaryFunction *Function, + DWARFContext *DwCtx) { + DebugLineTableRowRef RowRef = + DebugLineTableRowRef::fromSMLoc(Instruction.getLoc()); + if (RowRef == DebugLineTableRowRef::NULL_ROW) + return; + + const DWARFDebugLine::LineTable *LineTable; + if (Function && Function->getDWARFUnit() && + Function->getDWARFUnit()->getOffset() == RowRef.DwCompileUnitIndex) { + LineTable = Function->getDWARFLineTable(); + } else { + LineTable = DwCtx->getLineTableForUnit( + DwCtx->getCompileUnitForOffset(RowRef.DwCompileUnitIndex)); + } + assert(LineTable && "line table expected for instruction with debug info"); + + const DWARFDebugLine::Row &Row = LineTable->Rows[RowRef.RowIndex - 1]; + StringRef FileName = ""; + if (Optional FName = + dwarf::toString(LineTable->Prologue.FileNames[Row.File - 1].Name)) + FileName = *FName; + OS << " # debug line " << FileName << ":" << Row.Line; + if (Row.Column) + OS << ":" << Row.Column; + if (Row.Discriminator) + OS << " discriminator:" << Row.Discriminator; +} + void BinaryContext::printInstruction(raw_ostream &OS, const MCInst &Instruction, uint64_t Offset, const BinaryFunction *Function, @@ -1686,33 +1750,8 @@ void BinaryContext::printInstruction(raw_ostream &OS, const MCInst &Instruction, MIB->printAnnotations(Instruction, OS); - if (opts::PrintDebugInfo) { - DebugLineTableRowRef RowRef = - DebugLineTableRowRef::fromSMLoc(Instruction.getLoc()); - if (RowRef != DebugLineTableRowRef::NULL_ROW) { - const DWARFDebugLine::LineTable *LineTable; - if (Function && Function->getDWARFUnit() && - Function->getDWARFUnit()->getOffset() == RowRef.DwCompileUnitIndex) { - LineTable = Function->getDWARFLineTable(); - } else { - LineTable = DwCtx->getLineTableForUnit( - DwCtx->getCompileUnitForOffset(RowRef.DwCompileUnitIndex)); - } - assert(LineTable && - "line table expected for instruction with debug info"); - - const DWARFDebugLine::Row &Row = LineTable->Rows[RowRef.RowIndex - 1]; - StringRef FileName = ""; - if (Optional FName = - dwarf::toString(LineTable->Prologue.FileNames[Row.File - 1].Name)) - FileName = *FName; - OS << " # debug line " << FileName << ":" << Row.Line; - if (Row.Column) - OS << ":" << Row.Column; - if (Row.Discriminator) - OS << " discriminator:" << Row.Discriminator; - } - } + if (opts::PrintDebugInfo) + printDebugInfo(OS, Instruction, Function, DwCtx.get()); if ((opts::PrintRelocations || PrintRelocations) && Function) { const uint64_t Size = computeCodeSize(&Instruction, &Instruction + 1); @@ -2033,7 +2072,7 @@ BinaryContext::calculateEmittedSize(BinaryFunction &BF, bool FixBranches) { MCSymbol *ColdStartLabel = LocalCtx->createTempSymbol(); MCSymbol *ColdEndLabel = LocalCtx->createTempSymbol(); - Streamer->SwitchSection(Section); + Streamer->switchSection(Section); Streamer->emitLabel(StartLabel); emitFunctionBody(*Streamer, BF, /*EmitColdPart=*/false, /*EmitCodeOnly=*/true); @@ -2045,14 +2084,14 @@ BinaryContext::calculateEmittedSize(BinaryFunction &BF, bool FixBranches) { ELF::SHF_EXECINSTR | ELF::SHF_ALLOC); ColdSection->setHasInstructions(true); - Streamer->SwitchSection(ColdSection); + Streamer->switchSection(ColdSection); Streamer->emitLabel(ColdStartLabel); emitFunctionBody(*Streamer, BF, /*EmitColdPart=*/true, /*EmitCodeOnly=*/true); Streamer->emitLabel(ColdEndLabel); // To avoid calling MCObjectStreamer::flushPendingLabels() which is private Streamer->emitBytes(StringRef("")); - Streamer->SwitchSection(Section); + Streamer->switchSection(Section); } // To avoid calling MCObjectStreamer::flushPendingLabels() which is private or diff --git a/bolt/lib/Core/BinaryData.cpp b/bolt/lib/Core/BinaryData.cpp index d8f59573af67d..f963406c17d58 100644 --- a/bolt/lib/Core/BinaryData.cpp +++ b/bolt/lib/Core/BinaryData.cpp @@ -25,11 +25,9 @@ extern cl::OptionCategory BoltCategory; extern cl::opt Verbosity; cl::opt -PrintSymbolAliases("print-aliases", - cl::desc("print aliases when printing objects"), - cl::Hidden, - cl::ZeroOrMore, - cl::cat(BoltCategory)); + PrintSymbolAliases("print-aliases", + cl::desc("print aliases when printing objects"), + cl::Hidden, cl::cat(BoltCategory)); } bool BinaryData::isAbsolute() const { return Flags & SymbolRef::SF_Absolute; } diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp index f923f6f28ade9..ce79668847768 100644 --- a/bolt/lib/Core/BinaryEmitter.cpp +++ b/bolt/lib/Core/BinaryEmitter.cpp @@ -34,12 +34,8 @@ namespace opts { extern cl::opt JumpTables; extern cl::opt PreserveBlocksAlignment; -cl::opt -AlignBlocks("align-blocks", - cl::desc("align basic blocks"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); +cl::opt AlignBlocks("align-blocks", cl::desc("align basic blocks"), + cl::cat(BoltOptCategory)); cl::opt AlignMacroOpFusion("align-macro-fusion", @@ -70,20 +66,15 @@ FunctionPadSpec("pad-funcs", cl::Hidden, cl::cat(BoltCategory)); -static cl::opt -MarkFuncs("mark-funcs", - cl::desc("mark function boundaries with break instruction to make " - "sure we accidentally don't cross them"), - cl::ReallyHidden, - cl::ZeroOrMore, - cl::cat(BoltCategory)); +static cl::opt MarkFuncs( + "mark-funcs", + cl::desc("mark function boundaries with break instruction to make " + "sure we accidentally don't cross them"), + cl::ReallyHidden, cl::cat(BoltCategory)); -static cl::opt -PrintJumpTables("print-jump-tables", - cl::desc("print jump tables"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); +static cl::opt PrintJumpTables("print-jump-tables", + cl::desc("print jump tables"), cl::Hidden, + cl::cat(BoltCategory)); static cl::opt X86AlignBranchBoundaryHotOnly("x86-align-branch-boundary-hot-only", @@ -258,7 +249,7 @@ void BinaryEmitter::emitFunctions() { // Mark the start of hot text. if (opts::HotText) { - Streamer.SwitchSection(BC.getTextSection()); + Streamer.switchSection(BC.getTextSection()); Streamer.emitLabel(BC.getHotTextStartSymbol()); } @@ -271,7 +262,7 @@ void BinaryEmitter::emitFunctions() { // Mark the end of hot text. if (opts::HotText) { - Streamer.SwitchSection(BC.getTextSection()); + Streamer.switchSection(BC.getTextSection()); Streamer.emitLabel(BC.getHotTextEndSymbol()); } } @@ -286,7 +277,7 @@ bool BinaryEmitter::emitFunction(BinaryFunction &Function, bool EmitColdPart) { MCSection *Section = BC.getCodeSection(EmitColdPart ? Function.getColdCodeSectionName() : Function.getCodeSectionName()); - Streamer.SwitchSection(Section); + Streamer.switchSection(Section); Section->setHasInstructions(true); BC.Ctx->addGenDwarfSection(Section); @@ -328,10 +319,9 @@ bool BinaryEmitter::emitFunction(BinaryFunction &Function, bool EmitColdPart) { // Emit CFI start if (Function.hasCFI()) { Streamer.emitCFIStartProc(/*IsSimple=*/false); - if (Function.getPersonalityFunction() != nullptr) { + if (Function.getPersonalityFunction() != nullptr) Streamer.emitCFIPersonality(Function.getPersonalityFunction(), Function.getPersonalityEncoding()); - } MCSymbol *LSDASymbol = EmitColdPart ? Function.getColdLSDASymbol() : Function.getLSDASymbol(); if (LSDASymbol) @@ -414,10 +404,9 @@ void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, bool EmitColdPart, continue; if ((opts::AlignBlocks || opts::PreserveBlocksAlignment) && - BB->getAlignment() > 1) { + BB->getAlignment() > 1) Streamer.emitCodeAlignment(BB->getAlignment(), &*BC.STI, BB->getAlignmentMaxBytes()); - } Streamer.emitLabel(BB->getLabel()); if (!EmitCodeOnly) { if (MCSymbol *EntrySymbol = BF.getSecondaryEntryPointSymbol(*BB)) @@ -540,15 +529,14 @@ void BinaryEmitter::emitConstantIslands(BinaryFunction &BF, bool EmitColdPart, auto NextData = std::next(DataIter); auto CodeIter = Islands.CodeOffsets.lower_bound(*DataIter); if (CodeIter == Islands.CodeOffsets.end() && - NextData == Islands.DataOffsets.end()) { + NextData == Islands.DataOffsets.end()) EndOffset = BF.getMaxSize(); - } else if (CodeIter == Islands.CodeOffsets.end()) { + else if (CodeIter == Islands.CodeOffsets.end()) EndOffset = *NextData; - } else if (NextData == Islands.DataOffsets.end()) { + else if (NextData == Islands.DataOffsets.end()) EndOffset = *CodeIter; - } else { + else EndOffset = (*CodeIter > *NextData) ? *NextData : *CodeIter; - } if (FunctionOffset == EndOffset) continue; // Size is zero, nothing to emit @@ -783,7 +771,7 @@ void BinaryEmitter::emitJumpTable(const JumpTable &JT, MCSection *HotSection, } LabelCounts[CurrentLabel] = CurrentLabelCount; } else { - Streamer.SwitchSection(JT.Count > 0 ? HotSection : ColdSection); + Streamer.switchSection(JT.Count > 0 ? HotSection : ColdSection); Streamer.emitValueToAlignment(JT.EntrySize); } MCSymbol *LastLabel = nullptr; @@ -800,9 +788,9 @@ void BinaryEmitter::emitJumpTable(const JumpTable &JT, MCSection *HotSection, LLVM_DEBUG(dbgs() << "BOLT-DEBUG: jump table count: " << LabelCounts[LI->second] << '\n'); if (LabelCounts[LI->second] > 0) - Streamer.SwitchSection(HotSection); + Streamer.switchSection(HotSection); else - Streamer.SwitchSection(ColdSection); + Streamer.switchSection(ColdSection); Streamer.emitValueToAlignment(JT.EntrySize); } Streamer.emitLabel(LI->second); @@ -874,9 +862,8 @@ void BinaryEmitter::emitCFIInstruction(const MCCFIInstruction &Inst) const { void BinaryEmitter::emitLSDA(BinaryFunction &BF, bool EmitColdPart) { const BinaryFunction::CallSitesType *Sites = EmitColdPart ? &BF.getColdCallSites() : &BF.getCallSites(); - if (Sites->empty()) { + if (Sites->empty()) return; - } // Calculate callsite table size. Size of each callsite entry is: // @@ -886,11 +873,10 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, bool EmitColdPart) { // // sizeof(dwarf::DW_EH_PE_data4) * 3 + sizeof(uleb128(action)) uint64_t CallSiteTableLength = Sites->size() * 4 * 3; - for (const BinaryFunction::CallSite &CallSite : *Sites) { + for (const BinaryFunction::CallSite &CallSite : *Sites) CallSiteTableLength += getULEB128Size(CallSite.Action); - } - Streamer.SwitchSection(BC.MOFI->getLSDASection()); + Streamer.switchSection(BC.MOFI->getLSDASection()); const unsigned TTypeEncoding = BC.TTypeEncoding; const unsigned TTypeEncodingSize = BC.getDWARFEncodingSize(TTypeEncoding); diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp index 157d5d9c5d779..8ff29b6c17af0 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -64,23 +64,18 @@ extern cl::opt Verbosity; extern bool processAllFunctions(); -cl::opt -CheckEncoding("check-encoding", - cl::desc("perform verification of LLVM instruction encoding/decoding. " - "Every instruction in the input is decoded and re-encoded. " - "If the resulting bytes do not match the input, a warning message " - "is printed."), - cl::init(false), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); - -static cl::opt -DotToolTipCode("dot-tooltip-code", - cl::desc("add basic block instructions as tool tips on nodes"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); +cl::opt CheckEncoding( + "check-encoding", + cl::desc("perform verification of LLVM instruction encoding/decoding. " + "Every instruction in the input is decoded and re-encoded. " + "If the resulting bytes do not match the input, a warning message " + "is printed."), + cl::Hidden, cl::cat(BoltCategory)); + +static cl::opt DotToolTipCode( + "dot-tooltip-code", + cl::desc("add basic block instructions as tool tips on nodes"), cl::Hidden, + cl::cat(BoltCategory)); cl::opt JumpTables("jump-tables", @@ -102,21 +97,17 @@ JumpTables("jump-tables", cl::ZeroOrMore, cl::cat(BoltOptCategory)); -static cl::opt -NoScan("no-scan", - cl::desc("do not scan cold functions for external references (may result in " - "slower binary)"), - cl::init(false), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); +static cl::opt NoScan( + "no-scan", + cl::desc( + "do not scan cold functions for external references (may result in " + "slower binary)"), + cl::Hidden, cl::cat(BoltOptCategory)); cl::opt -PreserveBlocksAlignment("preserve-blocks-alignment", - cl::desc("try to preserve basic block alignment"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); + PreserveBlocksAlignment("preserve-blocks-alignment", + cl::desc("try to preserve basic block alignment"), + cl::cat(BoltOptCategory)); cl::opt PrintDynoStats("dyno-stats", @@ -139,11 +130,9 @@ PrintOnly("print-only", cl::cat(BoltCategory)); cl::opt -TimeBuild("time-build", - cl::desc("print time spent constructing binary functions"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); + TimeBuild("time-build", + cl::desc("print time spent constructing binary functions"), + cl::Hidden, cl::cat(BoltCategory)); cl::opt TrapOnAVX512("trap-avx512", @@ -1028,6 +1017,8 @@ bool BinaryFunction::disassemble() { auto &Ctx = BC.Ctx; auto &MIB = BC.MIB; + BC.SymbolicDisAsm->setSymbolizer(MIB->createTargetSymbolizer(*this)); + // Insert a label at the beginning of the function. This will be our first // basic block. Labels[0] = Ctx->createNamedTempSymbol("BB0"); @@ -1201,9 +1192,9 @@ bool BinaryFunction::disassemble() { continue; } - if (!BC.DisAsm->getInstruction(Instruction, Size, - FunctionData.slice(Offset), - AbsoluteInstrAddr, nulls())) { + if (!BC.SymbolicDisAsm->getInstruction(Instruction, Size, + FunctionData.slice(Offset), + AbsoluteInstrAddr, nulls())) { // Functions with "soft" boundaries, e.g. coming from assembly source, // can have 0-byte padding at the end. if (isZeroPaddingAt(Offset)) @@ -1243,12 +1234,16 @@ bool BinaryFunction::disassemble() { break; } - // Check if our disassembly is correct and matches the assembler output. - if (!BC.validateEncoding(Instruction, FunctionData.slice(Offset, Size))) { - if (opts::Verbosity >= 1) { + // Disassemble again without the symbolizer and check that the disassembly + // matches the assembler output. + MCInst TempInst; + BC.DisAsm->getInstruction(TempInst, Size, FunctionData.slice(Offset), + AbsoluteInstrAddr, nulls()); + if (!BC.validateEncoding(TempInst, FunctionData.slice(Offset, Size))) { + if (opts::Verbosity >= 0) { errs() << "BOLT-WARNING: internal assembler/disassembler error " "detected for AVX512 instruction:\n"; - BC.printInstruction(errs(), Instruction, AbsoluteInstrAddr); + BC.printInstruction(errs(), TempInst, AbsoluteInstrAddr); errs() << " in function " << *this << '\n'; } @@ -1341,71 +1336,24 @@ bool BinaryFunction::disassemble() { if (BC.isAArch64()) handleAArch64IndirectCall(Instruction, Offset); } - } else { + } else if (BC.isAArch64()) { // Check if there's a relocation associated with this instruction. bool UsedReloc = false; for (auto Itr = Relocations.lower_bound(Offset), ItrE = Relocations.lower_bound(Offset + Size); Itr != ItrE; ++Itr) { const Relocation &Relocation = Itr->second; - uint64_t SymbolValue = Relocation.Value - Relocation.Addend; - if (Relocation.isPCRelative()) - SymbolValue += getAddress() + Relocation.Offset; - - // Process reference to the symbol. - if (BC.isX86()) - BC.handleAddressRef(SymbolValue, *this, Relocation.isPCRelative()); - - if (BC.isAArch64() || !Relocation.isPCRelative()) { - int64_t Value = Relocation.Value; - const bool Result = BC.MIB->replaceImmWithSymbolRef( - Instruction, Relocation.Symbol, Relocation.Addend, Ctx.get(), - Value, Relocation.Type); - (void)Result; - assert(Result && "cannot replace immediate with relocation"); - - if (BC.isX86()) { - // Make sure we replaced the correct immediate (instruction - // can have multiple immediate operands). - assert( - truncateToSize(static_cast(Value), - Relocation::getSizeForType(Relocation.Type)) == - truncateToSize(Relocation.Value, Relocation::getSizeForType( - Relocation.Type)) && - "immediate value mismatch in function"); - } else if (BC.isAArch64()) { - // For aarch, if we replaced an immediate with a symbol from a - // relocation, we mark it so we do not try to further process a - // pc-relative operand. All we need is the symbol. - UsedReloc = true; - } - } else { - // Check if the relocation matches memop's Disp. - uint64_t TargetAddress; - if (!BC.MIB->evaluateMemOperandTarget(Instruction, TargetAddress, - AbsoluteInstrAddr, Size)) { - errs() << "BOLT-ERROR: PC-relative operand can't be evaluated\n"; - exit(1); - } - assert(TargetAddress == Relocation.Value + AbsoluteInstrAddr + Size && - "Immediate value mismatch detected."); - - const MCExpr *Expr = MCSymbolRefExpr::create( - Relocation.Symbol, MCSymbolRefExpr::VK_None, *BC.Ctx); - // Real addend for pc-relative targets is adjusted with a delta - // from relocation placement to the next instruction. - const uint64_t TargetAddend = - Relocation.Addend + Offset + Size - Relocation.Offset; - if (TargetAddend) { - const MCConstantExpr *Offset = - MCConstantExpr::create(TargetAddend, *BC.Ctx); - Expr = MCBinaryExpr::createAdd(Expr, Offset, *BC.Ctx); - } - BC.MIB->replaceMemOperandDisp( - Instruction, MCOperand::createExpr(BC.MIB->getTargetExprFor( - Instruction, Expr, *BC.Ctx, 0))); - UsedReloc = true; - } + int64_t Value = Relocation.Value; + const bool Result = BC.MIB->replaceImmWithSymbolRef( + Instruction, Relocation.Symbol, Relocation.Addend, Ctx.get(), Value, + Relocation.Type); + (void)Result; + assert(Result && "cannot replace immediate with relocation"); + + // For aarch64, if we replaced an immediate with a symbol from a + // relocation, we mark it so we do not try to further process a + // pc-relative operand. All we need is the symbol. + UsedReloc = true; } if (MIB->hasPCRelOperand(Instruction) && !UsedReloc) @@ -1432,6 +1380,12 @@ bool BinaryFunction::disassemble() { addInstruction(Offset, std::move(Instruction)); } + // Reset symbolizer for the disassembler. + BC.SymbolicDisAsm->setSymbolizer(nullptr); + + if (uint64_t Offset = getFirstInstructionOffset()) + Labels[Offset] = BC.Ctx->createNamedTempSymbol(); + clearList(Relocations); if (!IsSimple) { @@ -1944,7 +1898,7 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) { return false; assert(BasicBlocks.empty() && "basic block list should be empty"); - assert((Labels.find(0) != Labels.end()) && + assert((Labels.find(getFirstInstructionOffset()) != Labels.end()) && "first instruction should always have a label"); // Create basic blocks in the original layout order: @@ -2048,9 +2002,9 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) { updateOffset(LastInstrOffset); } } - if (Offset == 0) { - // Add associated CFI pseudos in the first offset (0) - addCFIPlaceholders(0, InsertBB); + if (Offset == getFirstInstructionOffset()) { + // Add associated CFI pseudos in the first offset + addCFIPlaceholders(Offset, InsertBB); } const bool IsBlockEnd = MIB->isTerminator(Instr); @@ -3045,28 +2999,49 @@ std::string formatEscapes(const std::string &Str) { } // namespace void BinaryFunction::dumpGraph(raw_ostream &OS) const { - OS << "strict digraph \"" << getPrintName() << "\" {\n"; + OS << "digraph \"" << getPrintName() << "\" {\n" + << "node [fontname=courier, shape=box, style=filled, colorscheme=brbg9]\n"; uint64_t Offset = Address; for (BinaryBasicBlock *BB : BasicBlocks) { auto LayoutPos = std::find(BasicBlocksLayout.begin(), BasicBlocksLayout.end(), BB); unsigned Layout = LayoutPos - BasicBlocksLayout.begin(); const char *ColdStr = BB->isCold() ? " (cold)" : ""; - OS << format("\"%s\" [label=\"%s%s\\n(C:%lu,O:%lu,I:%u,L:%u:CFI:%u)\"]\n", + std::vector Attrs; + // Bold box for entry points + if (isEntryPoint(*BB)) + Attrs.push_back("penwidth=2"); + if (BLI && BLI->getLoopFor(BB)) { + // Distinguish innermost loops + const BinaryLoop *Loop = BLI->getLoopFor(BB); + if (Loop->isInnermost()) + Attrs.push_back("fillcolor=6"); + else // some outer loop + Attrs.push_back("fillcolor=4"); + } else { // non-loopy code + Attrs.push_back("fillcolor=5"); + } + ListSeparator LS; + OS << "\"" << BB->getName() << "\" ["; + for (StringRef Attr : Attrs) + OS << LS << Attr; + OS << "]\n"; + OS << format("\"%s\" [label=\"%s%s\\n(C:%lu,O:%lu,I:%u,L:%u,CFI:%u)\\n", BB->getName().data(), BB->getName().data(), ColdStr, - (BB->ExecutionCount != BinaryBasicBlock::COUNT_NO_PROFILE - ? BB->ExecutionCount - : 0), - BB->getOffset(), getIndex(BB), Layout, BB->getCFIState()); - OS << format("\"%s\" [shape=box]\n", BB->getName().data()); + BB->getKnownExecutionCount(), BB->getOffset(), getIndex(BB), + Layout, BB->getCFIState()); + if (opts::DotToolTipCode) { std::string Str; raw_string_ostream CS(Str); - Offset = BC.printInstructions(CS, BB->begin(), BB->end(), Offset, this); - const std::string Code = formatEscapes(CS.str()); - OS << format("\"%s\" [tooltip=\"%s\"]\n", BB->getName().data(), - Code.c_str()); + Offset = BC.printInstructions(CS, BB->begin(), BB->end(), Offset, this, + /* PrintMCInst = */ false, + /* PrintMemData = */ false, + /* PrintRelocations = */ false, + /* Endl = */ R"(\\l)"); + OS << formatEscapes(CS.str()) << '\n'; } + OS << "\"]\n"; // analyzeBranch is just used to get the names of the branch // opcodes. @@ -3926,33 +3901,6 @@ void BinaryFunction::deleteConservativeEdges() { } } -bool BinaryFunction::isDataMarker(const SymbolRef &Symbol, - uint64_t SymbolSize) const { - // For aarch64, the ABI defines mapping symbols so we identify data in the - // code section (see IHI0056B). $d identifies a symbol starting data contents. - if (BC.isAArch64() && Symbol.getType() && - cantFail(Symbol.getType()) == SymbolRef::ST_Unknown && SymbolSize == 0 && - Symbol.getName() && - (cantFail(Symbol.getName()) == "$d" || - cantFail(Symbol.getName()).startswith("$d."))) - return true; - return false; -} - -bool BinaryFunction::isCodeMarker(const SymbolRef &Symbol, - uint64_t SymbolSize) const { - // For aarch64, the ABI defines mapping symbols so we identify data in the - // code section (see IHI0056B). $x identifies a symbol starting code or the - // end of a data chunk inside code. - if (BC.isAArch64() && Symbol.getType() && - cantFail(Symbol.getType()) == SymbolRef::ST_Unknown && SymbolSize == 0 && - Symbol.getName() && - (cantFail(Symbol.getName()) == "$x" || - cantFail(Symbol.getName()).startswith("$x."))) - return true; - return false; -} - bool BinaryFunction::isSymbolValidInScope(const SymbolRef &Symbol, uint64_t SymbolSize) const { // If this symbol is in a different section from the one where the @@ -3963,7 +3911,7 @@ bool BinaryFunction::isSymbolValidInScope(const SymbolRef &Symbol, // Some symbols are tolerated inside function bodies, others are not. // The real function boundaries may not be known at this point. - if (isDataMarker(Symbol, SymbolSize) || isCodeMarker(Symbol, SymbolSize)) + if (BC.isMarker(Symbol)) return true; // It's okay to have a zero-sized symbol in the middle of non-zero-sized diff --git a/bolt/lib/Core/BinaryFunctionProfile.cpp b/bolt/lib/Core/BinaryFunctionProfile.cpp index c6dc87b68f0f1..a8d36a93ce52a 100644 --- a/bolt/lib/Core/BinaryFunctionProfile.cpp +++ b/bolt/lib/Core/BinaryFunctionProfile.cpp @@ -40,29 +40,20 @@ cl::opt ICP( extern cl::opt JumpTables; -static cl::opt -FixFuncCounts("fix-func-counts", - cl::desc("adjust function counts based on basic blocks execution count"), - cl::init(false), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); +static cl::opt FixFuncCounts( + "fix-func-counts", + cl::desc("adjust function counts based on basic blocks execution count"), + cl::Hidden, cl::cat(BoltOptCategory)); -static cl::opt -FixBlockCounts("fix-block-counts", - cl::desc("adjust block counts based on outgoing branch counts"), - cl::init(true), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); +static cl::opt FixBlockCounts( + "fix-block-counts", + cl::desc("adjust block counts based on outgoing branch counts"), + cl::init(true), cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt -InferFallThroughs("infer-fall-throughs", - cl::desc("infer execution count for fall-through blocks"), - cl::init(false), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); + InferFallThroughs("infer-fall-throughs", + cl::desc("infer execution count for fall-through blocks"), + cl::Hidden, cl::cat(BoltOptCategory)); } // namespace opts diff --git a/bolt/lib/Core/BinarySection.cpp b/bolt/lib/Core/BinarySection.cpp index 4d8c98868e9a6..dc0e80c36cffa 100644 --- a/bolt/lib/Core/BinarySection.cpp +++ b/bolt/lib/Core/BinarySection.cpp @@ -71,7 +71,7 @@ void BinarySection::emitAsData(MCStreamer &Streamer, StringRef NewName) const { MCSectionELF *ELFSection = BC.Ctx->getELFSection(SectionName, getELFType(), getELFFlags()); - Streamer.SwitchSection(ELFSection); + Streamer.switchSection(ELFSection); Streamer.emitValueToAlignment(getAlignment()); if (BC.HasRelocations && opts::HotData && isReordered()) diff --git a/bolt/lib/Core/CMakeLists.txt b/bolt/lib/Core/CMakeLists.txt index 8184f25112b87..d5ccfa8d23569 100644 --- a/bolt/lib/Core/CMakeLists.txt +++ b/bolt/lib/Core/CMakeLists.txt @@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS DebugInfoDWARF Demangle MC + MCDisassembler Object Support ) diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp index ac2e6cc497878..767df183b1478 100644 --- a/bolt/lib/Core/DebugData.cpp +++ b/bolt/lib/Core/DebugData.cpp @@ -42,11 +42,6 @@ class MCSymbol; namespace bolt { -/// Finds attributes FormValue and Offset. -/// -/// \param DIE die to look up in. -/// \param Index the attribute index to extract. -/// \return an optional AttrInfo with DWARFFormValue and Offset. Optional findAttributeInfo(const DWARFDie DIE, const DWARFAbbreviationDeclaration *AbbrevDecl, @@ -75,8 +70,21 @@ findAttributeInfo(const DWARFDie DIE, // location. ValSize = NewOffset - Offset; } + return AttrInfo{*Value, DIE.getAbbreviationDeclarationPtr(), Offset, ValSize}; +} - return AttrInfo{*Value, Offset, ValSize}; +Optional findAttributeInfo(const DWARFDie DIE, + dwarf::Attribute Attr) { + if (!DIE.isValid()) + return None; + const DWARFAbbreviationDeclaration *AbbrevDecl = + DIE.getAbbreviationDeclarationPtr(); + if (!AbbrevDecl) + return None; + Optional Index = AbbrevDecl->findAttributeIndex(Attr); + if (!Index) + return None; + return findAttributeInfo(DIE, AbbrevDecl, *Index); } const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0}; @@ -496,20 +504,30 @@ uint64_t DebugAddrWriterDwarf5::getOffset(DWARFUnit &Unit) { return Iter->second; } -DebugLocWriter::DebugLocWriter(BinaryContext *BC) { +void DebugLocWriter::init() { LocBuffer = std::make_unique(); LocStream = std::make_unique(*LocBuffer); + // Writing out empty location list to which all references to empty location + // lists will point. + if (!LocSectionOffset && DwarfVersion < 5) { + const char Zeroes[16] = {0}; + *LocStream << StringRef(Zeroes, 16); + LocSectionOffset += 16; + } } -void DebugLocWriter::addList(uint64_t AttrOffset, uint32_t LocListIndex, - DebugLocationsVector &&LocList) { +uint32_t DebugLocWriter::LocSectionOffset = 0; +void DebugLocWriter::addList(AttrInfo &AttrVal, DebugLocationsVector &LocList, + DebugInfoBinaryPatcher &DebugInfoPatcher, + DebugAbbrevWriter &AbbrevWriter) { + const uint64_t AttrOffset = AttrVal.Offset; if (LocList.empty()) { - EmptyAttrLists.push_back(AttrOffset); + DebugInfoPatcher.addLE32Patch(AttrOffset, DebugLocWriter::EmptyListOffset); return; } // Since there is a separate DebugLocWriter for each thread, // we don't need a lock to read the SectionOffset and update it. - const uint32_t EntryOffset = SectionOffset; + const uint32_t EntryOffset = LocSectionOffset; for (const DebugLocationEntry &Entry : LocList) { support::endian::write(*LocStream, static_cast(Entry.LowPC), @@ -520,16 +538,12 @@ void DebugLocWriter::addList(uint64_t AttrOffset, uint32_t LocListIndex, support::little); *LocStream << StringRef(reinterpret_cast(Entry.Expr.data()), Entry.Expr.size()); - SectionOffset += 2 * 8 + 2 + Entry.Expr.size(); + LocSectionOffset += 2 * 8 + 2 + Entry.Expr.size(); } LocStream->write_zeros(16); - SectionOffset += 16; + LocSectionOffset += 16; LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset}); -} - -void DebugLoclistWriter::addList(uint64_t AttrOffset, uint32_t LocListIndex, - DebugLocationsVector &&LocList) { - Patches.push_back({AttrOffset, LocListIndex, std::move(LocList)}); + DebugInfoPatcher.addLE32Patch(AttrOffset, EntryOffset); } std::unique_ptr DebugLocWriter::getBuffer() { @@ -537,18 +551,8 @@ std::unique_ptr DebugLocWriter::getBuffer() { } // DWARF 4: 2.6.2 -void DebugLocWriter::finalize(uint64_t SectionOffset, - SimpleBinaryPatcher &DebugInfoPatcher) { - for (const auto LocListDebugInfoPatchType : LocListDebugInfoPatches) { - uint64_t Offset = SectionOffset + LocListDebugInfoPatchType.LocListOffset; - DebugInfoPatcher.addLE32Patch(LocListDebugInfoPatchType.DebugInfoAttrOffset, - Offset); - } - - for (uint64_t DebugInfoAttrOffset : EmptyAttrLists) - DebugInfoPatcher.addLE32Patch(DebugInfoAttrOffset, - DebugLocWriter::EmptyListOffset); -} +void DebugLocWriter::finalize(DebugInfoBinaryPatcher &DebugInfoPatcher, + DebugAbbrevWriter &AbbrevWriter) {} static void writeEmptyListDwarf5(raw_svector_ostream &Stream) { support::endian::write(Stream, static_cast(4), support::little); @@ -562,123 +566,138 @@ static void writeEmptyListDwarf5(raw_svector_ostream &Stream) { Stream, static_cast(dwarf::DW_LLE_end_of_list), support::little); } -void DebugLoclistWriter::finalizeDWARF5(uint64_t SectionOffset, - SimpleBinaryPatcher &DebugInfoPatcher) { +static void writeLegacyLocList(AttrInfo &AttrVal, DebugLocationsVector &LocList, + DebugInfoBinaryPatcher &DebugInfoPatcher, + DebugAddrWriter &AddrWriter, + DebugBufferVector &LocBuffer, DWARFUnit &CU, + raw_svector_ostream &LocStream) { + const uint64_t AttrOffset = AttrVal.Offset; + if (LocList.empty()) { + DebugInfoPatcher.addLE32Patch(AttrOffset, DebugLocWriter::EmptyListOffset); + return; + } + + const uint32_t EntryOffset = LocBuffer.size(); + for (const DebugLocationEntry &Entry : LocList) { + support::endian::write(LocStream, + static_cast(dwarf::DW_LLE_startx_length), + support::little); + const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU); + encodeULEB128(Index, LocStream); - std::unique_ptr LocArrayBuffer = - std::make_unique(); - std::unique_ptr LocArrayStream = - std::make_unique(*LocArrayBuffer); - std::unique_ptr LocBodyBuffer = - std::make_unique(); - std::unique_ptr LocBodyStream = - std::make_unique(*LocBodyBuffer); + support::endian::write(LocStream, + static_cast(Entry.HighPC - Entry.LowPC), + support::little); + support::endian::write(LocStream, static_cast(Entry.Expr.size()), + support::little); + LocStream << StringRef(reinterpret_cast(Entry.Expr.data()), + Entry.Expr.size()); + } + support::endian::write(LocStream, + static_cast(dwarf::DW_LLE_end_of_list), + support::little); + DebugInfoPatcher.addLE32Patch(AttrOffset, EntryOffset); +} - const uint32_t SizeOfArraySection = Patches.size() * sizeof(uint32_t); - std::sort(Patches.begin(), Patches.end(), - [](const LocPatch &P1, const LocPatch &P2) -> bool { - return P1.Index < P2.Index; - }); +static void writeDWARF5LocList( + uint32_t &NumberOfEntries, AttrInfo &AttrVal, DebugLocationsVector &LocList, + DebugInfoBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter, + DebugAddrWriter &AddrWriter, DebugBufferVector &LocBodyBuffer, + std::vector &RelativeLocListOffsets, DWARFUnit &CU, + raw_svector_ostream &LocBodyStream) { + if (AttrVal.V.getForm() != dwarf::DW_FORM_loclistx) { + AbbrevWriter.addAttributePatch(CU, AttrVal.AbbrevDecl, + dwarf::DW_AT_location, dwarf::DW_AT_location, + dwarf::DW_FORM_loclistx); + } + DebugInfoPatcher.addUDataPatch(AttrVal.Offset, NumberOfEntries, AttrVal.Size); + RelativeLocListOffsets.push_back(LocBodyBuffer.size()); + ++NumberOfEntries; + if (LocList.empty()) { + writeEmptyListDwarf5(LocBodyStream); + return; + } - if (LocListsBaseAttrOffset != InvalidLocListsBaseAttrOffset) - DebugInfoPatcher.addLE32Patch(LocListsBaseAttrOffset, - SectionOffset + - getDWARF5RngListLocListHeaderSize()); + std::vector OffsetsArray; + for (const DebugLocationEntry &Entry : LocList) { + support::endian::write(LocBodyStream, + static_cast(dwarf::DW_LLE_startx_length), + support::little); + const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU); + encodeULEB128(Index, LocBodyStream); + encodeULEB128(Entry.HighPC - Entry.LowPC, LocBodyStream); + encodeULEB128(Entry.Expr.size(), LocBodyStream); + LocBodyStream << StringRef( + reinterpret_cast(Entry.Expr.data()), Entry.Expr.size()); + } + support::endian::write(LocBodyStream, + static_cast(dwarf::DW_LLE_end_of_list), + support::little); +} - uint32_t Index{0}; - for (LocPatch &Patch : Patches) { - const uint32_t EntryOffset = LocBodyBuffer->size(); - if (Patch.LocList.empty()) { - if (Patch.Index == DebugLoclistWriter::InvalidIndex) - DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset); +void DebugLoclistWriter::addList(AttrInfo &AttrVal, + DebugLocationsVector &LocList, + DebugInfoBinaryPatcher &DebugInfoPatcher, + DebugAbbrevWriter &AbbrevWriter) { + if (DwarfVersion < 5) + writeLegacyLocList(AttrVal, LocList, DebugInfoPatcher, *AddrWriter, + *LocBuffer, CU, *LocStream); + else + writeDWARF5LocList(NumberOfEntries, AttrVal, LocList, DebugInfoPatcher, + AbbrevWriter, *AddrWriter, *LocBodyBuffer, + RelativeLocListOffsets, CU, *LocBodyStream); +} - writeEmptyListDwarf5(*LocBodyStream); - continue; - } +uint32_t DebugLoclistWriter::LoclistBaseOffset = 0; +void DebugLoclistWriter::finalizeDWARF5( + DebugInfoBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter) { + if (LocBodyBuffer->empty()) + return; - assert(Patch.Index == DebugLoclistWriter::InvalidIndex || - Patch.Index == Index++ && "Gap in LocList Index Array."); - (void)Index; - - std::vector OffsetsArray; - for (const DebugLocationEntry &Entry : Patch.LocList) { - support::endian::write(*LocBodyStream, - static_cast(dwarf::DW_LLE_startx_length), - support::little); - const uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, CU); - encodeULEB128(Index, *LocBodyStream); - encodeULEB128(Entry.HighPC - Entry.LowPC, *LocBodyStream); - encodeULEB128(Entry.Expr.size(), *LocBodyStream); - *LocBodyStream << StringRef( - reinterpret_cast(Entry.Expr.data()), Entry.Expr.size()); - } - support::endian::write(*LocBodyStream, - static_cast(dwarf::DW_LLE_end_of_list), - support::little); + std::unique_ptr LocArrayBuffer = + std::make_unique(); + std::unique_ptr LocArrayStream = + std::make_unique(*LocArrayBuffer); - // Write out IndexArray + const uint32_t SizeOfArraySection = NumberOfEntries * sizeof(uint32_t); + // Write out IndexArray + for (uint32_t RelativeOffset : RelativeLocListOffsets) support::endian::write( *LocArrayStream, - static_cast(SizeOfArraySection + EntryOffset), + static_cast(SizeOfArraySection + RelativeOffset), support::little); - // Don't need to patch Index since we are re-using them. - if (Patch.Index == DebugLoclistWriter::InvalidIndex) - DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset); - clearList(Patch.LocList); - } - if (!Patches.empty()) { - std::unique_ptr Header = - getDWARF5Header({static_cast(SizeOfArraySection + - LocBodyBuffer.get()->size()), - 5, 8, 0, static_cast(Patches.size())}); - *LocStream << *Header; - *LocStream << *LocArrayBuffer; - *LocStream << *LocBodyBuffer; - } - clearList(Patches); -} -void DebugLoclistWriter::finalizeDWARFLegacy( - uint64_t SectionOffset, SimpleBinaryPatcher &DebugInfoPatcher) { - for (LocPatch &Patch : Patches) { - if (Patch.LocList.empty()) { - DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, - DebugLocWriter::EmptyListOffset); - continue; - } - const uint32_t EntryOffset = LocBuffer->size(); - for (const DebugLocationEntry &Entry : Patch.LocList) { - support::endian::write(*LocStream, - static_cast(dwarf::DW_LLE_startx_length), - support::little); - const uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, CU); - encodeULEB128(Index, *LocStream); - - // TODO: Support DWARF5 - support::endian::write(*LocStream, - static_cast(Entry.HighPC - Entry.LowPC), - support::little); - support::endian::write(*LocStream, - static_cast(Entry.Expr.size()), - support::little); - *LocStream << StringRef(reinterpret_cast(Entry.Expr.data()), - Entry.Expr.size()); + std::unique_ptr Header = getDWARF5Header( + {static_cast(SizeOfArraySection + LocBodyBuffer.get()->size()), + 5, 8, 0, NumberOfEntries}); + *LocStream << *Header; + *LocStream << *LocArrayBuffer; + *LocStream << *LocBodyBuffer; + + if (!isSplitDwarf()) { + if (Optional AttrInfoVal = + findAttributeInfo(CU.getUnitDIE(), dwarf::DW_AT_loclists_base)) + DebugInfoPatcher.addLE32Patch(AttrInfoVal->Offset, + LoclistBaseOffset + + getDWARF5RngListLocListHeaderSize()); + else { + AbbrevWriter.addAttribute( + CU, CU.getUnitDIE().getAbbreviationDeclarationPtr(), + dwarf::DW_AT_loclists_base, dwarf::DW_FORM_sec_offset); + DebugInfoPatcher.insertNewEntry(CU.getUnitDIE(), + LoclistBaseOffset + Header->size()); } - support::endian::write(*LocStream, - static_cast(dwarf::DW_LLE_end_of_list), - support::little); - DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset); - clearList(Patch.LocList); + LoclistBaseOffset += LocBuffer->size(); } - clearList(Patches); + clearList(RelativeLocListOffsets); + clearList(*LocArrayBuffer); + clearList(*LocBodyBuffer); } -void DebugLoclistWriter::finalize(uint64_t SectionOffset, - SimpleBinaryPatcher &DebugInfoPatcher) { - if (DwarfVersion < 5) - finalizeDWARFLegacy(SectionOffset, DebugInfoPatcher); - else - finalizeDWARF5(SectionOffset, DebugInfoPatcher); +void DebugLoclistWriter::finalize(DebugInfoBinaryPatcher &DebugInfoPatcher, + DebugAbbrevWriter &AbbrevWriter) { + if (DwarfVersion >= 5) + finalizeDWARF5(DebugInfoPatcher, AbbrevWriter); } DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr; @@ -1590,7 +1609,7 @@ void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) { } // Switch to the section where the table will be emitted into. - Streamer.SwitchSection(BC.MOFI->getDwarfLineSection()); + Streamer.switchSection(BC.MOFI->getDwarfLineSection()); const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion(); // Handle the rest of the Compile Units. diff --git a/bolt/lib/Core/Exceptions.cpp b/bolt/lib/Core/Exceptions.cpp index 70e41077a53f1..b3ee89bd9a58e 100644 --- a/bolt/lib/Core/Exceptions.cpp +++ b/bolt/lib/Core/Exceptions.cpp @@ -39,11 +39,9 @@ extern llvm::cl::OptionCategory BoltCategory; extern llvm::cl::opt Verbosity; static llvm::cl::opt -PrintExceptions("print-exceptions", - llvm::cl::desc("print exception handling data"), - llvm::cl::ZeroOrMore, - llvm::cl::Hidden, - llvm::cl::cat(BoltCategory)); + PrintExceptions("print-exceptions", + llvm::cl::desc("print exception handling data"), + llvm::cl::Hidden, llvm::cl::cat(BoltCategory)); } // namespace opts @@ -495,7 +493,7 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const { Optional LSDA = CurFDE.getLSDAAddress(); Function.setLSDAAddress(LSDA ? *LSDA : 0); - uint64_t Offset = 0; + uint64_t Offset = Function.getFirstInstructionOffset(); uint64_t CodeAlignment = CurFDE.getLinkedCIE()->getCodeAlignmentFactor(); uint64_t DataAlignment = CurFDE.getLinkedCIE()->getDataAlignmentFactor(); if (CurFDE.getLinkedCIE()->getPersonalityAddress()) { diff --git a/bolt/lib/Core/Relocation.cpp b/bolt/lib/Core/Relocation.cpp index 98d75d2cf44dc..f989ab1e0c47b 100644 --- a/bolt/lib/Core/Relocation.cpp +++ b/bolt/lib/Core/Relocation.cpp @@ -165,6 +165,12 @@ size_t getSizeForTypeAArch64(uint64_t Type) { } } +bool skipRelocationTypeX86(uint64_t Type) { return Type == ELF::R_X86_64_NONE; } + +bool skipRelocationTypeAArch64(uint64_t Type) { + return Type == ELF::R_AARCH64_NONE || Type == ELF::R_AARCH64_LD_PREL_LO19; +} + bool skipRelocationProcessX86(uint64_t Type, uint64_t Contents) { return false; } @@ -536,6 +542,12 @@ size_t Relocation::getSizeForType(uint64_t Type) { return getSizeForTypeX86(Type); } +bool Relocation::skipRelocationType(uint64_t Type) { + if (Arch == Triple::aarch64) + return skipRelocationTypeAArch64(Type); + return skipRelocationTypeX86(Type); +} + bool Relocation::skipRelocationProcess(uint64_t Type, uint64_t Contents) { if (Arch == Triple::aarch64) return skipRelocationProcessAArch64(Type, Contents); @@ -562,6 +574,12 @@ bool Relocation::isGOT(uint64_t Type) { return isGOTX86(Type); } +bool Relocation::isX86GOTPCRELX(uint64_t Type) { + if (Arch != Triple::x86_64) + return false; + return Type == ELF::R_X86_64_GOTPCRELX || Type == ELF::R_X86_64_REX_GOTPCRELX; +} + bool Relocation::isNone(uint64_t Type) { return Type == getNone(); } bool Relocation::isRelative(uint64_t Type) { diff --git a/bolt/lib/Passes/Aligner.cpp b/bolt/lib/Passes/Aligner.cpp index 89e7877378669..9f2a6db39755d 100644 --- a/bolt/lib/Passes/Aligner.cpp +++ b/bolt/lib/Passes/Aligner.cpp @@ -33,23 +33,19 @@ AlignBlocksMinSize("align-blocks-min-size", cl::Hidden, cl::cat(BoltOptCategory)); -cl::opt -AlignBlocksThreshold("align-blocks-threshold", - cl::desc("align only blocks with frequency larger than containing function " - "execution frequency specified in percent. E.g. 1000 means aligning " - "blocks that are 10 times more frequently executed than the " - "containing function."), - cl::init(800), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); - -cl::opt -AlignFunctionsMaxBytes("align-functions-max-bytes", - cl::desc("maximum number of bytes to use to align functions"), - cl::init(32), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); +cl::opt AlignBlocksThreshold( + "align-blocks-threshold", + cl::desc( + "align only blocks with frequency larger than containing function " + "execution frequency specified in percent. E.g. 1000 means aligning " + "blocks that are 10 times more frequently executed than the " + "containing function."), + cl::init(800), cl::Hidden, cl::cat(BoltOptCategory)); + +cl::opt AlignFunctionsMaxBytes( + "align-functions-max-bytes", + cl::desc("maximum number of bytes to use to align functions"), cl::init(32), + cl::cat(BoltOptCategory)); cl::opt BlockAlignment("block-alignment", @@ -59,11 +55,9 @@ BlockAlignment("block-alignment", cl::cat(BoltOptCategory)); cl::opt -UseCompactAligner("use-compact-aligner", - cl::desc("Use compact approach for aligning functions"), - cl::init(true), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); + UseCompactAligner("use-compact-aligner", + cl::desc("Use compact approach for aligning functions"), + cl::init(true), cl::cat(BoltOptCategory)); } // end namespace opts diff --git a/bolt/lib/Passes/AsmDump.cpp b/bolt/lib/Passes/AsmDump.cpp index b89b46319289f..fda787cb2f41b 100644 --- a/bolt/lib/Passes/AsmDump.cpp +++ b/bolt/lib/Passes/AsmDump.cpp @@ -30,7 +30,7 @@ extern cl::opt Verbosity; cl::opt AsmDump("asm-dump", cl::desc("dump function into assembly"), cl::value_desc("dump folder"), cl::ValueOptional, - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltCategory)); + cl::Hidden, cl::cat(BoltCategory)); } // end namespace opts namespace llvm { diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp index 125ae3246d60d..3de01bbd3e56e 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -69,13 +69,11 @@ enum DynoStatsSortOrder : char { Descending }; -static cl::opt -DynoStatsSortOrderOpt("print-sorted-by-order", - cl::desc("use ascending or descending order when printing functions " - "ordered by dyno stats"), - cl::ZeroOrMore, - cl::init(DynoStatsSortOrder::Descending), - cl::cat(BoltOptCategory)); +static cl::opt DynoStatsSortOrderOpt( + "print-sorted-by-order", + cl::desc("use ascending or descending order when printing functions " + "ordered by dyno stats"), + cl::init(DynoStatsSortOrder::Descending), cl::cat(BoltOptCategory)); cl::list HotTextMoveSections("hot-text-move-sections", @@ -97,13 +95,11 @@ bool isHotTextMover(const BinaryFunction &Function) { return false; } -static cl::opt -MinBranchClusters("min-branch-clusters", - cl::desc("use a modified clustering algorithm geared towards minimizing " - "branches"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); +static cl::opt MinBranchClusters( + "min-branch-clusters", + cl::desc("use a modified clustering algorithm geared towards minimizing " + "branches"), + cl::Hidden, cl::cat(BoltOptCategory)); static cl::list Peepholes( "peepholes", cl::CommaSeparated, cl::desc("enable peephole optimizations"), @@ -120,11 +116,9 @@ static cl::list Peepholes( cl::ZeroOrMore, cl::cat(BoltOptCategory)); static cl::opt -PrintFuncStat("print-function-statistics", - cl::desc("print statistics about basic block ordering"), - cl::init(0), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); + PrintFuncStat("print-function-statistics", + cl::desc("print statistics about basic block ordering"), + cl::init(0), cl::cat(BoltOptCategory)); static cl::list PrintSortedBy("print-sorted-by", @@ -144,21 +138,18 @@ PrintSortedBy("print-sorted-by", cl::cat(BoltOptCategory)); static cl::opt -PrintUnknown("print-unknown", - cl::desc("print names of functions with unknown control flow"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltCategory), - cl::Hidden); + PrintUnknown("print-unknown", + cl::desc("print names of functions with unknown control flow"), + cl::cat(BoltCategory), cl::Hidden); static cl::opt -PrintUnknownCFG("print-unknown-cfg", - cl::desc("dump CFG of functions with unknown control flow"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltCategory), - cl::ReallyHidden); + PrintUnknownCFG("print-unknown-cfg", + cl::desc("dump CFG of functions with unknown control flow"), + cl::cat(BoltCategory), cl::ReallyHidden); +// Please MSVC19 with a forward declaration: otherwise it reports an error about +// an undeclared variable inside a callback. +extern cl::opt ReorderBlocks; cl::opt ReorderBlocks( "reorder-blocks", cl::desc("change layout of basic blocks in a function"), cl::init(bolt::ReorderBasicBlocks::LT_NONE), @@ -176,29 +167,31 @@ cl::opt ReorderBlocks( clEnumValN(bolt::ReorderBasicBlocks::LT_OPTIMIZE_CACHE, "cache", "perform optimal layout prioritizing I-cache " "behavior"), - clEnumValN(bolt::ReorderBasicBlocks::LT_OPTIMIZE_EXT_TSP, "cache+", + clEnumValN(bolt::ReorderBasicBlocks::LT_OPTIMIZE_CACHE_PLUS, "cache+", "perform layout optimizing I-cache behavior"), clEnumValN(bolt::ReorderBasicBlocks::LT_OPTIMIZE_EXT_TSP, "ext-tsp", "perform layout optimizing I-cache behavior"), clEnumValN(bolt::ReorderBasicBlocks::LT_OPTIMIZE_SHUFFLE, "cluster-shuffle", "perform random layout of clusters")), - cl::ZeroOrMore, cl::cat(BoltOptCategory)); + cl::ZeroOrMore, cl::cat(BoltOptCategory), + cl::callback([](const bolt::ReorderBasicBlocks::LayoutType &option) { + if (option == bolt::ReorderBasicBlocks::LT_OPTIMIZE_CACHE_PLUS) { + WithColor::warning() + << "'-reorder-blocks=cache+' is deprecated, " + << "please use '-reorder-blocks=ext-tsp' instead\n"; + ReorderBlocks = bolt::ReorderBasicBlocks::LT_OPTIMIZE_EXT_TSP; + } + })); -static cl::opt -ReportBadLayout("report-bad-layout", - cl::desc("print top functions with suboptimal code layout on input"), - cl::init(0), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); +static cl::opt ReportBadLayout( + "report-bad-layout", + cl::desc("print top functions with suboptimal code layout on input"), + cl::init(0), cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt -ReportStaleFuncs("report-stale", - cl::desc("print the list of functions with stale profile"), - cl::init(false), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); + ReportStaleFuncs("report-stale", + cl::desc("print the list of functions with stale profile"), + cl::Hidden, cl::cat(BoltOptCategory)); enum SctcModes : char { SctcAlways, @@ -229,23 +222,18 @@ StaleThreshold("stale-threshold", cl::Hidden, cl::cat(BoltOptCategory)); -static cl::opt -TSPThreshold("tsp-threshold", - cl::desc("maximum number of hot basic blocks in a function for which to use " - "a precise TSP solution while re-ordering basic blocks"), - cl::init(10), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); +static cl::opt TSPThreshold( + "tsp-threshold", + cl::desc( + "maximum number of hot basic blocks in a function for which to use " + "a precise TSP solution while re-ordering basic blocks"), + cl::init(10), cl::Hidden, cl::cat(BoltOptCategory)); -static cl::opt -TopCalledLimit("top-called-limit", - cl::desc("maximum number of functions to print in top called " - "functions section"), - cl::init(100), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); +static cl::opt TopCalledLimit( + "top-called-limit", + cl::desc("maximum number of functions to print in top called " + "functions section"), + cl::init(100), cl::Hidden, cl::cat(BoltCategory)); } // namespace opts @@ -1226,8 +1214,7 @@ void AssignSections::runOnFunctions(BinaryContext &BC) { continue; } - if (!UseColdSection || Function.hasValidIndex() || - Function.hasValidProfile()) + if (!UseColdSection || Function.hasValidIndex()) Function.setCodeSectionName(BC.getMainCodeSectionName()); else Function.setCodeSectionName(BC.getColdCodeSectionName()); diff --git a/bolt/lib/Passes/ExtTSPReorderAlgorithm.cpp b/bolt/lib/Passes/ExtTSPReorderAlgorithm.cpp index eed1aaa8ef8d9..e20f97935cfae 100644 --- a/bolt/lib/Passes/ExtTSPReorderAlgorithm.cpp +++ b/bolt/lib/Passes/ExtTSPReorderAlgorithm.cpp @@ -45,46 +45,32 @@ namespace opts { extern cl::OptionCategory BoltOptCategory; extern cl::opt NoThreads; -cl::opt -ChainSplitThreshold("chain-split-threshold", - cl::desc("The maximum size of a chain to apply splitting"), - cl::init(128), - cl::ReallyHidden, - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); +cl::opt ChainSplitThreshold( + "chain-split-threshold", + cl::desc("The maximum size of a chain to apply splitting"), cl::init(128), + cl::ReallyHidden, cl::cat(BoltOptCategory)); cl::opt -ForwardWeight("forward-weight", - cl::desc("The weight of forward jumps for ExtTSP value"), - cl::init(0.1), - cl::ReallyHidden, - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); + ForwardWeight("forward-weight", + cl::desc("The weight of forward jumps for ExtTSP value"), + cl::init(0.1), cl::ReallyHidden, cl::cat(BoltOptCategory)); cl::opt -BackwardWeight("backward-weight", - cl::desc("The weight of backward jumps for ExtTSP value"), - cl::init(0.1), - cl::ReallyHidden, - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); - -cl::opt -ForwardDistance("forward-distance", - cl::desc("The maximum distance (in bytes) of forward jumps for ExtTSP value"), - cl::init(1024), - cl::ReallyHidden, - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); - -cl::opt -BackwardDistance("backward-distance", - cl::desc("The maximum distance (in bytes) of backward jumps for ExtTSP value"), - cl::init(640), - cl::ReallyHidden, - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); - + BackwardWeight("backward-weight", + cl::desc("The weight of backward jumps for ExtTSP value"), + cl::init(0.1), cl::ReallyHidden, cl::cat(BoltOptCategory)); + +cl::opt ForwardDistance( + "forward-distance", + cl::desc( + "The maximum distance (in bytes) of forward jumps for ExtTSP value"), + cl::init(1024), cl::ReallyHidden, cl::cat(BoltOptCategory)); + +cl::opt BackwardDistance( + "backward-distance", + cl::desc( + "The maximum distance (in bytes) of backward jumps for ExtTSP value"), + cl::init(640), cl::ReallyHidden, cl::cat(BoltOptCategory)); } namespace llvm { diff --git a/bolt/lib/Passes/FrameAnalysis.cpp b/bolt/lib/Passes/FrameAnalysis.cpp index 7ccb724716177..afd8344bd480e 100644 --- a/bolt/lib/Passes/FrameAnalysis.cpp +++ b/bolt/lib/Passes/FrameAnalysis.cpp @@ -35,12 +35,8 @@ static cl::opt FrameOptFunctionNamesFile( "funcs-file-fop", cl::desc("file with list of functions to frame optimize")); -static cl::opt -TimeFA("time-fa", - cl::desc("time frame analysis steps"), - cl::ReallyHidden, - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); +static cl::opt TimeFA("time-fa", cl::desc("time frame analysis steps"), + cl::ReallyHidden, cl::cat(BoltOptCategory)); bool shouldFrameOptimize(const llvm::bolt::BinaryFunction &Function) { if (Function.hasUnknownControlFlow()) diff --git a/bolt/lib/Passes/FrameOptimizer.cpp b/bolt/lib/Passes/FrameOptimizer.cpp index 4954cc7f94a70..8422d094a1110 100644 --- a/bolt/lib/Passes/FrameOptimizer.cpp +++ b/bolt/lib/Passes/FrameOptimizer.cpp @@ -43,13 +43,10 @@ FrameOptimization("frame-opt", cl::ZeroOrMore, cl::cat(BoltOptCategory)); -cl::opt -RemoveStores("frame-opt-rm-stores", - cl::init(FOP_NONE), - cl::desc("apply additional analysis to remove stores (experimental)"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); +cl::opt RemoveStores( + "frame-opt-rm-stores", cl::init(FOP_NONE), + cl::desc("apply additional analysis to remove stores (experimental)"), + cl::cat(BoltOptCategory)); } // namespace opts diff --git a/bolt/lib/Passes/HFSortPlus.cpp b/bolt/lib/Passes/HFSortPlus.cpp index f2b30d2d86bff..fff9165810aa9 100644 --- a/bolt/lib/Passes/HFSortPlus.cpp +++ b/bolt/lib/Passes/HFSortPlus.cpp @@ -37,45 +37,30 @@ namespace opts { extern cl::OptionCategory BoltOptCategory; -cl::opt -ITLBPageSize("itlb-page-size", - cl::desc("The size of i-tlb cache page"), - cl::init(4096), - cl::ReallyHidden, - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); - -cl::opt -ITLBEntries("itlb-entries", - cl::desc("The number of entries in i-tlb cache"), - cl::init(16), - cl::ReallyHidden, - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); - -static cl::opt -ITLBDensity("itlb-density", - cl::desc("The density of i-tlb cache"), - cl::init(4096), - cl::ReallyHidden, - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); - -static cl::opt -MergeProbability("merge-probability", - cl::desc("The minimum probability of a call for merging two clusters"), - cl::init(0.9), - cl::ReallyHidden, - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); - -static cl::opt -ArcThreshold("arc-threshold", - cl::desc("The threshold for ignoring arcs with a small relative weight"), - cl::init(0.00000001), - cl::ReallyHidden, - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); +cl::opt ITLBPageSize("itlb-page-size", + cl::desc("The size of i-tlb cache page"), + cl::init(4096), cl::ReallyHidden, + cl::cat(BoltOptCategory)); + +cl::opt ITLBEntries("itlb-entries", + cl::desc("The number of entries in i-tlb cache"), + cl::init(16), cl::ReallyHidden, + cl::cat(BoltOptCategory)); + +static cl::opt ITLBDensity("itlb-density", + cl::desc("The density of i-tlb cache"), + cl::init(4096), cl::ReallyHidden, + cl::cat(BoltOptCategory)); + +static cl::opt MergeProbability( + "merge-probability", + cl::desc("The minimum probability of a call for merging two clusters"), + cl::init(0.9), cl::ReallyHidden, cl::cat(BoltOptCategory)); + +static cl::opt ArcThreshold( + "arc-threshold", + cl::desc("The threshold for ignoring arcs with a small relative weight"), + cl::init(0.00000001), cl::ReallyHidden, cl::cat(BoltOptCategory)); } // namespace opts diff --git a/bolt/lib/Passes/IdenticalCodeFolding.cpp b/bolt/lib/Passes/IdenticalCodeFolding.cpp index c7c6ec7062e32..e9dc6171cdc1a 100644 --- a/bolt/lib/Passes/IdenticalCodeFolding.cpp +++ b/bolt/lib/Passes/IdenticalCodeFolding.cpp @@ -29,12 +29,9 @@ namespace opts { extern cl::OptionCategory BoltOptCategory; -static cl::opt -UseDFS("icf-dfs", - cl::desc("use DFS ordering when using -icf option"), - cl::ReallyHidden, - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); +static cl::opt UseDFS("icf-dfs", + cl::desc("use DFS ordering when using -icf option"), + cl::ReallyHidden, cl::cat(BoltOptCategory)); static cl::opt TimeICF("time-icf", diff --git a/bolt/lib/Passes/IndirectCallPromotion.cpp b/bolt/lib/Passes/IndirectCallPromotion.cpp index 33b6904624ca0..3448748007527 100644 --- a/bolt/lib/Passes/IndirectCallPromotion.cpp +++ b/bolt/lib/Passes/IndirectCallPromotion.cpp @@ -44,26 +44,26 @@ static cl::opt ICPJTTotalPercentThreshold( cl::desc( "The percentage threshold against total count for the promotion for " "jump tables"), - cl::init(5), cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + cl::init(5), cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt ICPCallsRemainingPercentThreshold( "icp-calls-remaining-percent-threshold", cl::desc("The percentage threshold against remaining unpromoted indirect " "call count for the promotion for calls"), - cl::init(50), cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + cl::init(50), cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt ICPCallsTotalPercentThreshold( "icp-calls-total-percent-threshold", cl::desc( "The percentage threshold against total count for the promotion for " "calls"), - cl::init(30), cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + cl::init(30), cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt ICPMispredictThreshold( "indirect-call-promotion-mispredict-threshold", cl::desc("misprediction threshold for skipping ICP on an " "indirect call"), - cl::init(0), cl::ZeroOrMore, cl::cat(BoltOptCategory)); + cl::init(0), cl::cat(BoltOptCategory)); static cl::opt ICPUseMispredicts( "indirect-call-promotion-use-mispredicts", @@ -71,37 +71,37 @@ static cl::opt ICPUseMispredicts( "should be applied at a callsite. The " "-indirect-call-promotion-mispredict-threshold value will be used " "by this heuristic"), - cl::ZeroOrMore, cl::cat(BoltOptCategory)); + cl::cat(BoltOptCategory)); static cl::opt ICPTopN("indirect-call-promotion-topn", cl::desc("limit number of targets to consider when doing indirect " "call promotion. 0 = no limit"), - cl::init(3), cl::ZeroOrMore, cl::cat(BoltOptCategory)); + cl::init(3), cl::cat(BoltOptCategory)); static cl::opt ICPCallsTopN( "indirect-call-promotion-calls-topn", cl::desc("limit number of targets to consider when doing indirect " "call promotion on calls. 0 = no limit"), - cl::init(0), cl::ZeroOrMore, cl::cat(BoltOptCategory)); + cl::init(0), cl::cat(BoltOptCategory)); static cl::opt ICPJumpTablesTopN( "indirect-call-promotion-jump-tables-topn", cl::desc("limit number of targets to consider when doing indirect " "call promotion on jump tables. 0 = no limit"), - cl::init(0), cl::ZeroOrMore, cl::cat(BoltOptCategory)); + cl::init(0), cl::cat(BoltOptCategory)); static cl::opt EliminateLoads( "icp-eliminate-loads", cl::desc("enable load elimination using memory profiling data when " "performing ICP"), - cl::init(true), cl::ZeroOrMore, cl::cat(BoltOptCategory)); + cl::init(true), cl::cat(BoltOptCategory)); static cl::opt ICPTopCallsites( "icp-top-callsites", cl::desc("optimize hottest calls until at least this percentage of all " "indirect calls frequency is covered. 0 = all callsites"), - cl::init(99), cl::Hidden, cl::ZeroOrMore, cl::cat(BoltOptCategory)); + cl::init(99), cl::Hidden, cl::cat(BoltOptCategory)); static cl::list ICPFuncsList("icp-funcs", cl::CommaSeparated, @@ -112,27 +112,21 @@ static cl::list static cl::opt ICPOldCodeSequence("icp-old-code-sequence", cl::desc("use old code sequence for promoted calls"), - cl::init(false), cl::ZeroOrMore, cl::Hidden, - cl::cat(BoltOptCategory)); + cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt ICPJumpTablesByTarget( "icp-jump-tables-targets", cl::desc( "for jump tables, optimize indirect jmp targets instead of indices"), - cl::init(false), cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt ICPPeelForInline( "icp-inline", cl::desc("only promote call targets eligible for inlining"), - cl::init(false), cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + cl::Hidden, cl::cat(BoltOptCategory)); } // namespace opts -namespace llvm { -namespace bolt { - -namespace { - -bool verifyProfile(std::map &BFs) { +static bool verifyProfile(std::map &BFs) { bool IsValid = true; for (auto &BFI : BFs) { BinaryFunction &BF = BFI.second; @@ -157,7 +151,8 @@ bool verifyProfile(std::map &BFs) { return IsValid; } -} // namespace +namespace llvm { +namespace bolt { IndirectCallPromotion::Callsite::Callsite(BinaryFunction &BF, const IndirectCallProfile &ICP) diff --git a/bolt/lib/Passes/Inliner.cpp b/bolt/lib/Passes/Inliner.cpp index 85b8c16f174b0..1d4fa8fa29355 100644 --- a/bolt/lib/Passes/Inliner.cpp +++ b/bolt/lib/Passes/Inliner.cpp @@ -38,10 +38,9 @@ namespace opts { extern cl::OptionCategory BoltOptCategory; static cl::opt -AdjustProfile("inline-ap", - cl::desc("adjust function profile after inlining"), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); + AdjustProfile("inline-ap", + cl::desc("adjust function profile after inlining"), + cl::cat(BoltOptCategory)); static cl::list ForceInlineFunctions("force-inline", @@ -51,68 +50,46 @@ ForceInlineFunctions("force-inline", cl::Hidden, cl::cat(BoltOptCategory)); -static cl::opt -InlineAll("inline-all", - cl::desc("inline all functions"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); +static cl::opt InlineAll("inline-all", cl::desc("inline all functions"), + cl::cat(BoltOptCategory)); -static cl::opt -InlineIgnoreLeafCFI("inline-ignore-leaf-cfi", - cl::desc("inline leaf functions with CFI programs (can break unwinding)"), - cl::init(true), - cl::ZeroOrMore, - cl::ReallyHidden, - cl::cat(BoltOptCategory)); +static cl::opt InlineIgnoreLeafCFI( + "inline-ignore-leaf-cfi", + cl::desc("inline leaf functions with CFI programs (can break unwinding)"), + cl::init(true), cl::ReallyHidden, cl::cat(BoltOptCategory)); -static cl::opt -InlineIgnoreCFI("inline-ignore-cfi", - cl::desc("inline functions with CFI programs (can break exception handling)"), - cl::init(false), - cl::ZeroOrMore, - cl::ReallyHidden, - cl::cat(BoltOptCategory)); +static cl::opt InlineIgnoreCFI( + "inline-ignore-cfi", + cl::desc( + "inline functions with CFI programs (can break exception handling)"), + cl::ReallyHidden, cl::cat(BoltOptCategory)); static cl::opt -InlineLimit("inline-limit", - cl::desc("maximum number of call sites to inline"), - cl::init(0), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); + InlineLimit("inline-limit", + cl::desc("maximum number of call sites to inline"), cl::init(0), + cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt -InlineMaxIters("inline-max-iters", - cl::desc("maximum number of inline iterations"), - cl::init(3), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); - -static cl::opt -InlineSmallFunctions("inline-small-functions", - cl::desc("inline functions if increase in size is less than defined by " - "-inline-small-functions-bytes"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); - -static cl::opt -InlineSmallFunctionsBytes("inline-small-functions-bytes", - cl::desc("max number of bytes for the function to be considered small for " - "inlining purposes"), - cl::init(4), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); - -static cl::opt -NoInline("no-inline", - cl::desc("disable all inlining (overrides other inlining options)"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); + InlineMaxIters("inline-max-iters", + cl::desc("maximum number of inline iterations"), cl::init(3), + cl::Hidden, cl::cat(BoltOptCategory)); + +static cl::opt InlineSmallFunctions( + "inline-small-functions", + cl::desc("inline functions if increase in size is less than defined by " + "-inline-small-functions-bytes"), + cl::cat(BoltOptCategory)); + +static cl::opt InlineSmallFunctionsBytes( + "inline-small-functions-bytes", + cl::desc("max number of bytes for the function to be considered small for " + "inlining purposes"), + cl::init(4), cl::Hidden, cl::cat(BoltOptCategory)); + +static cl::opt NoInline( + "no-inline", + cl::desc("disable all inlining (overrides other inlining options)"), + cl::cat(BoltOptCategory)); /// This function returns true if any of inlining options are specified and the /// inlining pass should be executed. Whenever a new inlining option is added, diff --git a/bolt/lib/Passes/LongJmp.cpp b/bolt/lib/Passes/LongJmp.cpp index 24139f2b9ee16..96c0e7486f9c7 100644 --- a/bolt/lib/Passes/LongJmp.cpp +++ b/bolt/lib/Passes/LongJmp.cpp @@ -23,12 +23,9 @@ extern cl::opt AlignFunctions; extern cl::opt UseOldText; extern cl::opt HotFunctionsAtEnd; -static cl::opt -GroupStubs("group-stubs", - cl::desc("share stubs across functions"), - cl::init(true), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); +static cl::opt GroupStubs("group-stubs", + cl::desc("share stubs across functions"), + cl::init(true), cl::cat(BoltOptCategory)); } namespace llvm { diff --git a/bolt/lib/Passes/MCF.cpp b/bolt/lib/Passes/MCF.cpp index b1c7de907d153..4ba737da41cff 100644 --- a/bolt/lib/Passes/MCF.cpp +++ b/bolt/lib/Passes/MCF.cpp @@ -30,31 +30,23 @@ extern cl::OptionCategory BoltOptCategory; extern cl::opt TimeOpts; -static cl::opt -IterativeGuess("iterative-guess", - cl::desc("in non-LBR mode, guess edge counts using iterative technique"), - cl::ZeroOrMore, - cl::init(false), - cl::Hidden, - cl::cat(BoltOptCategory)); +static cl::opt IterativeGuess( + "iterative-guess", + cl::desc("in non-LBR mode, guess edge counts using iterative technique"), -static cl::opt -EqualizeBBCounts("equalize-bb-counts", - cl::desc("in non-LBR mode, use same count for BBs " - "that should have equivalent count"), - cl::ZeroOrMore, - cl::init(false), - cl::Hidden, - cl::cat(BoltOptCategory)); + cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt -UseRArcs("mcf-use-rarcs", - cl::desc("in MCF, consider the possibility of cancelling flow to balance " - "edges"), - cl::ZeroOrMore, - cl::init(false), - cl::Hidden, - cl::cat(BoltOptCategory)); + EqualizeBBCounts("equalize-bb-counts", + cl::desc("in non-LBR mode, use same count for BBs " + "that should have equivalent count"), + cl::Hidden, cl::cat(BoltOptCategory)); + +static cl::opt UseRArcs( + "mcf-use-rarcs", + cl::desc("in MCF, consider the possibility of cancelling flow to balance " + "edges"), + cl::Hidden, cl::cat(BoltOptCategory)); } // namespace opts diff --git a/bolt/lib/Passes/PatchEntries.cpp b/bolt/lib/Passes/PatchEntries.cpp index e049dee97e436..9cb1314ab9c9a 100644 --- a/bolt/lib/Passes/PatchEntries.cpp +++ b/bolt/lib/Passes/PatchEntries.cpp @@ -22,13 +22,9 @@ extern llvm::cl::OptionCategory BoltCategory; extern llvm::cl::opt Verbosity; llvm::cl::opt -ForcePatch("force-patch", - llvm::cl::desc("force patching of original entry points"), - llvm::cl::init(false), - llvm::cl::Hidden, - llvm::cl::ZeroOrMore, - llvm::cl::cat(BoltCategory)); - + ForcePatch("force-patch", + llvm::cl::desc("force patching of original entry points"), + llvm::cl::Hidden, llvm::cl::cat(BoltCategory)); } namespace llvm { diff --git a/bolt/lib/Passes/RegAnalysis.cpp b/bolt/lib/Passes/RegAnalysis.cpp index ca66b24842ddc..eab16cb090328 100644 --- a/bolt/lib/Passes/RegAnalysis.cpp +++ b/bolt/lib/Passes/RegAnalysis.cpp @@ -24,12 +24,9 @@ namespace opts { extern cl::opt Verbosity; extern cl::OptionCategory BoltOptCategory; -cl::opt AssumeABI( - "assume-abi", - cl::desc("assume the ABI is never violated"), - cl::ZeroOrMore, - cl::init(false), - cl::cat(BoltOptCategory)); +cl::opt AssumeABI("assume-abi", + cl::desc("assume the ABI is never violated"), + cl::cat(BoltOptCategory)); } namespace llvm { diff --git a/bolt/lib/Passes/RegReAssign.cpp b/bolt/lib/Passes/RegReAssign.cpp index b1b1d6a38cd02..d4f12222ec4d1 100644 --- a/bolt/lib/Passes/RegReAssign.cpp +++ b/bolt/lib/Passes/RegReAssign.cpp @@ -26,14 +26,11 @@ namespace opts { extern cl::OptionCategory BoltOptCategory; extern cl::opt UpdateDebugSections; -static cl::opt -AggressiveReAssign("use-aggr-reg-reassign", - cl::desc("use register liveness analysis to try to find more opportunities " - "for -reg-reassign optimization"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); - +static cl::opt AggressiveReAssign( + "use-aggr-reg-reassign", + cl::desc("use register liveness analysis to try to find more opportunities " + "for -reg-reassign optimization"), + cl::cat(BoltOptCategory)); } namespace llvm { diff --git a/bolt/lib/Passes/ReorderAlgorithm.cpp b/bolt/lib/Passes/ReorderAlgorithm.cpp index 60da527d5345b..62752b077ce5e 100644 --- a/bolt/lib/Passes/ReorderAlgorithm.cpp +++ b/bolt/lib/Passes/ReorderAlgorithm.cpp @@ -38,20 +38,12 @@ static cl::opt ColdThreshold( "samples). Default: 0 "), cl::init(0), cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); -static cl::opt -PrintClusters("print-clusters", - cl::desc("print clusters"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); - -cl::opt -RandomSeed("bolt-seed", - cl::desc("seed for randomization"), - cl::init(42), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); +static cl::opt PrintClusters("print-clusters", cl::desc("print clusters"), + cl::Hidden, cl::cat(BoltOptCategory)); + +cl::opt RandomSeed("bolt-seed", cl::desc("seed for randomization"), + cl::init(42), cl::Hidden, + cl::cat(BoltOptCategory)); } // namespace opts diff --git a/bolt/lib/Passes/ReorderData.cpp b/bolt/lib/Passes/ReorderData.cpp index 53c7e8dfb62f0..3f36caba53ae4 100644 --- a/bolt/lib/Passes/ReorderData.cpp +++ b/bolt/lib/Passes/ReorderData.cpp @@ -30,11 +30,9 @@ extern cl::OptionCategory BoltOptCategory; extern cl::opt JumpTables; static cl::opt -PrintReorderedData("print-reordered-data", - cl::desc("print section contents after reordering"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); + PrintReorderedData("print-reordered-data", + cl::desc("print section contents after reordering"), + cl::Hidden, cl::cat(BoltCategory)); cl::list ReorderData("reorder-data", @@ -63,18 +61,14 @@ ReorderAlgorithm("reorder-data-algo", cl::cat(BoltOptCategory)); static cl::opt -ReorderDataMaxSymbols("reorder-data-max-symbols", - cl::desc("maximum number of symbols to reorder"), - cl::ZeroOrMore, - cl::init(std::numeric_limits::max()), - cl::cat(BoltOptCategory)); + ReorderDataMaxSymbols("reorder-data-max-symbols", + cl::desc("maximum number of symbols to reorder"), + cl::init(std::numeric_limits::max()), + cl::cat(BoltOptCategory)); -static cl::opt -ReorderDataMaxBytes("reorder-data-max-bytes", - cl::desc("maximum number of bytes to reorder"), - cl::ZeroOrMore, - cl::init(std::numeric_limits::max()), - cl::cat(BoltOptCategory)); +static cl::opt ReorderDataMaxBytes( + "reorder-data-max-bytes", cl::desc("maximum number of bytes to reorder"), + cl::init(std::numeric_limits::max()), cl::cat(BoltOptCategory)); static cl::list ReorderSymbols("reorder-symbols", @@ -92,13 +86,10 @@ SkipSymbols("reorder-skip-symbols", cl::Hidden, cl::cat(BoltCategory)); -static cl::opt -ReorderInplace("reorder-data-inplace", - cl::desc("reorder data sections in place"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); +static cl::opt ReorderInplace("reorder-data-inplace", + cl::desc("reorder data sections in place"), + cl::cat(BoltOptCategory)); } namespace llvm { diff --git a/bolt/lib/Passes/ReorderFunctions.cpp b/bolt/lib/Passes/ReorderFunctions.cpp index ed58404c7ff7e..6b7f80960faea 100644 --- a/bolt/lib/Passes/ReorderFunctions.cpp +++ b/bolt/lib/Passes/ReorderFunctions.cpp @@ -55,12 +55,10 @@ ReorderFunctions("reorder-functions", cl::ZeroOrMore, cl::cat(BoltOptCategory)); -static cl::opt -ReorderFunctionsUseHotSize("reorder-functions-use-hot-size", - cl::desc("use a function's hot size when doing clustering"), - cl::init(true), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); +static cl::opt ReorderFunctionsUseHotSize( + "reorder-functions-use-hot-size", + cl::desc("use a function's hot size when doing clustering"), cl::init(true), + cl::cat(BoltOptCategory)); static cl::opt FunctionOrderFile("function-order", @@ -81,11 +79,9 @@ LinkSectionsFile("generate-link-sections", cl::cat(BoltOptCategory)); static cl::opt -UseEdgeCounts("use-edge-counts", - cl::desc("use edge count data when doing clustering"), - cl::init(true), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); + UseEdgeCounts("use-edge-counts", + cl::desc("use edge count data when doing clustering"), + cl::init(true), cl::cat(BoltOptCategory)); static cl::opt CgFromPerfData("cg-from-perf-data", @@ -95,12 +91,10 @@ CgFromPerfData("cg-from-perf-data", cl::ZeroOrMore, cl::cat(BoltOptCategory)); -static cl::opt -CgIgnoreRecursiveCalls("cg-ignore-recursive-calls", - cl::desc("ignore recursive calls when constructing the call graph"), - cl::init(true), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); +static cl::opt CgIgnoreRecursiveCalls( + "cg-ignore-recursive-calls", + cl::desc("ignore recursive calls when constructing the call graph"), + cl::init(true), cl::cat(BoltOptCategory)); static cl::opt CgUseSplitHotSize("cg-use-split-hot-size", @@ -134,6 +128,13 @@ void ReorderFunctions::reorder(std::vector &&Clusters, } } + // Assign valid index for functions with valid profile. + for (auto &It : BFs) { + BinaryFunction &BF = It.second; + if (!BF.hasValidIndex() && BF.hasValidProfile()) + BF.setIndex(Index++); + } + if (opts::ReorderFunctions == RT_NONE) return; diff --git a/bolt/lib/Passes/RetpolineInsertion.cpp b/bolt/lib/Passes/RetpolineInsertion.cpp index c91c185a0665a..160507ac4e374 100644 --- a/bolt/lib/Passes/RetpolineInsertion.cpp +++ b/bolt/lib/Passes/RetpolineInsertion.cpp @@ -32,12 +32,9 @@ namespace opts { extern cl::OptionCategory BoltCategory; -llvm::cl::opt -InsertRetpolines("insert-retpolines", - cl::desc("run retpoline insertion pass"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltCategory)); +llvm::cl::opt InsertRetpolines("insert-retpolines", + cl::desc("run retpoline insertion pass"), + cl::cat(BoltCategory)); llvm::cl::opt RetpolineLfence("retpoline-lfence", diff --git a/bolt/lib/Passes/SplitFunctions.cpp b/bolt/lib/Passes/SplitFunctions.cpp index d89e72c34199f..5e80620074dd9 100644 --- a/bolt/lib/Passes/SplitFunctions.cpp +++ b/bolt/lib/Passes/SplitFunctions.cpp @@ -29,21 +29,18 @@ extern cl::OptionCategory BoltOptCategory; extern cl::opt SplitEH; extern cl::opt ExecutionCountThreshold; -static cl::opt -AggressiveSplitting("split-all-cold", - cl::desc("outline as many cold basic blocks as possible"), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); +static cl::opt AggressiveSplitting( + "split-all-cold", cl::desc("outline as many cold basic blocks as possible"), + cl::cat(BoltOptCategory)); -static cl::opt -SplitAlignThreshold("split-align-threshold", - cl::desc("when deciding to split a function, apply this alignment " - "while doing the size comparison (see -split-threshold). " - "Default value: 2."), - cl::init(2), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); +static cl::opt SplitAlignThreshold( + "split-align-threshold", + cl::desc("when deciding to split a function, apply this alignment " + "while doing the size comparison (see -split-threshold). " + "Default value: 2."), + cl::init(2), + + cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt SplitFunctions("split-functions", @@ -61,16 +58,13 @@ SplitFunctions("split-functions", cl::ZeroOrMore, cl::cat(BoltOptCategory)); -static cl::opt -SplitThreshold("split-threshold", - cl::desc("split function only if its main size is reduced by more than " - "given amount of bytes. Default value: 0, i.e. split iff the " - "size is reduced. Note that on some architectures the size can " - "increase after splitting."), - cl::init(0), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); +static cl::opt SplitThreshold( + "split-threshold", + cl::desc("split function only if its main size is reduced by more than " + "given amount of bytes. Default value: 0, i.e. split iff the " + "size is reduced. Note that on some architectures the size can " + "increase after splitting."), + cl::init(0), cl::Hidden, cl::cat(BoltOptCategory)); void syncOptions(BinaryContext &BC) { if (!BC.HasRelocations && opts::SplitFunctions == SplitFunctions::ST_LARGE) diff --git a/bolt/lib/Passes/TailDuplication.cpp b/bolt/lib/Passes/TailDuplication.cpp index b783bf8422be8..21bd44fa4ffbe 100644 --- a/bolt/lib/Passes/TailDuplication.cpp +++ b/bolt/lib/Passes/TailDuplication.cpp @@ -11,7 +11,9 @@ //===----------------------------------------------------------------------===// #include "bolt/Passes/TailDuplication.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/MC/MCRegisterInfo.h" + #include #define DEBUG_TYPE "taildup" @@ -21,35 +23,62 @@ using namespace llvm; namespace opts { extern cl::OptionCategory BoltOptCategory; - -static cl::opt TailDuplicationAggressive( - "tail-duplication-aggressive", - cl::desc("tail duplication should act aggressively in duplicating multiple " - "blocks per tail"), - cl::ZeroOrMore, cl::ReallyHidden, cl::init(false), - cl::cat(BoltOptCategory)); +extern cl::opt NoThreads; + +cl::opt TailDuplicationMode( + "tail-duplication", + cl::desc("duplicate unconditional branches that cross a cache line"), + cl::init(bolt::TailDuplication::TD_NONE), + cl::values(clEnumValN(bolt::TailDuplication::TD_NONE, "none", + "do not apply"), + clEnumValN(bolt::TailDuplication::TD_AGGRESSIVE, "aggressive", + "aggressive strategy"), + clEnumValN(bolt::TailDuplication::TD_MODERATE, "moderate", + "moderate strategy"), + clEnumValN(bolt::TailDuplication::TD_CACHE, "cache", + "cache-aware duplication strategy")), + cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt TailDuplicationMinimumOffset("tail-duplication-minimum-offset", cl::desc("minimum offset needed between block " "and successor to allow duplication"), - cl::ZeroOrMore, cl::ReallyHidden, cl::init(64), + cl::ReallyHidden, cl::init(64), cl::cat(BoltOptCategory)); static cl::opt TailDuplicationMaximumDuplication( "tail-duplication-maximum-duplication", - cl::desc("maximum size of duplicated blocks (in bytes)"), cl::ZeroOrMore, - cl::ReallyHidden, cl::init(64), cl::cat(BoltOptCategory)); + cl::desc("tail blocks whose size (in bytes) exceeds the value are never " + "duplicated"), + cl::ZeroOrMore, cl::ReallyHidden, cl::init(24), cl::cat(BoltOptCategory)); + +static cl::opt TailDuplicationMinimumDuplication( + "tail-duplication-minimum-duplication", + cl::desc("tail blocks with size (in bytes) not exceeding the value are " + "always duplicated"), + cl::ReallyHidden, cl::init(2), cl::cat(BoltOptCategory)); static cl::opt TailDuplicationConstCopyPropagation( "tail-duplication-const-copy-propagation", cl::desc("enable const and copy propagation after tail duplication"), cl::ReallyHidden, cl::init(false), cl::cat(BoltOptCategory)); +static cl::opt TailDuplicationMaxCacheDistance( + "tail-duplication-max-cache-distance", + cl::desc("The weight of backward jumps for ExtTSP value"), cl::init(256), + cl::ReallyHidden, cl::cat(BoltOptCategory)); + +static cl::opt TailDuplicationCacheBackwardWeight( + "tail-duplication-cache-backward-weight", + cl::desc( + "The maximum distance (in bytes) of backward jumps for ExtTSP value"), + cl::init(0.5), cl::ReallyHidden, cl::cat(BoltOptCategory)); + } // namespace opts namespace llvm { namespace bolt { + void TailDuplication::getCallerSavedRegs(const MCInst &Inst, BitVector &Regs, BinaryContext &BC) const { if (!BC.MIB->isCall(Inst)) @@ -242,24 +271,39 @@ bool TailDuplication::isInCacheLine(const BinaryBasicBlock &BB, } std::vector -TailDuplication::moderateCodeToDuplicate(BinaryBasicBlock &BB) const { +TailDuplication::moderateDuplicate(BinaryBasicBlock &BB, + BinaryBasicBlock &Tail) const { std::vector BlocksToDuplicate; - if (BB.hasJumpTable()) + // The block must be hot + if (BB.getKnownExecutionCount() == 0) + return BlocksToDuplicate; + // and its sucessor is not already in the same cache line + if (isInCacheLine(BB, Tail)) return BlocksToDuplicate; - if (BB.getOriginalSize() > opts::TailDuplicationMaximumDuplication) + // and its size do not exceed the maximum allowed size + if (Tail.getOriginalSize() > opts::TailDuplicationMaximumDuplication) return BlocksToDuplicate; - for (auto Itr = BB.succ_begin(); Itr != BB.succ_end(); ++Itr) { - if ((*Itr)->getLayoutIndex() == BB.getLayoutIndex() + 1) - // If duplicating would introduce a new branch, don't duplicate + // If duplicating would introduce a new branch, don't duplicate + for (auto Itr = Tail.succ_begin(); Itr != Tail.succ_end(); ++Itr) { + if ((*Itr)->getLayoutIndex() == Tail.getLayoutIndex() + 1) return BlocksToDuplicate; } - BlocksToDuplicate.push_back(&BB); + + BlocksToDuplicate.push_back(&Tail); return BlocksToDuplicate; } std::vector -TailDuplication::aggressiveCodeToDuplicate(BinaryBasicBlock &BB) const { +TailDuplication::aggressiveDuplicate(BinaryBasicBlock &BB, + BinaryBasicBlock &Tail) const { std::vector BlocksToDuplicate; + // The block must be hot + if (BB.getKnownExecutionCount() == 0) + return BlocksToDuplicate; + // and its sucessor is not already in the same cache line + if (isInCacheLine(BB, Tail)) + return BlocksToDuplicate; + BinaryBasicBlock *CurrBB = &BB; while (CurrBB) { LLVM_DEBUG(dbgs() << "Aggressive tail duplication: adding " @@ -297,10 +341,10 @@ TailDuplication::aggressiveCodeToDuplicate(BinaryBasicBlock &BB) const { // With one successor, if its a jump, we should duplicate all blocks in // BlocksToDuplicate. Otherwise, we should keep going - BinaryBasicBlock *Succ = CurrBB->getSuccessor(); - if (Succ->getLayoutIndex() != CurrBB->getLayoutIndex() + 1) + BinaryBasicBlock *SuccBB = CurrBB->getSuccessor(); + if (SuccBB->getLayoutIndex() != CurrBB->getLayoutIndex() + 1) break; - CurrBB = Succ; + CurrBB = SuccBB; } // Don't duplicate if its too much code unsigned DuplicationByteCount = std::accumulate( @@ -319,7 +363,146 @@ TailDuplication::aggressiveCodeToDuplicate(BinaryBasicBlock &BB) const { return BlocksToDuplicate; } -std::vector TailDuplication::tailDuplicate( +bool TailDuplication::shouldDuplicate(BinaryBasicBlock *Pred, + BinaryBasicBlock *Tail) const { + if (Pred == Tail) + return false; + // Cannot duplicate non-tail blocks + if (Tail->succ_size() != 0) + return false; + // The blocks are already in the order + if (Pred->getLayoutIndex() + 1 == Tail->getLayoutIndex()) + return false; + // No tail duplication for blocks with jump tables + if (Pred->hasJumpTable()) + return false; + if (Tail->hasJumpTable()) + return false; + + return true; +} + +double TailDuplication::cacheScore(uint64_t SrcAddr, uint64_t SrcSize, + uint64_t DstAddr, uint64_t DstSize, + uint64_t Count) const { + assert(Count != BinaryBasicBlock::COUNT_NO_PROFILE); + + bool IsForwardJump = SrcAddr <= DstAddr; + uint64_t JumpDistance = 0; + // Computing the length of the jump so that it takes the sizes of the two + // blocks into consideration + if (IsForwardJump) { + JumpDistance = (DstAddr + DstSize) - (SrcAddr); + } else { + JumpDistance = (SrcAddr + SrcSize) - (DstAddr); + } + + if (JumpDistance >= opts::TailDuplicationMaxCacheDistance) + return 0; + double Prob = 1.0 - static_cast(JumpDistance) / + opts::TailDuplicationMaxCacheDistance; + return (IsForwardJump ? 1.0 : opts::TailDuplicationCacheBackwardWeight) * + Prob * Count; +} + +bool TailDuplication::cacheScoreImproved(const MCCodeEmitter *Emitter, + BinaryFunction &BF, + BinaryBasicBlock *Pred, + BinaryBasicBlock *Tail) const { + // Collect (estimated) basic block sizes + DenseMap BBSize; + for (BinaryBasicBlock *BB : BF.layout()) { + BBSize[BB] = std::max(BB->estimateSize(Emitter), 1); + } + + // Build current addresses of basic blocks starting at the entry block + DenseMap CurAddr; + uint64_t Addr = 0; + for (BinaryBasicBlock *SrcBB : BF.layout()) { + CurAddr[SrcBB] = Addr; + Addr += BBSize[SrcBB]; + } + + // Build new addresses (after duplication) starting at the entry block + DenseMap NewAddr; + Addr = 0; + for (BinaryBasicBlock *SrcBB : BF.layout()) { + NewAddr[SrcBB] = Addr; + Addr += BBSize[SrcBB]; + if (SrcBB == Pred) + Addr += BBSize[Tail]; + } + + // Compute the cache score for the existing layout of basic blocks + double CurScore = 0; + for (BinaryBasicBlock *SrcBB : BF.layout()) { + auto BI = SrcBB->branch_info_begin(); + for (BinaryBasicBlock *DstBB : SrcBB->successors()) { + if (SrcBB != DstBB) { + CurScore += cacheScore(CurAddr[SrcBB], BBSize[SrcBB], CurAddr[DstBB], + BBSize[DstBB], BI->Count); + } + ++BI; + } + } + + // Compute the cache score for the layout of blocks after tail duplication + double NewScore = 0; + for (BinaryBasicBlock *SrcBB : BF.layout()) { + auto BI = SrcBB->branch_info_begin(); + for (BinaryBasicBlock *DstBB : SrcBB->successors()) { + if (SrcBB != DstBB) { + if (SrcBB == Pred && DstBB == Tail) { + NewScore += cacheScore(NewAddr[SrcBB], BBSize[SrcBB], + NewAddr[SrcBB] + BBSize[SrcBB], BBSize[DstBB], + BI->Count); + } else { + NewScore += cacheScore(NewAddr[SrcBB], BBSize[SrcBB], NewAddr[DstBB], + BBSize[DstBB], BI->Count); + } + } + ++BI; + } + } + + return NewScore > CurScore; +} + +std::vector +TailDuplication::cacheDuplicate(const MCCodeEmitter *Emitter, + BinaryFunction &BF, BinaryBasicBlock *Pred, + BinaryBasicBlock *Tail) const { + std::vector BlocksToDuplicate; + + // No need to duplicate cold basic blocks + if (Pred->isCold() || Tail->isCold()) { + return BlocksToDuplicate; + } + // Always duplicate "small" tail basic blocks, which might be beneficial for + // code size, since a jump instruction is eliminated + if (Tail->estimateSize(Emitter) <= opts::TailDuplicationMinimumDuplication) { + BlocksToDuplicate.push_back(Tail); + return BlocksToDuplicate; + } + // Never duplicate "large" tail basic blocks + if (Tail->estimateSize(Emitter) > opts::TailDuplicationMaximumDuplication) { + return BlocksToDuplicate; + } + // Do not append basic blocks after the last hot block in the current layout + auto NextBlock = BF.getBasicBlockAfter(Pred); + if (NextBlock == nullptr || (!Pred->isCold() && NextBlock->isCold())) { + return BlocksToDuplicate; + } + + // Duplicate the tail only if it improves the cache score + if (cacheScoreImproved(Emitter, BF, Pred, Tail)) { + BlocksToDuplicate.push_back(Tail); + } + + return BlocksToDuplicate; +} + +std::vector TailDuplication::duplicateBlocks( BinaryBasicBlock &BB, const std::vector &BlocksToDuplicate) const { BinaryFunction *BF = BB.getFunction(); @@ -329,7 +512,7 @@ std::vector TailDuplication::tailDuplicate( // successor's execution count. Used to set this new branches execution count // and lower the old successor's execution count double ExecutionCountRatio = - BB.getExecutionCount() > BB.getSuccessor()->getExecutionCount() + BB.getExecutionCount() >= BB.getSuccessor()->getExecutionCount() ? 1.0 : (double)BB.getExecutionCount() / BB.getSuccessor()->getExecutionCount(); @@ -347,15 +530,15 @@ std::vector TailDuplication::tailDuplicate( std::vector> DuplicatedBlocks; std::vector DuplicatedBlocksToReturn; - for (BinaryBasicBlock *CurrBB : BlocksToDuplicate) { + for (BinaryBasicBlock *CurBB : BlocksToDuplicate) { DuplicatedBlocks.emplace_back( BF->createBasicBlock(0, (BC.Ctx)->createNamedTempSymbol("tail-dup"))); BinaryBasicBlock *NewBB = DuplicatedBlocks.back().get(); - NewBB->addInstructions(CurrBB->begin(), CurrBB->end()); + NewBB->addInstructions(CurBB->begin(), CurBB->end()); // Set execution count as if it was just a copy of the original - NewBB->setExecutionCount( - std::max((uint64_t)1, CurrBB->getExecutionCount())); + NewBB->setExecutionCount(CurBB->getExecutionCount()); + NewBB->setIsCold(CurBB->isCold()); LastDuplicatedBB->addSuccessor(NewBB, LastBI); DuplicatedBlocksToReturn.push_back(NewBB); @@ -367,10 +550,10 @@ std::vector TailDuplication::tailDuplicate( LastDuplicatedBB->adjustExecutionCount(ExecutionCountRatio); } - if (CurrBB->succ_size() == 1) - LastBI = CurrBB->getBranchInfo(*(CurrBB->getSuccessor())); + if (CurBB->succ_size() == 1) + LastBI = CurBB->getBranchInfo(*(CurBB->getSuccessor())); - LastOriginalBB = CurrBB; + LastOriginalBB = CurBB; LastDuplicatedBB = NewBB; } @@ -387,64 +570,73 @@ std::vector TailDuplication::tailDuplicate( } void TailDuplication::runOnFunction(BinaryFunction &Function) { + // Create a separate MCCodeEmitter to allow lock-free execution + BinaryContext::IndependentCodeEmitter Emitter; + if (!opts::NoThreads) { + Emitter = Function.getBinaryContext().createIndependentMCCodeEmitter(); + } + + Function.updateLayoutIndices(); + // New blocks will be added and layout will change, // so make a copy here to iterate over the original layout BinaryFunction::BasicBlockOrderType BlockLayout = Function.getLayout(); + bool ModifiedFunction = false; for (BinaryBasicBlock *BB : BlockLayout) { - if (BB->succ_size() == 1 && - BB->getSuccessor()->getLayoutIndex() != BB->getLayoutIndex() + 1) - UnconditionalBranchDynamicCount += BB->getExecutionCount(); - if (BB->succ_size() == 2 && - BB->getFallthrough()->getLayoutIndex() != BB->getLayoutIndex() + 1) - UnconditionalBranchDynamicCount += BB->getFallthroughBranchInfo().Count; - AllBlocksDynamicCount += BB->getExecutionCount(); - - // The block must be hot - if (BB->getExecutionCount() == 0) - continue; - // with one successor - if (BB->succ_size() != 1) - continue; + AllDynamicCount += BB->getKnownExecutionCount(); - // no jump table - if (BB->hasJumpTable()) + // The block must be with one successor + if (BB->succ_size() != 1) continue; - - // Skip not-in-layout, i.e. unreachable, blocks. - if (BB->getLayoutIndex() >= BlockLayout.size()) + BinaryBasicBlock *Tail = BB->getSuccessor(); + // Verify that the tail should be duplicated + if (!shouldDuplicate(BB, Tail)) continue; - // and we are estimating that this sucessor is not already in the same cache - // line - BinaryBasicBlock *Succ = BB->getSuccessor(); - if (isInCacheLine(*BB, *Succ)) - continue; std::vector BlocksToDuplicate; - if (opts::TailDuplicationAggressive) - BlocksToDuplicate = aggressiveCodeToDuplicate(*Succ); - else - BlocksToDuplicate = moderateCodeToDuplicate(*Succ); + if (opts::TailDuplicationMode == TailDuplication::TD_AGGRESSIVE) { + BlocksToDuplicate = aggressiveDuplicate(*BB, *Tail); + } else if (opts::TailDuplicationMode == TailDuplication::TD_MODERATE) { + BlocksToDuplicate = moderateDuplicate(*BB, *Tail); + } else if (opts::TailDuplicationMode == TailDuplication::TD_CACHE) { + BlocksToDuplicate = cacheDuplicate(Emitter.MCE.get(), Function, BB, Tail); + } else { + llvm_unreachable("unknown tail duplication mode"); + } - if (BlocksToDuplicate.size() == 0) - continue; - PossibleDuplications++; - PossibleDuplicationsDynamicCount += BB->getExecutionCount(); - std::vector DuplicatedBlocks = - tailDuplicate(*BB, BlocksToDuplicate); - if (!opts::TailDuplicationConstCopyPropagation) + if (BlocksToDuplicate.empty()) continue; - constantAndCopyPropagate(*BB, DuplicatedBlocks); - BinaryBasicBlock *FirstBB = BlocksToDuplicate[0]; - if (FirstBB->pred_size() == 1) { - BinaryBasicBlock *PredBB = *FirstBB->pred_begin(); - if (PredBB->succ_size() == 1) - constantAndCopyPropagate(*PredBB, BlocksToDuplicate); + // Apply the the duplication + ModifiedFunction = true; + DuplicationsDynamicCount += BB->getExecutionCount(); + auto DuplicatedBlocks = duplicateBlocks(*BB, BlocksToDuplicate); + for (BinaryBasicBlock *BB : DuplicatedBlocks) { + DuplicatedBlockCount++; + DuplicatedByteCount += BB->estimateSize(Emitter.MCE.get()); + } + + if (opts::TailDuplicationConstCopyPropagation) { + constantAndCopyPropagate(*BB, DuplicatedBlocks); + BinaryBasicBlock *FirstBB = BlocksToDuplicate[0]; + if (FirstBB->pred_size() == 1) { + BinaryBasicBlock *PredBB = *FirstBB->pred_begin(); + if (PredBB->succ_size() == 1) + constantAndCopyPropagate(*PredBB, BlocksToDuplicate); + } } + + // Layout indices might be stale after duplication + Function.updateLayoutIndices(); } + if (ModifiedFunction) + ModifiedFunctions++; } void TailDuplication::runOnFunctions(BinaryContext &BC) { + if (opts::TailDuplicationMode == TailDuplication::TD_NONE) + return; + for (auto &It : BC.getBinaryFunctions()) { BinaryFunction &Function = It.second; if (!shouldOptimize(Function)) @@ -452,24 +644,23 @@ void TailDuplication::runOnFunctions(BinaryContext &BC) { runOnFunction(Function); } - outs() << "BOLT-INFO: tail duplication possible duplications: " - << PossibleDuplications << "\n"; - outs() << "BOLT-INFO: tail duplication possible dynamic reductions: " - << PossibleDuplicationsDynamicCount << "\n"; - outs() << "BOLT-INFO: tail duplication possible dynamic reductions to " - "unconditional branch execution : " - << format("%.1f", ((float)PossibleDuplicationsDynamicCount * 100.0f) / - UnconditionalBranchDynamicCount) - << "%\n"; - outs() << "BOLT-INFO: tail duplication possible dynamic reductions to all " - "blocks execution : " - << format("%.1f", ((float)PossibleDuplicationsDynamicCount * 100.0f) / - AllBlocksDynamicCount) - << "%\n"; - outs() << "BOLT-INFO: tail duplication static propagation deletions: " - << StaticInstructionDeletionCount << "\n"; - outs() << "BOLT-INFO: tail duplication dynamic propagation deletions: " - << DynamicInstructionDeletionCount << "\n"; // + 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", + StaticInstructionDeletionCount, + DynamicInstructionDeletionCount) + << "\n"; + } } } // end namespace bolt diff --git a/bolt/lib/Passes/VeneerElimination.cpp b/bolt/lib/Passes/VeneerElimination.cpp index d1f25e5312fcf..dcfd553f729d1 100644 --- a/bolt/lib/Passes/VeneerElimination.cpp +++ b/bolt/lib/Passes/VeneerElimination.cpp @@ -21,12 +21,9 @@ namespace opts { extern cl::OptionCategory BoltOptCategory; static llvm::cl::opt -EliminateVeneers("elim-link-veneers", - cl::desc("run veneer elimination pass"), - cl::init(true), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); + EliminateVeneers("elim-link-veneers", + cl::desc("run veneer elimination pass"), cl::init(true), + cl::Hidden, cl::cat(BoltOptCategory)); } // namespace opts namespace llvm { diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index 314ab8969d43f..9942a4033807f 100644 --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -40,11 +40,9 @@ using namespace bolt; namespace opts { static cl::opt -BasicAggregation("nl", - cl::desc("aggregate basic samples (without LBR info)"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(AggregatorCategory)); + BasicAggregation("nl", + cl::desc("aggregate basic samples (without LBR info)"), + cl::cat(AggregatorCategory)); static cl::opt FilterMemProfile("filter-mem-profile", @@ -66,12 +64,10 @@ IgnoreBuildID("ignore-build-id", cl::init(false), cl::cat(AggregatorCategory)); -static cl::opt -IgnoreInterruptLBR("ignore-interrupt-lbr", - cl::desc("ignore kernel interrupt LBR that happens asynchronously"), - cl::init(true), - cl::ZeroOrMore, - cl::cat(AggregatorCategory)); +static cl::opt IgnoreInterruptLBR( + "ignore-interrupt-lbr", + cl::desc("ignore kernel interrupt LBR that happens asynchronously"), + cl::init(true), cl::cat(AggregatorCategory)); static cl::opt MaxSamples("max-samples", @@ -81,12 +77,9 @@ MaxSamples("max-samples", cl::Hidden, cl::cat(AggregatorCategory)); -static cl::opt -ReadPreAggregated("pa", - cl::desc("skip perf and read data from a pre-aggregated file format"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(AggregatorCategory)); +static cl::opt ReadPreAggregated( + "pa", cl::desc("skip perf and read data from a pre-aggregated file format"), + cl::cat(AggregatorCategory)); static cl::opt TimeAggregator("time-aggr", @@ -96,18 +89,13 @@ TimeAggregator("time-aggr", cl::cat(AggregatorCategory)); static cl::opt -UseEventPC("use-event-pc", - cl::desc("use event PC in combination with LBR sampling"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(AggregatorCategory)); + UseEventPC("use-event-pc", + cl::desc("use event PC in combination with LBR sampling"), + cl::cat(AggregatorCategory)); -static cl::opt -WriteAutoFDOData("autofdo", - cl::desc("generate autofdo textual data instead of bolt data"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(AggregatorCategory)); +static cl::opt WriteAutoFDOData( + "autofdo", cl::desc("generate autofdo textual data instead of bolt data"), + cl::cat(AggregatorCategory)); } // namespace opts diff --git a/bolt/lib/Profile/YAMLProfileReader.cpp b/bolt/lib/Profile/YAMLProfileReader.cpp index 1ccdb2e974f76..59819b4ce6cd0 100644 --- a/bolt/lib/Profile/YAMLProfileReader.cpp +++ b/bolt/lib/Profile/YAMLProfileReader.cpp @@ -22,13 +22,9 @@ extern cl::opt Verbosity; extern cl::OptionCategory BoltOptCategory; static llvm::cl::opt -IgnoreHash("profile-ignore-hash", - cl::desc("ignore hash while reading function profile"), - cl::init(false), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); - + IgnoreHash("profile-ignore-hash", + cl::desc("ignore hash while reading function profile"), + cl::Hidden, cl::cat(BoltOptCategory)); } namespace llvm { diff --git a/bolt/lib/Rewrite/BinaryPassManager.cpp b/bolt/lib/Rewrite/BinaryPassManager.cpp index 929b734204792..3230fad99df8d 100644 --- a/bolt/lib/Rewrite/BinaryPassManager.cpp +++ b/bolt/lib/Rewrite/BinaryPassManager.cpp @@ -55,25 +55,21 @@ DynoStatsAll("dyno-stats-all", cl::ZeroOrMore, cl::Hidden, cl::cat(BoltCategory)); static cl::opt -EliminateUnreachable("eliminate-unreachable", - cl::desc("eliminate unreachable code"), - cl::init(true), cl::ZeroOrMore, cl::cat(BoltOptCategory)); + EliminateUnreachable("eliminate-unreachable", + cl::desc("eliminate unreachable code"), cl::init(true), + cl::cat(BoltOptCategory)); -cl::opt -ICF("icf", - cl::desc("fold functions with identical code"), - cl::ZeroOrMore, cl::cat(BoltOptCategory)); +cl::opt ICF("icf", cl::desc("fold functions with identical code"), + cl::cat(BoltOptCategory)); -static cl::opt -JTFootprintReductionFlag("jt-footprint-reduction", - cl::desc("make jump tables size smaller at the cost of using more " - "instructions at jump sites"), - cl::ZeroOrMore, cl::cat(BoltOptCategory)); +static cl::opt JTFootprintReductionFlag( + "jt-footprint-reduction", + cl::desc("make jump tables size smaller at the cost of using more " + "instructions at jump sites"), + cl::cat(BoltOptCategory)); -cl::opt -NeverPrint("never-print", - cl::desc("never print"), - cl::init(false), cl::ZeroOrMore, cl::ReallyHidden, cl::cat(BoltOptCategory)); +cl::opt NeverPrint("never-print", cl::desc("never print"), + cl::ReallyHidden, cl::cat(BoltOptCategory)); cl::opt PrintAfterBranchFixup("print-after-branch-fixup", @@ -91,125 +87,122 @@ PrintFinalized("print-finalized", cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt -PrintFOP("print-fop", - cl::desc("print functions after frame optimizer pass"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + PrintFOP("print-fop", + cl::desc("print functions after frame optimizer pass"), cl::Hidden, + cl::cat(BoltOptCategory)); static cl::opt -PrintICF("print-icf", - cl::desc("print functions after ICF optimization"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + PrintICF("print-icf", cl::desc("print functions after ICF optimization"), + cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt -PrintICP("print-icp", - cl::desc("print functions after indirect call promotion"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + PrintICP("print-icp", + cl::desc("print functions after indirect call promotion"), + cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt -PrintInline("print-inline", - cl::desc("print functions after inlining optimization"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + PrintInline("print-inline", + cl::desc("print functions after inlining optimization"), + cl::Hidden, cl::cat(BoltOptCategory)); -static cl::opt -PrintJTFootprintReduction("print-after-jt-footprint-reduction", - cl::desc("print function after jt-footprint-reduction pass"), - cl::ZeroOrMore, cl::cat(BoltOptCategory)); +static cl::opt PrintJTFootprintReduction( + "print-after-jt-footprint-reduction", + cl::desc("print function after jt-footprint-reduction pass"), + cl::cat(BoltOptCategory)); static cl::opt -PrintLongJmp("print-longjmp", - cl::desc("print functions after longjmp pass"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + PrintLongJmp("print-longjmp", + cl::desc("print functions after longjmp pass"), cl::Hidden, + cl::cat(BoltOptCategory)); cl::opt -PrintNormalized("print-normalized", - cl::desc("print functions after CFG is normalized"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltCategory)); + PrintNormalized("print-normalized", + cl::desc("print functions after CFG is normalized"), + cl::Hidden, cl::cat(BoltCategory)); -static cl::opt -PrintOptimizeBodyless("print-optimize-bodyless", - cl::desc("print functions after bodyless optimization"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); +static cl::opt PrintOptimizeBodyless( + "print-optimize-bodyless", + cl::desc("print functions after bodyless optimization"), cl::Hidden, + cl::cat(BoltOptCategory)); static cl::opt -PrintPeepholes("print-peepholes", - cl::desc("print functions after peephole optimization"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + PrintPeepholes("print-peepholes", + cl::desc("print functions after peephole optimization"), + cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt -PrintPLT("print-plt", - cl::desc("print functions after PLT optimization"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + PrintPLT("print-plt", cl::desc("print functions after PLT optimization"), + cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt -PrintProfileStats("print-profile-stats", - cl::desc("print profile quality/bias analysis"), - cl::ZeroOrMore, cl::init(false), cl::cat(BoltCategory)); + PrintProfileStats("print-profile-stats", + cl::desc("print profile quality/bias analysis"), + cl::cat(BoltCategory)); static cl::opt -PrintRegReAssign("print-regreassign", - cl::desc("print functions after regreassign pass"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + PrintRegReAssign("print-regreassign", + cl::desc("print functions after regreassign pass"), + cl::Hidden, cl::cat(BoltOptCategory)); cl::opt -PrintReordered("print-reordered", - cl::desc("print functions after layout optimization"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + PrintReordered("print-reordered", + cl::desc("print functions after layout optimization"), + cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt -PrintReorderedFunctions("print-reordered-functions", - cl::desc("print functions after clustering"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + PrintReorderedFunctions("print-reordered-functions", + cl::desc("print functions after clustering"), + cl::Hidden, cl::cat(BoltOptCategory)); -static cl::opt -PrintRetpolineInsertion("print-retpoline-insertion", - cl::desc("print functions after retpoline insertion pass"), - cl::init(false), cl::ZeroOrMore, cl::cat(BoltCategory)); +static cl::opt PrintRetpolineInsertion( + "print-retpoline-insertion", + cl::desc("print functions after retpoline insertion pass"), + cl::cat(BoltCategory)); -static cl::opt -PrintSCTC("print-sctc", - cl::desc("print functions after conditional tail call simplification"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); +static cl::opt PrintSCTC( + "print-sctc", + cl::desc("print functions after conditional tail call simplification"), + cl::Hidden, cl::cat(BoltOptCategory)); -static cl::opt -PrintSimplifyROLoads("print-simplify-rodata-loads", - cl::desc("print functions after simplification of RO data loads"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); +static cl::opt PrintSimplifyROLoads( + "print-simplify-rodata-loads", + cl::desc("print functions after simplification of RO data loads"), + cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt -PrintSplit("print-split", - cl::desc("print functions after code splitting"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + PrintSplit("print-split", cl::desc("print functions after code splitting"), + cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt -PrintStoke("print-stoke", - cl::desc("print functions after stoke analysis"), - cl::init(false), cl::ZeroOrMore, cl::cat(BoltOptCategory)); + PrintStoke("print-stoke", cl::desc("print functions after stoke analysis"), + cl::cat(BoltOptCategory)); -static cl::opt -PrintVeneerElimination("print-veneer-elimination", - cl::desc("print functions after veneer elimination pass"), - cl::init(false), cl::ZeroOrMore, cl::cat(BoltOptCategory)); +static cl::opt PrintVeneerElimination( + "print-veneer-elimination", + cl::desc("print functions after veneer elimination pass"), + cl::cat(BoltOptCategory)); static cl::opt -PrintUCE("print-uce", - cl::desc("print functions after unreachable code elimination"), - cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); + PrintUCE("print-uce", + cl::desc("print functions after unreachable code elimination"), + cl::Hidden, cl::cat(BoltOptCategory)); -static cl::opt -RegReAssign("reg-reassign", - cl::desc("reassign registers so as to avoid using REX prefixes in hot code"), - cl::init(false), cl::ZeroOrMore, cl::cat(BoltOptCategory)); +static cl::opt RegReAssign( + "reg-reassign", + cl::desc( + "reassign registers so as to avoid using REX prefixes in hot code"), + cl::cat(BoltOptCategory)); -static cl::opt -SimplifyConditionalTailCalls("simplify-conditional-tail-calls", - cl::desc("simplify conditional tail calls by removing unnecessary jumps"), - cl::init(true), cl::ZeroOrMore, cl::cat(BoltOptCategory)); +static cl::opt SimplifyConditionalTailCalls( + "simplify-conditional-tail-calls", + cl::desc("simplify conditional tail calls by removing unnecessary jumps"), + cl::init(true), cl::cat(BoltOptCategory)); -static cl::opt -SimplifyRODataLoads("simplify-rodata-loads", - cl::desc("simplify loads from read-only sections by replacing the memory " - "operand with the constant found in the corresponding section"), - cl::ZeroOrMore, cl::cat(BoltOptCategory)); +static cl::opt SimplifyRODataLoads( + "simplify-rodata-loads", + cl::desc("simplify loads from read-only sections by replacing the memory " + "operand with the constant found in the corresponding section"), + cl::cat(BoltOptCategory)); static cl::list SpecializeMemcpy1("memcpy1-spec", @@ -218,39 +211,31 @@ SpecializeMemcpy1("memcpy1-spec", cl::value_desc("func1,func2:cs1:cs2,func3:cs1,..."), cl::ZeroOrMore, cl::cat(BoltOptCategory)); -static cl::opt -Stoke("stoke", - cl::desc("turn on the stoke analysis"), - cl::init(false), cl::ZeroOrMore, cl::cat(BoltOptCategory)); - -static cl::opt -StringOps("inline-memcpy", - cl::desc("inline memcpy using 'rep movsb' instruction (X86-only)"), - cl::init(false), cl::ZeroOrMore, cl::cat(BoltOptCategory)); +static cl::opt Stoke("stoke", cl::desc("turn on the stoke analysis"), + cl::cat(BoltOptCategory)); -static cl::opt -StripRepRet("strip-rep-ret", - cl::desc("strip 'repz' prefix from 'repz retq' sequence (on by default)"), - cl::init(true), cl::ZeroOrMore, cl::cat(BoltOptCategory)); +static cl::opt StringOps( + "inline-memcpy", + cl::desc("inline memcpy using 'rep movsb' instruction (X86-only)"), + cl::cat(BoltOptCategory)); -static cl::opt -VerifyCFG("verify-cfg", - cl::desc("verify the CFG after every pass"), - cl::init(false), cl::Hidden, cl::ZeroOrMore, cl::cat(BoltOptCategory)); +static cl::opt StripRepRet( + "strip-rep-ret", + cl::desc("strip 'repz' prefix from 'repz retq' sequence (on by default)"), + cl::init(true), cl::cat(BoltOptCategory)); -static cl::opt -TailDuplicationFlag("tail-duplication", - cl::desc("duplicate unconditional branches that cross a cache line"), - cl::ZeroOrMore, cl::ReallyHidden, cl::cat(BoltOptCategory)); +static cl::opt VerifyCFG("verify-cfg", + cl::desc("verify the CFG after every pass"), + cl::Hidden, cl::cat(BoltOptCategory)); -static cl::opt -ThreeWayBranchFlag("three-way-branch", - cl::desc("reorder three way branches"), - cl::ZeroOrMore, cl::ReallyHidden, cl::cat(BoltOptCategory)); +static cl::opt ThreeWayBranchFlag("three-way-branch", + cl::desc("reorder three way branches"), + cl::ReallyHidden, + cl::cat(BoltOptCategory)); static cl::opt CMOVConversionFlag("cmov-conversion", cl::desc("fold jcc+mov into cmov"), - cl::ZeroOrMore, cl::ReallyHidden, + cl::ReallyHidden, cl::cat(BoltOptCategory)); } // namespace opts @@ -396,8 +381,7 @@ void BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) { Manager.registerPass(std::make_unique()); - Manager.registerPass(std::make_unique(), - opts::TailDuplicationFlag); + Manager.registerPass(std::make_unique()); Manager.registerPass(std::make_unique(), opts::CMOVConversionFlag); diff --git a/bolt/lib/Rewrite/BoltDiff.cpp b/bolt/lib/Rewrite/BoltDiff.cpp index fc7fb8efa2435..b1ea6d50692a8 100644 --- a/bolt/lib/Rewrite/BoltDiff.cpp +++ b/bolt/lib/Rewrite/BoltDiff.cpp @@ -28,76 +28,58 @@ extern cl::OptionCategory BoltDiffCategory; extern cl::opt NeverPrint; extern cl::opt ICF; -static cl::opt -IgnoreLTOSuffix("ignore-lto-suffix", - cl::desc("ignore lto_priv or const suffixes when matching functions"), - cl::init(true), - cl::ZeroOrMore, - cl::cat(BoltDiffCategory)); - -static cl::opt -PrintUnmapped("print-unmapped", - cl::desc("print functions of binary 2 that were not matched to any " - "function in binary 1"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltDiffCategory)); - -static cl::opt -PrintProfiledUnmapped("print-profiled-unmapped", - cl::desc("print functions that have profile in binary 1 but do not " - "in binary 2"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltDiffCategory)); - -static cl::opt -PrintDiffCFG("print-diff-cfg", - cl::desc("print the CFG of important functions that changed in " - "binary 2"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltDiffCategory)); - -static cl::opt -PrintDiffBBs("print-diff-bbs", - cl::desc("print the basic blocks showed in top differences"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltDiffCategory)); - -static cl::opt -MatchByHash("match-by-hash", - cl::desc("match functions in binary 2 to binary 1 if they have the same " - "hash of a function in binary 1"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltDiffCategory)); - -static cl::opt -IgnoreUnchanged("ignore-unchanged", - cl::desc("do not diff functions whose contents have not been changed from " - "one binary to another"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltDiffCategory)); - -static cl::opt -DisplayCount("display-count", - cl::desc("number of functions to display when printing the top largest " - "differences in function activity"), - cl::init(10), - cl::ZeroOrMore, - cl::cat(BoltDiffCategory)); +static cl::opt IgnoreLTOSuffix( + "ignore-lto-suffix", + cl::desc("ignore lto_priv or const suffixes when matching functions"), + cl::init(true), cl::cat(BoltDiffCategory)); + +static cl::opt PrintUnmapped( + "print-unmapped", + cl::desc("print functions of binary 2 that were not matched to any " + "function in binary 1"), + cl::cat(BoltDiffCategory)); + +static cl::opt PrintProfiledUnmapped( + "print-profiled-unmapped", + cl::desc("print functions that have profile in binary 1 but do not " + "in binary 2"), + cl::cat(BoltDiffCategory)); + +static cl::opt PrintDiffCFG( + "print-diff-cfg", + cl::desc("print the CFG of important functions that changed in " + "binary 2"), + cl::cat(BoltDiffCategory)); static cl::opt -NormalizeByBin1("normalize-by-bin1", - cl::desc("show execution count of functions in binary 2 as a ratio of the " - "total samples in binary 1 - make sure both profiles have equal " - "collection time and sampling rate for this to make sense"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltDiffCategory)); + PrintDiffBBs("print-diff-bbs", + cl::desc("print the basic blocks showed in top differences"), + cl::cat(BoltDiffCategory)); + +static cl::opt MatchByHash( + "match-by-hash", + cl::desc("match functions in binary 2 to binary 1 if they have the same " + "hash of a function in binary 1"), + cl::cat(BoltDiffCategory)); + +static cl::opt IgnoreUnchanged( + "ignore-unchanged", + cl::desc("do not diff functions whose contents have not been changed from " + "one binary to another"), + cl::cat(BoltDiffCategory)); + +static cl::opt DisplayCount( + "display-count", + cl::desc("number of functions to display when printing the top largest " + "differences in function activity"), + cl::init(10), cl::cat(BoltDiffCategory)); + +static cl::opt NormalizeByBin1( + "normalize-by-bin1", + cl::desc("show execution count of functions in binary 2 as a ratio of the " + "total samples in binary 1 - make sure both profiles have equal " + "collection time and sampling rate for this to make sense"), + cl::cat(BoltDiffCategory)); } // end namespace opts diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp index 9175c5c592a0a..f0d6a4db0244b 100644 --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -39,6 +39,8 @@ #include #include #include +#include +#include #undef DEBUG_TYPE #define DEBUG_TYPE "bolt" @@ -55,25 +57,6 @@ static void printDie(const DWARFDie &DIE) { namespace llvm { namespace bolt { -/// Finds attributes FormValue and Offset. -/// -/// \param DIE die to look up in. -/// \param Attr the attribute to extract. -/// \return an optional AttrInfo with DWARFFormValue and Offset. -static Optional findAttributeInfo(const DWARFDie DIE, - dwarf::Attribute Attr) { - if (!DIE.isValid()) - return None; - const DWARFAbbreviationDeclaration *AbbrevDecl = - DIE.getAbbreviationDeclarationPtr(); - if (!AbbrevDecl) - return None; - Optional Index = AbbrevDecl->findAttributeIndex(Attr); - if (!Index) - return None; - return findAttributeInfo(DIE, AbbrevDecl, *Index); -} - /// Finds attributes FormValue and Offset. /// /// \param DIE die to look up in. @@ -100,12 +83,11 @@ extern cl::OptionCategory BoltCategory; extern cl::opt Verbosity; extern cl::opt OutputFilename; -static cl::opt -KeepARanges("keep-aranges", - cl::desc("keep or generate .debug_aranges section if .gdb_index is written"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); +static cl::opt KeepARanges( + "keep-aranges", + cl::desc( + "keep or generate .debug_aranges section if .gdb_index is written"), + cl::Hidden, cl::cat(BoltCategory)); static cl::opt DeterministicDebugInfo("deterministic-debuginfo", @@ -191,10 +173,12 @@ void DWARFRewriter::updateDebugInfo() { AbbrevWriter = std::make_unique(*BC.DwCtx); - if (BC.isDWARF5Used()) { - // Disabling none deterministic mode for dwarf5, to keep implementation - // simpler. + if (!opts::DeterministicDebugInfo) { opts::DeterministicDebugInfo = true; + errs() << "BOLT-WARNING: --deterministic-debuginfo is being deprecated\n"; + } + + if (BC.isDWARF5Used()) { AddrWriter = std::make_unique(&BC); RangesSectionWriter = std::make_unique(); DebugRangeListsSectionWriter::setAddressWriter(AddrWriter.get()); @@ -209,14 +193,9 @@ void DWARFRewriter::updateDebugInfo() { for (std::unique_ptr &CU : BC.DwCtx->compile_units()) { const uint16_t DwarfVersion = CU->getVersion(); if (DwarfVersion >= 5) { - uint32_t AttrInfoOffset = - DebugLoclistWriter::InvalidLocListsBaseAttrOffset; - if (Optional AttrInfoVal = - findAttributeInfo(CU->getUnitDIE(), dwarf::DW_AT_loclists_base)) { - AttrInfoOffset = AttrInfoVal->Offset; - LocListWritersByCU[CUIndex] = std::make_unique( - &BC, *CU.get(), AttrInfoOffset, DwarfVersion, false); - } + LocListWritersByCU[CUIndex] = + std::make_unique(*CU.get(), DwarfVersion, false); + if (Optional DWOId = CU->getDWOId()) { assert(LocListWritersByCU.count(*DWOId) == 0 && "RangeLists writer for DWO unit already exists."); @@ -227,7 +206,7 @@ void DWARFRewriter::updateDebugInfo() { } } else { - LocListWritersByCU[CUIndex] = std::make_unique(&BC); + LocListWritersByCU[CUIndex] = std::make_unique(); } if (Optional DWOId = CU->getDWOId()) { @@ -235,10 +214,8 @@ void DWARFRewriter::updateDebugInfo() { "LocList writer for DWO unit already exists."); // Work around some bug in llvm-15. If I pass in directly lld reports // undefined symbol. - auto constexpr WorkAround = - DebugLoclistWriter::InvalidLocListsBaseAttrOffset; - LocListWritersByCU[*DWOId] = std::make_unique( - &BC, *CU.get(), WorkAround, DwarfVersion, true); + LocListWritersByCU[*DWOId] = + std::make_unique(*CU.get(), DwarfVersion, true); } ++CUIndex; } @@ -318,6 +295,7 @@ void DWARFRewriter::updateDebugInfo() { createBinaryDWOAbbrevWriter((*SplitCU)->getContext(), *DWOId); updateUnitDebugInfo(*(*SplitCU), *DwoDebugInfoPatcher, *DWOAbbrevWriter, *DebugLocWriter, *TempRangesSectionWriter); + DebugLocWriter->finalize(*DwoDebugInfoPatcher, *DWOAbbrevWriter); DwoDebugInfoPatcher->clearDestinationLabels(); if (!DwoDebugInfoPatcher->getWasRangBasedUsed()) RangesBase = None; @@ -341,6 +319,7 @@ void DWARFRewriter::updateDebugInfo() { DebugInfoPatcher->addUnitBaseOffsetLabel(Unit->getOffset()); updateUnitDebugInfo(*Unit, *DebugInfoPatcher, *AbbrevWriter, *DebugLocWriter, *RangesSectionWriter, RangesBase); + DebugLocWriter->finalize(*DebugInfoPatcher, *AbbrevWriter); if (Unit->getVersion() >= 5) RangesSectionWriter.get()->finalizeSection(); }; @@ -387,6 +366,10 @@ void DWARFRewriter::updateUnitDebugInfo( DWARFDataExtractor DebugInfoData = Unit.getDebugInfoExtractor(); uint32_t Depth = 0; + bool IsDWP = false; + if (DWARFContext *DWOCtx = BC.getDWOContext()) + IsDWP = !DWOCtx->getCUIndex().getRows().empty(); + while ( DIEOffset < NextCUOffset && Die.extractFast(Unit, &DIEOffset, DebugInfoData, NextCUOffset, Depth)) { @@ -517,7 +500,8 @@ void DWARFRewriter::updateUnitDebugInfo( if (SectionAddress) BaseAddress = SectionAddress->Address; - if (Unit.getVersion() >= 5) { + if (Unit.getVersion() >= 5 && + AttrVal->V.getForm() == dwarf::DW_FORM_loclistx) { Optional LocOffset = Unit.getLoclistOffset(Offset); assert(LocOffset && "Location Offset is invalid."); Offset = *LocOffset; @@ -545,7 +529,7 @@ void DWARFRewriter::updateUnitDebugInfo( BaseAddress + Entry.Value0, BaseAddress + Entry.Value1, Entry.Loc}); break; - case dwarf::DW_RLE_start_length: + case dwarf::DW_LLE_start_length: InputLL.emplace_back(DebugLocationEntry{ Entry.Value0, Entry.Value0 + Entry.Value1, Entry.Loc}); break; @@ -604,24 +588,8 @@ void DWARFRewriter::updateUnitDebugInfo( // information. OutputLL = InputLL; } - uint32_t LocListIndex = 0; - dwarf::Form Form = Value.getForm(); - if (Form == dwarf::DW_FORM_sec_offset || - Form == dwarf::DW_FORM_data4) { - // For DWARF5 we can access location list entry either using - // index, or offset. If it's offset, then it's from begnning of - // the file. This implementation was before we could add entries - // to the DIE. For DWARF4 this is no-op. - // TODO: For DWARF5 convert all the offset based entries to index - // based, and insert loclist_base if necessary. - LocListIndex = DebugLoclistWriter::InvalidIndex; - } else if (Form == dwarf::DW_FORM_loclistx) { - LocListIndex = Value.getRawUValue(); - } else { - llvm_unreachable("Unsupported LocList access Form."); - } - DebugLocWriter.addList(AttrOffset, LocListIndex, - std::move(OutputLL)); + DebugLocWriter.addList(*AttrVal, OutputLL, DebugInfoPatcher, + AbbrevWriter); } } else { assert((Value.isFormClass(DWARFFormValue::FC_Exprloc) || @@ -718,6 +686,20 @@ void DWARFRewriter::updateUnitDebugInfo( errs() << "BOLT-WARNING: unexpected form value for attribute at 0x" << Twine::utohexstr(AttrOffset); } + } else if (IsDWP && Unit.isDWOUnit()) { + // Not a common path so don't want to search all DIEs all the time. + Optional SignatureAttrVal = + findAttributeInfo(DIE, dwarf::DW_AT_signature); + if (!SignatureAttrVal) + continue; + // If input is DWP file we need to keep track of which TU came from each + // CU, so we can write it out correctly. + if (Optional Val = SignatureAttrVal->V.getAsReferenceUVal()) + TypeSignaturesPerCU[*DIE.getDwarfUnit()->getDWOId()].insert(*Val); + else { + errs() << "BOT-ERROR: DW_AT_signature form is not supported.\n"; + exit(1); + } } } } @@ -971,17 +953,19 @@ DWARFRewriter::finalizeDebugSections(DebugInfoBinaryPatcher &DebugInfoPatcher) { if (BC.isDWARF5Used()) { std::unique_ptr LocationListSectionContents = makeFinalLocListsSection(DebugInfoPatcher, DWARFVersion::DWARF5); - BC.registerOrUpdateNoteSection(".debug_loclists", - copyByteArray(*LocationListSectionContents), - LocationListSectionContents->size()); + if (!LocationListSectionContents->empty()) + BC.registerOrUpdateNoteSection( + ".debug_loclists", copyByteArray(*LocationListSectionContents), + LocationListSectionContents->size()); } if (BC.isDWARFLegacyUsed()) { std::unique_ptr LocationListSectionContents = makeFinalLocListsSection(DebugInfoPatcher, DWARFVersion::DWARFLegacy); - BC.registerOrUpdateNoteSection(".debug_loc", - copyByteArray(*LocationListSectionContents), - LocationListSectionContents->size()); + if (!LocationListSectionContents->empty()) + BC.registerOrUpdateNoteSection( + ".debug_loc", copyByteArray(*LocationListSectionContents), + LocationListSectionContents->size()); } // AddrWriter should be finalized after debug_loc since more addresses can be @@ -1148,7 +1132,7 @@ updateDebugData(DWARFContext &DWCtx, std::string &Storage, StringRef SectionName, StringRef SectionContents, const StringMap &KnownSections, MCStreamer &Streamer, DWARFRewriter &Writer, - const DWARFUnitIndex::Entry *DWOEntry, uint64_t DWOId, + const DWARFUnitIndex::Entry *CUDWOEntry, uint64_t DWOId, std::unique_ptr &OutputBuffer, DebugRangeListsSectionWriter *RangeListsWriter) { auto applyPatch = [&](DebugInfoBinaryPatcher *Patcher, @@ -1174,7 +1158,8 @@ updateDebugData(DWARFContext &DWCtx, std::string &Storage, auto SectionIter = KnownSections.find(SectionName); if (SectionIter == KnownSections.end()) return None; - Streamer.SwitchSection(SectionIter->second.first); + + Streamer.switchSection(SectionIter->second.first); StringRef OutData = SectionContents; uint32_t DWPOffset = 0; @@ -1186,18 +1171,18 @@ updateDebugData(DWARFContext &DWCtx, std::string &Storage, return OutData; } case DWARFSectionKind::DW_SECT_INFO: { - OutData = getSliceData(DWOEntry, OutData, DWARFSectionKind::DW_SECT_INFO, + OutData = getSliceData(CUDWOEntry, OutData, DWARFSectionKind::DW_SECT_INFO, DWPOffset); DebugInfoBinaryPatcher *Patcher = llvm::cast( Writer.getBinaryDWODebugInfoPatcher(DWOId)); return applyPatch(Patcher, OutData); } case DWARFSectionKind::DW_SECT_EXT_TYPES: { - return getSliceData(DWOEntry, OutData, DWARFSectionKind::DW_SECT_EXT_TYPES, + return getSliceData(nullptr, OutData, DWARFSectionKind::DW_SECT_EXT_TYPES, DWPOffset); } case DWARFSectionKind::DW_SECT_STR_OFFSETS: { - return getSliceData(DWOEntry, OutData, + return getSliceData(CUDWOEntry, OutData, DWARFSectionKind::DW_SECT_STR_OFFSETS, DWPOffset); } case DWARFSectionKind::DW_SECT_ABBREV: { @@ -1220,7 +1205,7 @@ updateDebugData(DWARFContext &DWCtx, std::string &Storage, OutputBuffer->size()); } case DWARFSectionKind::DW_SECT_LINE: { - return getSliceData(DWOEntry, OutData, DWARFSectionKind::DW_SECT_LINE, + return getSliceData(CUDWOEntry, OutData, DWARFSectionKind::DW_SECT_LINE, DWPOffset); } case DWARFSectionKind::DW_SECT_RNGLISTS: { @@ -1233,6 +1218,87 @@ updateDebugData(DWARFContext &DWCtx, std::string &Storage, } // namespace +struct TUContribution { + uint64_t Signature{0}; + uint32_t Length{0}; +}; +using TUContributionVector = std::vector; +/// Iterates over all the signatures used in this CU, and +/// uses TU Index to extract their contributions from the DWP file. +/// It stores them in DWOTUSection. +static std::string extractDWOTUFromDWP( + const DWARFRewriter::DebugTypesSignaturesPerCUMap &TypeSignaturesPerCU, + const DWARFUnitIndex &TUIndex, StringRef Contents, + TUContributionVector &TUContributionsToCU, uint64_t DWOId) { + std::string DWOTUSection; + using TUEntry = + std::pair; + std::vector TUContributions; + for (const uint64_t TUSignature : TypeSignaturesPerCU.at(DWOId)) { + const DWARFUnitIndex::Entry *TUDWOEntry = TUIndex.getFromHash(TUSignature); + const DWARFUnitIndex::Entry::SectionContribution *C = + TUDWOEntry->getContribution(DW_SECT_EXT_TYPES); + TUContributions.emplace_back(TUSignature, C); + } + + // Sorting so it's easy to compare output. + // They should be sharing the same Abbrev. + std::sort(TUContributions.begin(), TUContributions.end(), + [](const TUEntry &V1, const TUEntry &V2) -> bool { + return V1.second->Offset < V2.second->Offset; + }); + + for (auto &PairEntry : TUContributions) { + const DWARFUnitIndex::Entry::SectionContribution *C = PairEntry.second; + const uint64_t TUSignature = PairEntry.first; + DWOTUSection.append(Contents.slice(C->Offset, C->Offset + C->Length).str()); + TUContributionsToCU.push_back({TUSignature, C->Length}); + } + return DWOTUSection; +} + +static void extractDWOTUFromDWO(StringRef Contents, + TUContributionVector &TUContributionsToCU) { + uint64_t Offset = 0; + DataExtractor Data(Contents, true, 0); + while (Data.isValidOffset(Offset)) { + auto PrevOffset = Offset; + // Length of the unit, including the 4 byte length field. + const uint32_t Length = Data.getU32(&Offset) + 4; + + Data.getU16(&Offset); // Version + Data.getU32(&Offset); // Abbrev offset + Data.getU8(&Offset); // Address size + const auto TUSignature = Data.getU64(&Offset); + Offset = PrevOffset + Length; + TUContributionsToCU.push_back({TUSignature, Length}); + } +} + +static void extractTypesFromDWPDWARF5( + const MCObjectFileInfo &MCOFI, const DWARFUnitIndex &TUIndex, + const DWARFRewriter::DebugTypesSignaturesPerCUMap &TypeSignaturesPerCU, + MCStreamer &Streamer, StringRef Contents, uint64_t DWOId) { + std::vector + TUContributions; + for (const uint64_t Val : TypeSignaturesPerCU.at(DWOId)) { + const DWARFUnitIndex::Entry *TUE = TUIndex.getFromHash(Val); + const DWARFUnitIndex::Entry::SectionContribution *C = + TUE->getContribution(DWARFSectionKind::DW_SECT_INFO); + TUContributions.push_back(C); + } + // Sorting so it's easy to compare output. + // They should be sharing the same Abbrev. + std::sort(TUContributions.begin(), TUContributions.end(), + [](const DWARFUnitIndex::Entry::SectionContribution *V1, + const DWARFUnitIndex::Entry::SectionContribution *V2) -> bool { + return V1->Offset < V2->Offset; + }); + Streamer.switchSection(MCOFI.getDwarfInfoDWOSection()); + for (const auto *C : TUContributions) + Streamer.emitBytes(Contents.slice(C->Offset, C->Offset + C->Length)); +} + void DWARFRewriter::writeDWP( std::unordered_map &DWOIdToName) { SmallString<0> OutputNameStr; @@ -1270,14 +1336,18 @@ void DWARFRewriter::writeDWP( std::deque> UncompressedSections; DWPStringPool Strings(*Streamer, StrSection); MapVector IndexEntries; - constexpr uint32_t IndexVersion = 2; + MapVector TypeIndexEntries; + uint16_t Version = 0; + uint32_t IndexVersion = 2; // Setup DWP code once. DWARFContext *DWOCtx = BC.getDWOContext(); const DWARFUnitIndex *CUIndex = nullptr; + const DWARFUnitIndex *TUIndex = nullptr; bool IsDWP = false; if (DWOCtx) { CUIndex = &DWOCtx->getCUIndex(); + TUIndex = &DWOCtx->getTUIndex(); IsDWP = !CUIndex->getRows().empty(); } @@ -1291,7 +1361,14 @@ void DWARFRewriter::writeDWP( if (!DWOCU) continue; - assert(CU->getVersion() <= 4 && "For DWP output only DWARF4 is supported"); + if (Version == 0) { + Version = CU->getVersion(); + IndexVersion = Version < 5 ? 2 : 5; + } else if (Version != CU->getVersion()) { + errs() << "BOLT-ERROR: Incompatible DWARF compile unit versions.\n"; + exit(1); + } + UnitIndexEntry CurEntry = {}; CurEntry.DWOName = dwarf::toString(CU->getUnitDIE().find( @@ -1308,9 +1385,9 @@ void DWARFRewriter::writeDWP( // i.e. offset and length, of each compile/type unit to a section. std::vector> SectionLength; - const DWARFUnitIndex::Entry *DWOEntry = nullptr; + const DWARFUnitIndex::Entry *CUDWOEntry = nullptr; if (IsDWP) - DWOEntry = CUIndex->getFromHash(*DWOId); + CUDWOEntry = CUIndex->getFromHash(*DWOId); bool StrSectionWrittenOut = false; const object::ObjectFile *DWOFile = @@ -1322,27 +1399,46 @@ void DWARFRewriter::writeDWP( "No RangeListsWriter for DWO ID."); RangeListssWriter = RangeListsWritersByCU[*DWOId].get(); } + std::string DWOTUSection; + TUContributionVector TUContributionsToCU; for (const SectionRef &Section : DWOFile->sections()) { + std::string DWOTUSection; std::string Storage = ""; std::unique_ptr OutputData; StringRef SectionName = getSectionName(Section); - Expected Contents = Section.getContents(); - assert(Contents && "Invalid contents."); - Optional TOutData = - updateDebugData((*DWOCU)->getContext(), Storage, SectionName, - *Contents, KnownSections, *Streamer, *this, DWOEntry, - *DWOId, OutputData, RangeListssWriter); + Expected ContentsExp = Section.getContents(); + assert(ContentsExp && "Invalid contents."); + StringRef Contents = *ContentsExp; + const bool IsTypesDWO = SectionName == "debug_types.dwo"; + if (IsDWP && IsTypesDWO) { + assert(TUIndex && + "DWP Input with .debug_types.dwo section with TU Index."); + DWOTUSection = + extractDWOTUFromDWP(TypeSignaturesPerCU, *TUIndex, Contents, + TUContributionsToCU, *DWOId); + Contents = DWOTUSection; + } else if (IsTypesDWO) { + extractDWOTUFromDWO(Contents, TUContributionsToCU); + } + + Optional TOutData = updateDebugData( + (*DWOCU)->getContext(), Storage, SectionName, Contents, KnownSections, + *Streamer, *this, CUDWOEntry, *DWOId, OutputData, RangeListssWriter); if (!TOutData) continue; StringRef OutData = *TOutData; - StringRef Name = getSectionName(Section); - if (Name.equals("debug_str.dwo")) { + if (IsTypesDWO) { + Streamer->emitBytes(OutData); + continue; + } + + if (SectionName.equals("debug_str.dwo")) { CurStrSection = OutData; } else { // Since handleDebugDataPatching returned true, we already know this is // a known section. - auto SectionIter = KnownSections.find(Name); + auto SectionIter = KnownSections.find(SectionName); if (SectionIter->second.second == DWARFSectionKind::DW_SECT_STR_OFFSETS) CurStrOffsetSection = OutData; else @@ -1372,15 +1468,42 @@ void DWARFRewriter::writeDWP( errs() << "BOLT-ERROR: " << toString(std::move(Err)) << "\n"; return; } + + // Handling TU + if (!TUContributionsToCU.empty()) { + const unsigned Index = + getContributionIndex(DW_SECT_EXT_TYPES, IndexVersion); + for (const TUContribution &TUC : TUContributionsToCU) { + UnitIndexEntry TUEntry = CurEntry; + TUEntry.Contributions[0] = {}; + TUEntry.Contributions[Index].Offset = ContributionOffsets[Index]; + TUEntry.Contributions[Index].Length = TUC.Length; + ContributionOffsets[Index] += TUEntry.Contributions[Index].Length; + TypeIndexEntries.insert(std::make_pair(TUC.Signature, TUEntry)); + } + } } - // Lie about the type contribution for DWARF < 5. In DWARFv5 the type - // section does not exist, so no need to do anything about this. - ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0; + if (Version < 5) { + // Lie about there being no info contributions so the TU index only includes + // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a + // contribution to the info section, so we do not want to lie about it. + ContributionOffsets[0] = 0; + } + writeIndex(*Streamer.get(), MCOFI.getDwarfTUIndexSection(), + ContributionOffsets, TypeIndexEntries, IndexVersion); + + if (Version < 5) { + // Lie about the type contribution for DWARF < 5. In DWARFv5 the type + // section does not exist, so no need to do anything about this. + ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0; + // Unlie about the info contribution + ContributionOffsets[0] = 1; + } writeIndex(*Streamer.get(), MCOFI.getDwarfCUIndexSection(), ContributionOffsets, IndexEntries, IndexVersion); - Streamer->Finish(); + Streamer->finish(); Out->keep(); } @@ -1389,9 +1512,11 @@ void DWARFRewriter::writeDWOFiles( // Setup DWP code once. DWARFContext *DWOCtx = BC.getDWOContext(); const DWARFUnitIndex *CUIndex = nullptr; + const DWARFUnitIndex *TUIndex = nullptr; bool IsDWP = false; if (DWOCtx) { CUIndex = &DWOCtx->getCUIndex(); + TUIndex = &DWOCtx->getTUIndex(); IsDWP = !CUIndex->getRows().empty(); } @@ -1415,16 +1540,16 @@ void DWARFRewriter::writeDWOFiles( std::unique_ptr TempOut = std::make_unique(FullPath, EC, sys::fs::OF_None); - const DWARFUnitIndex::Entry *DWOEntry = nullptr; + const DWARFUnitIndex::Entry *CUDWOEntry = nullptr; if (IsDWP) - DWOEntry = CUIndex->getFromHash(*DWOId); + CUDWOEntry = CUIndex->getFromHash(*DWOId); const object::ObjectFile *File = (*DWOCU)->getContext().getDWARFObj().getFile(); std::unique_ptr TmpBC = createDwarfOnlyBC(*File); std::unique_ptr Streamer = TmpBC->createStreamer(TempOut->os()); - StringMap KnownSections = - createKnownSectionsMap(*Streamer->getContext().getObjectFileInfo()); + const MCObjectFileInfo &MCOFI = *Streamer->getContext().getObjectFileInfo(); + StringMap KnownSections = createKnownSectionsMap(MCOFI); DebugRangeListsSectionWriter *RangeListssWriter = nullptr; if (CU->getVersion() == 5) { @@ -1439,26 +1564,45 @@ void DWARFRewriter::writeDWOFiles( std::unique_ptr OutputData; if (Optional OutData = updateDebugData( (*DWOCU)->getContext(), Storage, "debug_rnglists.dwo", "", - KnownSections, *Streamer, *this, DWOEntry, *DWOId, OutputData, + KnownSections, *Streamer, *this, CUDWOEntry, *DWOId, OutputData, RangeListssWriter)) Streamer->emitBytes(*OutData); } } + + TUContributionVector TUContributionsToCU; for (const SectionRef &Section : File->sections()) { std::string Storage = ""; + std::string DWOTUSection; std::unique_ptr OutputData; StringRef SectionName = getSectionName(Section); if (SectionName == "debug_rnglists.dwo") continue; - Expected Contents = Section.getContents(); - assert(Contents && "Invalid contents."); - if (Optional OutData = - updateDebugData((*DWOCU)->getContext(), Storage, SectionName, - *Contents, KnownSections, *Streamer, *this, - DWOEntry, *DWOId, OutputData, RangeListssWriter)) + Expected ContentsExp = Section.getContents(); + assert(ContentsExp && "Invalid contents."); + StringRef Contents = *ContentsExp; + if (IsDWP && SectionName == "debug_types.dwo") { + assert(TUIndex && + "DWP Input with .debug_types.dwo section with TU Index."); + DWOTUSection = + extractDWOTUFromDWP(TypeSignaturesPerCU, *TUIndex, Contents, + TUContributionsToCU, *DWOId); + Contents = DWOTUSection; + } else if (IsDWP && CU->getVersion() >= 5 && + SectionName == "debug_info.dwo") { + assert(TUIndex && + "DWP Input with .debug_types.dwo section with TU Index."); + extractTypesFromDWPDWARF5(MCOFI, *TUIndex, TypeSignaturesPerCU, + *Streamer, Contents, *DWOId); + } + + if (Optional OutData = updateDebugData( + (*DWOCU)->getContext(), Storage, SectionName, Contents, + KnownSections, *Streamer, *this, CUDWOEntry, *DWOId, OutputData, + RangeListssWriter)) Streamer->emitBytes(*OutData); } - Streamer->Finish(); + Streamer->finish(); TempOut->keep(); } } @@ -1584,49 +1728,37 @@ void DWARFRewriter::updateGdbIndexSection(CUOffsetMap &CUMap) { NewGdbIndexSize); } -std::unique_ptr -DWARFRewriter::makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher, - DWARFVersion Version) { +std::unique_ptr DWARFRewriter::makeFinalLocListsSection( + DebugInfoBinaryPatcher &DebugInfoPatcher, DWARFVersion Version) { auto LocBuffer = std::make_unique(); auto LocStream = std::make_unique(*LocBuffer); auto Writer = std::unique_ptr(BC.createObjectWriter(*LocStream)); - uint64_t SectionOffset = 0; - // Add an empty list as the first entry; - if (LocListWritersByCU.empty() || - LocListWritersByCU.begin()->second.get()->getDwarfVersion() < 5) { - // Should be fine for both DWARF4 and DWARF5? - const char Zeroes[16] = {0}; - *LocStream << StringRef(Zeroes, 16); - SectionOffset += 2 * 8; - } - for (std::pair> &Loc : LocListWritersByCU) { DebugLocWriter *LocWriter = Loc.second.get(); auto *LocListWriter = llvm::dyn_cast(LocWriter); + // Filter out DWARF4, writing out DWARF5 if (Version == DWARFVersion::DWARF5 && (!LocListWriter || LocListWriter->getDwarfVersion() <= 4)) continue; + // Filter out DWARF5, writing out DWARF4 if (Version == DWARFVersion::DWARFLegacy && (LocListWriter && LocListWriter->getDwarfVersion() >= 5)) continue; + + // Skipping DWARF4/5 split dwarf. if (LocListWriter && (LocListWriter->getDwarfVersion() <= 4 || (LocListWriter->getDwarfVersion() >= 5 && LocListWriter->isSplitDwarf()))) { - SimpleBinaryPatcher *Patcher = - getBinaryDWODebugInfoPatcher(LocListWriter->getCUID()); - LocListWriter->finalize(0, *Patcher); continue; } - LocWriter->finalize(SectionOffset, DebugInfoPatcher); std::unique_ptr CurrCULocationLists = LocWriter->getBuffer(); *LocStream << *CurrCULocationLists; - SectionOffset += CurrCULocationLists->size(); } return LocBuffer; diff --git a/bolt/lib/Rewrite/MachORewriteInstance.cpp b/bolt/lib/Rewrite/MachORewriteInstance.cpp index 0f85eb1a8a3b8..0958e6eb73142 100644 --- a/bolt/lib/Rewrite/MachORewriteInstance.cpp +++ b/bolt/lib/Rewrite/MachORewriteInstance.cpp @@ -494,7 +494,7 @@ void MachORewriteInstance::emitAndLink() { auto Streamer = BC->createStreamer(*OS); emitBinaryContext(*Streamer, *BC, getOrgSecPrefix()); - Streamer->Finish(); + Streamer->finish(); std::unique_ptr ObjectMemBuffer = MemoryBuffer::getMemBuffer(BOS->str(), "in-memory object file", false); diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 2d3f987af9597..684b098da031b 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -80,20 +80,17 @@ extern cl::list ReorderData; extern cl::opt ReorderFunctions; extern cl::opt TimeBuild; -static cl::opt -ForceToDataRelocations("force-data-relocations", - cl::desc("force relocations to data sections to always be processed"), - cl::init(false), - cl::Hidden, - cl::ZeroOrMore, - cl::cat(BoltCategory)); +static cl::opt ForceToDataRelocations( + "force-data-relocations", + cl::desc("force relocations to data sections to always be processed"), + + cl::Hidden, cl::cat(BoltCategory)); cl::opt -BoltID("bolt-id", - cl::desc("add any string to tag this execution in the " - "output binary via bolt info section"), - cl::ZeroOrMore, - cl::cat(BoltCategory)); + BoltID("bolt-id", + cl::desc("add any string to tag this execution in the " + "output binary via bolt info section"), + cl::cat(BoltCategory)); cl::opt AllowStripped("allow-stripped", @@ -101,12 +98,11 @@ AllowStripped("allow-stripped", cl::Hidden, cl::cat(BoltCategory)); -cl::opt -DumpDotAll("dump-dot-all", - cl::desc("dump function CFGs to graphviz format after each stage"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); +cl::opt DumpDotAll( + "dump-dot-all", + cl::desc("dump function CFGs to graphviz format after each stage;" + "enable '-print-loops' for color-coded blocks"), + cl::Hidden, cl::cat(BoltCategory)); static cl::list ForceFunctionNames("funcs", @@ -138,12 +134,8 @@ KeepTmp("keep-tmp", cl::Hidden, cl::cat(BoltCategory)); -cl::opt -Lite("lite", - cl::desc("skip processing of cold functions"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltCategory)); +cl::opt Lite("lite", cl::desc("skip processing of cold functions"), + cl::cat(BoltCategory)); static cl::opt LiteThresholdPct("lite-threshold-pct", @@ -156,72 +148,49 @@ LiteThresholdPct("lite-threshold-pct", cl::Hidden, cl::cat(BoltOptCategory)); -static cl::opt -LiteThresholdCount("lite-threshold-count", - cl::desc("similar to '-lite-threshold-pct' but specify threshold using " - "absolute function call count. I.e. limit processing to functions " - "executed at least the specified number of times."), - cl::init(0), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); +static cl::opt LiteThresholdCount( + "lite-threshold-count", + cl::desc("similar to '-lite-threshold-pct' but specify threshold using " + "absolute function call count. I.e. limit processing to functions " + "executed at least the specified number of times."), + cl::init(0), cl::Hidden, cl::cat(BoltOptCategory)); static cl::opt -MaxFunctions("max-funcs", - cl::desc("maximum number of functions to process"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); + MaxFunctions("max-funcs", + cl::desc("maximum number of functions to process"), cl::Hidden, + cl::cat(BoltCategory)); -static cl::opt -MaxDataRelocations("max-data-relocations", - cl::desc("maximum number of data relocations to process"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); +static cl::opt MaxDataRelocations( + "max-data-relocations", + cl::desc("maximum number of data relocations to process"), cl::Hidden, + cl::cat(BoltCategory)); -cl::opt -PrintAll("print-all", - cl::desc("print functions after each stage"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); +cl::opt PrintAll("print-all", + cl::desc("print functions after each stage"), cl::Hidden, + cl::cat(BoltCategory)); -cl::opt -PrintCFG("print-cfg", - cl::desc("print functions after CFG construction"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); +cl::opt PrintCFG("print-cfg", + cl::desc("print functions after CFG construction"), + cl::Hidden, cl::cat(BoltCategory)); cl::opt PrintDisasm("print-disasm", - cl::desc("print function after disassembly"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); + cl::desc("print function after disassembly"), + cl::Hidden, cl::cat(BoltCategory)); static cl::opt -PrintGlobals("print-globals", - cl::desc("print global symbols after disassembly"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); + PrintGlobals("print-globals", + cl::desc("print global symbols after disassembly"), cl::Hidden, + cl::cat(BoltCategory)); extern cl::opt PrintSections; -static cl::opt -PrintLoopInfo("print-loops", - cl::desc("print loop related information"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); +static cl::opt PrintLoopInfo("print-loops", + cl::desc("print loop related information"), + cl::Hidden, cl::cat(BoltCategory)); -static cl::opt -PrintSDTMarkers("print-sdt", - cl::desc("print all SDT markers"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); +static cl::opt PrintSDTMarkers("print-sdt", + cl::desc("print all SDT markers"), + cl::Hidden, cl::cat(BoltCategory)); enum PrintPseudoProbesOptions { PPP_None = 0, @@ -243,11 +212,9 @@ cl::opt PrintPseudoProbes( clEnumValN(PPP_All, "all", "enable all debugging printout")), cl::ZeroOrMore, cl::Hidden, cl::cat(BoltCategory)); -static cl::opt -RelocationMode("relocs", - cl::desc("use relocations in the binary (default=autodetect)"), - cl::ZeroOrMore, - cl::cat(BoltCategory)); +static cl::opt RelocationMode( + "relocs", cl::desc("use relocations in the binary (default=autodetect)"), + cl::cat(BoltCategory)); static cl::opt SaveProfile("w", @@ -276,8 +243,8 @@ TrapOldCode("trap-old-code", static cl::opt DWPPathName("dwp", cl::desc("Path and name to DWP file."), - cl::Hidden, cl::ZeroOrMore, - cl::init(""), cl::cat(BoltCategory)); + cl::Hidden, cl::init(""), + cl::cat(BoltCategory)); static cl::opt UseGnuStack("use-gnu-stack", @@ -287,11 +254,9 @@ UseGnuStack("use-gnu-stack", cl::cat(BoltCategory)); static cl::opt -TimeRewrite("time-rewrite", - cl::desc("print time spent in rewriting passes"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); + TimeRewrite("time-rewrite", + cl::desc("print time spent in rewriting passes"), cl::Hidden, + cl::cat(BoltCategory)); static cl::opt SequentialDisassembly("sequential-disassembly", @@ -299,13 +264,9 @@ SequentialDisassembly("sequential-disassembly", cl::init(false), cl::cat(BoltOptCategory)); -static cl::opt -WriteBoltInfoSection("bolt-info", - cl::desc("write bolt info section in the output binary"), - cl::init(true), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOutputCategory)); +static cl::opt WriteBoltInfoSection( + "bolt-info", cl::desc("write bolt info section in the output binary"), + cl::init(true), cl::Hidden, cl::cat(BoltOutputCategory)); } // namespace opts @@ -880,47 +841,88 @@ void RewriteInstance::discoverFileObjects() { std::vector SortedFileSymbols; std::copy_if(InputFile->symbol_begin(), InputFile->symbol_end(), std::back_inserter(SortedFileSymbols), isSymbolInMemory); + auto CompareSymbols = [this](const SymbolRef &A, const SymbolRef &B) { + // Marker symbols have the highest precedence, while + // SECTIONs have the lowest. + auto AddressA = cantFail(A.getAddress()); + auto AddressB = cantFail(B.getAddress()); + if (AddressA != AddressB) + return AddressA < AddressB; + + bool AMarker = BC->isMarker(A); + bool BMarker = BC->isMarker(B); + if (AMarker || BMarker) { + return AMarker && !BMarker; + } - std::stable_sort( - SortedFileSymbols.begin(), SortedFileSymbols.end(), - [](const SymbolRef &A, const SymbolRef &B) { - // FUNC symbols have the highest precedence, while SECTIONs - // have the lowest. - uint64_t AddressA = cantFail(A.getAddress()); - uint64_t AddressB = cantFail(B.getAddress()); - if (AddressA != AddressB) - return AddressA < AddressB; - - SymbolRef::Type AType = cantFail(A.getType()); - SymbolRef::Type BType = cantFail(B.getType()); - if (AType == SymbolRef::ST_Function && BType != SymbolRef::ST_Function) - return true; - if (BType == SymbolRef::ST_Debug && AType != SymbolRef::ST_Debug) - return true; + auto AType = cantFail(A.getType()); + auto BType = cantFail(B.getType()); + if (AType == SymbolRef::ST_Function && BType != SymbolRef::ST_Function) + return true; + if (BType == SymbolRef::ST_Debug && AType != SymbolRef::ST_Debug) + return true; - return false; - }); + return false; + }; + + std::stable_sort(SortedFileSymbols.begin(), SortedFileSymbols.end(), + CompareSymbols); + + auto LastSymbol = SortedFileSymbols.end() - 1; // For aarch64, the ABI defines mapping symbols so we identify data in the // code section (see IHI0056B). $d identifies data contents. - auto LastSymbol = SortedFileSymbols.end() - 1; + // Compilers usually merge multiple data objects in a single $d-$x interval, + // but we need every data object to be marked with $d. Because of that we + // create a vector of MarkerSyms with all locations of data objects. + + struct MarkerSym { + uint64_t Address; + MarkerSymType Type; + }; + + std::vector SortedMarkerSymbols; + auto addExtraDataMarkerPerSymbol = + [this](const std::vector &SortedFileSymbols, + std::vector &SortedMarkerSymbols) { + bool IsData = false; + uint64_t LastAddr = 0; + for (auto Sym = SortedFileSymbols.begin(); + Sym < SortedFileSymbols.end(); ++Sym) { + uint64_t Address = cantFail(Sym->getAddress()); + if (LastAddr == Address) // don't repeat markers + continue; + + MarkerSymType MarkerType = BC->getMarkerType(*Sym); + if (MarkerType != MarkerSymType::NONE) { + SortedMarkerSymbols.push_back(MarkerSym{Address, MarkerType}); + LastAddr = Address; + IsData = MarkerType == MarkerSymType::DATA; + continue; + } + + if (IsData) { + SortedMarkerSymbols.push_back( + MarkerSym{cantFail(Sym->getAddress()), MarkerSymType::DATA}); + LastAddr = Address; + } + } + }; + if (BC->isAArch64()) { + addExtraDataMarkerPerSymbol(SortedFileSymbols, SortedMarkerSymbols); LastSymbol = std::stable_partition( SortedFileSymbols.begin(), SortedFileSymbols.end(), - [](const SymbolRef &Symbol) { - StringRef Name = cantFail(Symbol.getName()); - return !(cantFail(Symbol.getType()) == SymbolRef::ST_Unknown && - (Name == "$d" || Name.startswith("$d.") || Name == "$x" || - Name.startswith("$x."))); - }); + [this](const SymbolRef &Symbol) { return !BC->isMarker(Symbol); }); --LastSymbol; } BinaryFunction *PreviousFunction = nullptr; unsigned AnonymousId = 0; - const auto MarkersBegin = std::next(LastSymbol); - for (auto ISym = SortedFileSymbols.begin(); ISym != MarkersBegin; ++ISym) { + const auto SortedSymbolsEnd = std::next(LastSymbol); + for (auto ISym = SortedFileSymbols.begin(); ISym != SortedSymbolsEnd; + ++ISym) { const SymbolRef &Symbol = *ISym; // Keep undefined symbols for pretty printing? if (cantFail(Symbol.getFlags()) & SymbolRef::SF_Undefined) @@ -1213,25 +1215,24 @@ void RewriteInstance::discoverFileObjects() { adjustFunctionBoundaries(); // Annotate functions with code/data markers in AArch64 - for (auto ISym = MarkersBegin; ISym != SortedFileSymbols.end(); ++ISym) { - const SymbolRef &Symbol = *ISym; - uint64_t Address = - cantFail(Symbol.getAddress(), "cannot get symbol address"); - uint64_t SymbolSize = ELFSymbolRef(Symbol).getSize(); - BinaryFunction *BF = - BC->getBinaryFunctionContainingAddress(Address, true, true); + for (auto ISym = SortedMarkerSymbols.begin(); + ISym != SortedMarkerSymbols.end(); ++ISym) { + + auto *BF = + BC->getBinaryFunctionContainingAddress(ISym->Address, true, true); + if (!BF) { // Stray marker continue; } - const uint64_t EntryOffset = Address - BF->getAddress(); - if (BF->isCodeMarker(Symbol, SymbolSize)) { + const auto EntryOffset = ISym->Address - BF->getAddress(); + if (ISym->Type == MarkerSymType::CODE) { BF->markCodeAtOffset(EntryOffset); continue; } - if (BF->isDataMarker(Symbol, SymbolSize)) { + if (ISym->Type == MarkerSymType::DATA) { BF->markDataAtOffset(EntryOffset); - BC->AddressToConstantIslandMap[Address] = BF; + BC->AddressToConstantIslandMap[ISym->Address] = BF; continue; } llvm_unreachable("Unknown marker"); @@ -2331,7 +2332,7 @@ void RewriteInstance::readRelocations(const SectionRef &Section) { SmallString<16> TypeName; Rel.getTypeName(TypeName); uint64_t RType = Rel.getType(); - if (Relocation::isNone(RType)) + if (Relocation::skipRelocationType(RType)) continue; // Adjust the relocation type as the linker might have skewed it. @@ -2924,7 +2925,8 @@ void RewriteInstance::disassembleFunctions() { continue; if (!Function.isSimple()) { - assert((!BC->HasRelocations || Function.getSize() == 0) && + assert((!BC->HasRelocations || Function.getSize() == 0 || + Function.hasSplitJumpTable()) && "unexpected non-simple function in relocation mode"); continue; } @@ -3115,7 +3117,7 @@ void RewriteInstance::emitAndLink() { emitBinaryContext(*Streamer, *BC, getOrgSecPrefix()); - Streamer->Finish(); + Streamer->finish(); if (Streamer->getContext().hadError()) { errs() << "BOLT-ERROR: Emission failed.\n"; exit(1); diff --git a/bolt/lib/RuntimeLibs/HugifyRuntimeLibrary.cpp b/bolt/lib/RuntimeLibs/HugifyRuntimeLibrary.cpp index d5a50239b1a8d..9572c964ff7e9 100644 --- a/bolt/lib/RuntimeLibs/HugifyRuntimeLibrary.cpp +++ b/bolt/lib/RuntimeLibs/HugifyRuntimeLibrary.cpp @@ -31,11 +31,11 @@ cl::opt cl::desc("Automatically put hot code on 2MB page(s) (hugify) at " "runtime. No manual call to hugify is needed in the binary " "(which is what --hot-text relies on)."), - cl::ZeroOrMore, cl::cat(BoltOptCategory)); + cl::cat(BoltOptCategory)); static cl::opt RuntimeHugifyLib( "runtime-hugify-lib", - cl::desc("specify file name of the runtime hugify library"), cl::ZeroOrMore, + cl::desc("specify file name of the runtime hugify library"), cl::init("libbolt_rt_hugify.a"), cl::cat(BoltOptCategory)); } // namespace opts @@ -80,7 +80,7 @@ void HugifyRuntimeLibrary::emitBinary(BinaryContext &BC, MCStreamer &Streamer) { MCSymbol *InitPtr = BC.Ctx->getOrCreateSymbol("__bolt_hugify_init_ptr"); Section->setAlignment(llvm::Align(BC.RegularPageSize)); - Streamer.SwitchSection(Section); + Streamer.switchSection(Section); Streamer.emitLabel(InitPtr); Streamer.emitSymbolAttribute(InitPtr, MCSymbolAttr::MCSA_Global); diff --git a/bolt/lib/RuntimeLibs/InstrumentationRuntimeLibrary.cpp b/bolt/lib/RuntimeLibs/InstrumentationRuntimeLibrary.cpp index db3195bcd1225..091211662a039 100644 --- a/bolt/lib/RuntimeLibs/InstrumentationRuntimeLibrary.cpp +++ b/bolt/lib/RuntimeLibs/InstrumentationRuntimeLibrary.cpp @@ -27,7 +27,7 @@ namespace opts { cl::opt RuntimeInstrumentationLib( "runtime-instrumentation-lib", cl::desc("specify file name of the runtime instrumentation library"), - cl::ZeroOrMore, cl::init("libbolt_rt_instr.a"), cl::cat(BoltOptCategory)); + cl::init("libbolt_rt_instr.a"), cl::cat(BoltOptCategory)); extern cl::opt InstrumentationFileAppendPID; extern cl::opt ConservativeInstrumentation; @@ -87,7 +87,7 @@ void InstrumentationRuntimeLibrary::emitBinary(BinaryContext &BC, } Section->setAlignment(llvm::Align(BC.RegularPageSize)); - Streamer.SwitchSection(Section); + Streamer.switchSection(Section); // EmitOffset is used to determine padding size for data alignment uint64_t EmitOffset = 0; @@ -185,7 +185,7 @@ void InstrumentationRuntimeLibrary::emitBinary(BinaryContext &BC, MCSection *TablesSection = BC.Ctx->getMachOSection( "__BOLT", "__tables", MachO::S_REGULAR, SectionKind::getData()); TablesSection->setAlignment(llvm::Align(BC.RegularPageSize)); - Streamer.SwitchSection(TablesSection); + Streamer.switchSection(TablesSection); emitString("__bolt_instr_tables", buildTables(BC)); } } diff --git a/bolt/lib/Target/X86/CMakeLists.txt b/bolt/lib/Target/X86/CMakeLists.txt index 8d4ec2d09e07d..47344fe331115 100644 --- a/bolt/lib/Target/X86/CMakeLists.txt +++ b/bolt/lib/Target/X86/CMakeLists.txt @@ -2,12 +2,14 @@ set(LLVM_LINK_COMPONENTS BOLTCore BOLTUtils MC + MCDisassembler Support X86Desc ) add_llvm_library(LLVMBOLTTargetX86 X86MCPlusBuilder.cpp + X86MCSymbolizer.cpp DEPENDS X86CommonTableGen diff --git a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp index d6debda767071..9c45314123319 100644 --- a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp +++ b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp @@ -13,6 +13,7 @@ #include "MCTargetDesc/X86BaseInfo.h" #include "MCTargetDesc/X86InstrRelaxTables.h" #include "MCTargetDesc/X86MCTargetDesc.h" +#include "X86MCSymbolizer.h" #include "bolt/Core/MCPlus.h" #include "bolt/Core/MCPlusBuilder.h" #include "llvm/BinaryFormat/ELF.h" @@ -43,7 +44,7 @@ extern cl::OptionCategory BoltOptCategory; static cl::opt X86StripRedundantAddressSize( "x86-strip-redundant-address-size", cl::desc("Remove redundant Address-Size override prefix"), cl::init(true), - cl::ZeroOrMore, cl::cat(BoltOptCategory)); + cl::cat(BoltOptCategory)); } // namespace opts @@ -81,6 +82,11 @@ class X86MCPlusBuilder : public MCPlusBuilder { const MCRegisterInfo *RegInfo) : MCPlusBuilder(Analysis, Info, RegInfo) {} + std::unique_ptr + createTargetSymbolizer(BinaryFunction &Function) const override { + return std::make_unique(Function); + } + bool isBranch(const MCInst &Inst) const override { return Analysis->isBranch(Inst) && !isTailCall(Inst); } diff --git a/bolt/lib/Target/X86/X86MCSymbolizer.cpp b/bolt/lib/Target/X86/X86MCSymbolizer.cpp new file mode 100644 index 0000000000000..852ce95798f3c --- /dev/null +++ b/bolt/lib/Target/X86/X86MCSymbolizer.cpp @@ -0,0 +1,141 @@ +//===- bolt/Target/X86/X86MCSymbolizer.cpp --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "X86MCSymbolizer.h" +#include "MCTargetDesc/X86BaseInfo.h" +#include "bolt/Core/BinaryContext.h" +#include "bolt/Core/BinaryFunction.h" +#include "bolt/Core/MCPlusBuilder.h" +#include "bolt/Core/Relocation.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCRegisterInfo.h" + +#define DEBUG_TYPE "bolt-symbolizer" + +namespace llvm { +namespace bolt { + +X86MCSymbolizer::~X86MCSymbolizer() {} + +bool X86MCSymbolizer::tryAddingSymbolicOperand( + MCInst &Inst, raw_ostream &CStream, int64_t Value, uint64_t InstAddress, + bool IsBranch, uint64_t ImmOffset, uint64_t ImmSize, uint64_t InstSize) { + if (IsBranch) + return false; + + // Ignore implicit operands. + if (ImmSize == 0) + return false; + + BinaryContext &BC = Function.getBinaryContext(); + MCContext *Ctx = BC.Ctx.get(); + + if (BC.MIB->isBranch(Inst) || BC.MIB->isCall(Inst)) + return false; + + /// Add symbolic operand to the instruction with an optional addend. + auto addOperand = [&](const MCSymbol *Symbol, uint64_t Addend) { + const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, *Ctx); + if (Addend) + Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Addend, *Ctx), + *Ctx); + Inst.addOperand(MCOperand::createExpr(Expr)); + }; + + // Check if the operand being added is a displacement part of a compound + // memory operand that uses PC-relative addressing. If it is, try to symbolize + // it without relocations. Return true on success, false otherwise. + auto processPCRelOperandNoRel = [&]() { + const int MemOp = BC.MIB->getMemoryOperandNo(Inst); + if (MemOp == -1) + return false; + + const unsigned DispOp = MemOp + X86::AddrDisp; + if (Inst.getNumOperands() != DispOp) + return false; + + const MCOperand &Base = Inst.getOperand(MemOp + X86::AddrBaseReg); + if (Base.getReg() != BC.MRI->getProgramCounter()) + return false; + + const MCOperand &Scale = Inst.getOperand(MemOp + X86::AddrScaleAmt); + const MCOperand &Index = Inst.getOperand(MemOp + X86::AddrIndexReg); + if (Scale.getImm() != 0 && Index.getReg() != MCRegister::NoRegister) + return false; + + const MCSymbol *TargetSymbol; + uint64_t TargetOffset; + std::tie(TargetSymbol, TargetOffset) = + BC.handleAddressRef(Value, Function, /*IsPCRel=*/true); + + addOperand(TargetSymbol, TargetOffset); + + return true; + }; + + // Check for GOTPCRELX relocations first. Because these relocations allow the + // linker to modify the instruction, we have to check the offset range + // corresponding to the instruction, not the offset of the operand. + // Note that if there is GOTPCRELX relocation against the instruction, there + // will be no other relocation in this range, since GOTPCRELX applies only to + // certain instruction types. + const uint64_t InstOffset = InstAddress - Function.getAddress(); + const Relocation *Relocation = + Function.getRelocationInRange(InstOffset, InstOffset + InstSize); + if (Relocation && Relocation::isX86GOTPCRELX(Relocation->Type)) { + // If the operand is PC-relative, convert it without using the relocation + // information. For GOTPCRELX, it is safe to use the absolute address + // instead of extracting the addend from the relocation, as non-standard + // forms will be rejected by linker conversion process and the operand + // will always reference GOT which we don't rewrite. + if (processPCRelOperandNoRel()) + return true; + + // The linker converted the PC-relative address to an absolute one. + // Symbolize this address. + BC.handleAddressRef(Value, Function, /*IsPCRel=*/false); + const BinaryData *Target = BC.getBinaryDataAtAddress(Value); + assert(Target && + "BinaryData should exist at converted GOTPCRELX destination"); + + addOperand(Target->getSymbol(), /*Addend=*/0); + + return true; + } + + // Check for relocations against the operand. + if (!Relocation || Relocation->Offset != InstOffset + ImmOffset) + Relocation = Function.getRelocationAt(InstOffset + ImmOffset); + + if (!Relocation) + return processPCRelOperandNoRel(); + + uint64_t SymbolValue = Relocation->Value - Relocation->Addend; + if (Relocation->isPCRelative()) + SymbolValue += InstAddress + ImmOffset; + + // Process reference to the symbol. + BC.handleAddressRef(SymbolValue, Function, Relocation->isPCRelative()); + + uint64_t Addend = Relocation->Addend; + // Real addend for pc-relative targets is adjusted with a delta from + // the relocation placement to the next instruction. + if (Relocation->isPCRelative()) + Addend += InstOffset + InstSize - Relocation->Offset; + + addOperand(Relocation->Symbol, Addend); + + return true; +} + +void X86MCSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &CStream, + int64_t Value, + uint64_t Address) {} + +} // namespace bolt +} // namespace llvm diff --git a/bolt/lib/Target/X86/X86MCSymbolizer.h b/bolt/lib/Target/X86/X86MCSymbolizer.h new file mode 100644 index 0000000000000..a0ddaa3b837a8 --- /dev/null +++ b/bolt/lib/Target/X86/X86MCSymbolizer.h @@ -0,0 +1,43 @@ +//===- bolt/Target/X86/X86MCSymbolizer.h ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef BOLT_CORE_X86MCSYMBOLIZER_H +#define BOLT_CORE_X86MCSYMBOLIZER_H + +#include "bolt/Core/BinaryFunction.h" +#include "llvm/MC/MCDisassembler/MCSymbolizer.h" + +namespace llvm { +namespace bolt { + +class X86MCSymbolizer : public MCSymbolizer { +protected: + BinaryFunction &Function; + +public: + X86MCSymbolizer(BinaryFunction &Function) + : MCSymbolizer(*Function.getBinaryContext().Ctx.get(), nullptr), + Function(Function) {} + + X86MCSymbolizer(const X86MCSymbolizer &) = delete; + X86MCSymbolizer &operator=(const X86MCSymbolizer &) = delete; + virtual ~X86MCSymbolizer(); + + bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &CStream, + int64_t Value, uint64_t Address, bool IsBranch, + uint64_t Offset, uint64_t OpSize, + uint64_t InstSize) override; + + void tryAddingPcLoadReferenceComment(raw_ostream &CStream, int64_t Value, + uint64_t Address) override; +}; + +} // namespace bolt +} // namespace llvm + +#endif diff --git a/bolt/lib/Utils/CommandLineOpts.cpp b/bolt/lib/Utils/CommandLineOpts.cpp index cdf75ac686a4c..dde84e4f000bc 100644 --- a/bolt/lib/Utils/CommandLineOpts.cpp +++ b/bolt/lib/Utils/CommandLineOpts.cpp @@ -40,17 +40,14 @@ cl::OptionCategory AggregatorCategory("Data aggregation options"); cl::OptionCategory BoltInstrCategory("BOLT instrumentation options"); cl::OptionCategory HeatmapCategory("Heatmap options"); -cl::opt -AlignText("align-text", - cl::desc("alignment of .text section"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); +cl::opt AlignText("align-text", + cl::desc("alignment of .text section"), cl::Hidden, + cl::cat(BoltCategory)); cl::opt AlignFunctions( "align-functions", cl::desc("align functions at a given value (relocation mode)"), - cl::init(64), cl::ZeroOrMore, cl::cat(BoltOptCategory)); + cl::init(64), cl::cat(BoltOptCategory)); cl::opt AggregateOnly("aggregate-only", @@ -77,7 +74,6 @@ EnableBAT("enable-bat", cl::cat(BoltCategory)); cl::opt RemoveSymtab("remove-symtab", cl::desc("Remove .symtab section"), - cl::init(false), cl::ZeroOrMore, cl::cat(BoltCategory)); cl::opt @@ -104,19 +100,15 @@ cl::opt HeatmapMinAddress( cl::desc("minimum address considered valid for heatmap (default 0)"), cl::Optional, cl::cat(HeatmapCategory)); -cl::opt -HotData("hot-data", - cl::desc("hot data symbols support (relocation mode)"), - cl::ZeroOrMore, - cl::cat(BoltCategory)); +cl::opt HotData("hot-data", + cl::desc("hot data symbols support (relocation mode)"), + cl::cat(BoltCategory)); -cl::opt -HotFunctionsAtEnd( - "hot-functions-at-end", - cl::desc( - "if reorder-functions is used, order functions putting hottest last"), - cl::ZeroOrMore, - cl::cat(BoltCategory)); +cl::opt HotFunctionsAtEnd( + "hot-functions-at-end", + cl::desc( + "if reorder-functions is used, order functions putting hottest last"), + cl::cat(BoltCategory)); cl::opt HotText( "hot-text", @@ -129,7 +121,7 @@ cl::opt HotText( cl::opt Instrument("instrument", cl::desc("instrument code to generate accurate profile data"), - cl::ZeroOrMore, cl::cat(BoltOptCategory)); + cl::cat(BoltOptCategory)); cl::opt OutputFilename("o", @@ -150,52 +142,37 @@ PerfDataA("p", cl::aliasopt(PerfData), cl::cat(AggregatorCategory)); -cl::opt -PrintCacheMetrics("print-cache-metrics", - cl::desc("calculate and print various metrics for instruction cache"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); +cl::opt PrintCacheMetrics( + "print-cache-metrics", + cl::desc("calculate and print various metrics for instruction cache"), + cl::cat(BoltOptCategory)); -cl::opt - PrintSections("print-sections", - cl::desc("print all registered sections"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltCategory)); +cl::opt PrintSections("print-sections", + cl::desc("print all registered sections"), + cl::Hidden, cl::cat(BoltCategory)); -cl::opt -SplitEH("split-eh", - cl::desc("split C++ exception handling code"), - cl::ZeroOrMore, - cl::Hidden, - cl::cat(BoltOptCategory)); +cl::opt SplitEH("split-eh", cl::desc("split C++ exception handling code"), + cl::Hidden, cl::cat(BoltOptCategory)); cl::opt -StrictMode("strict", - cl::desc("trust the input to be from a well-formed source"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltCategory)); + StrictMode("strict", + cl::desc("trust the input to be from a well-formed source"), -llvm::cl::opt -TimeOpts("time-opts", - cl::desc("print time spent in each optimization"), - cl::init(false), - cl::ZeroOrMore, - cl::cat(BoltOptCategory)); + cl::cat(BoltCategory)); -cl::opt -UseOldText("use-old-text", - cl::desc("re-use space in old .text if possible (relocation mode)"), - cl::ZeroOrMore, - cl::cat(BoltCategory)); +llvm::cl::opt TimeOpts("time-opts", + cl::desc("print time spent in each optimization"), + cl::cat(BoltOptCategory)); -cl::opt -UpdateDebugSections("update-debug-sections", - cl::desc("update DWARF debug sections of the executable"), - cl::ZeroOrMore, - cl::cat(BoltCategory)); +cl::opt UseOldText( + "use-old-text", + cl::desc("re-use space in old .text if possible (relocation mode)"), + cl::cat(BoltCategory)); + +cl::opt UpdateDebugSections( + "update-debug-sections", + cl::desc("update DWARF debug sections of the executable"), + cl::cat(BoltCategory)); cl::opt Verbosity("v", diff --git a/bolt/test/AArch64/Inputs/unmarked-data.yaml b/bolt/test/AArch64/Inputs/unmarked-data.yaml new file mode 100644 index 0000000000000..a91b62e42ab52 --- /dev/null +++ b/bolt/test/AArch64/Inputs/unmarked-data.yaml @@ -0,0 +1,90 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_AARCH64 + Entry: 0x210134 +ProgramHeaders: + - Type: PT_PHDR + Flags: [ PF_R ] + VAddr: 0x200040 + Align: 0x8 + FileSize: 0x0000e0 + MemSize: 0x0000e0 + Offset: 0x000040 + - Type: PT_LOAD + Flags: [ PF_R ] + VAddr: 0x200000 + Align: 0x10000 + FileSize: 0x000120 + MemSize: 0x000120 + Offset: 0x000000 + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + FirstSec: .text + LastSec: .text + VAddr: 0x210120 + Align: 0x10000 + - Type: PT_GNU_STACK + Flags: [ PF_W, PF_R ] + Align: 0x0 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x210120 + AddressAlign: 0x4 + Content: 030F0B0700000000030F0B0700000000C0035FD6FFFFFF97000080D2A80B8052010000D4 + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .text + Relocations: + - Offset: 0x210134 + Symbol: dummy + Type: R_AARCH64_CALL26 + - Name: .comment + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x1 + EntSize: 0x1 + Content: 4C696E6B65723A204C4C442031352E302E3000 +Symbols: + - Name: val + Index: SHN_ABS + Value: 0x70B0F03 + - Name: first + Section: .text + Value: 0x210120 + Size: 0x8 + - Name: '$d.0' + Section: .text + Value: 0x210120 + - Name: second + Section: .text + Value: 0x210128 + Size: 0x8 + - Name: '$x.1' + Section: .text + Value: 0x210130 + - Name: .text + Type: STT_SECTION + Section: .text + Value: 0x210120 + - Name: .comment + Type: STT_SECTION + Section: .comment + - Name: dummy + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x210130 + - Name: _start + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x210134 +... diff --git a/bolt/test/AArch64/asm-func-debug.test b/bolt/test/AArch64/asm-func-debug.test index 7c679ed8ce9ce..37499ecfeecd3 100644 --- a/bolt/test/AArch64/asm-func-debug.test +++ b/bolt/test/AArch64/asm-func-debug.test @@ -4,7 +4,7 @@ # The input test case foo() contains nops that we remove. RUN: %clang %cflags -no-pie -gdwarf-4 %p/../Inputs/asm_foo.s %p/../Inputs/asm_main.c -o %t.exe -RUN: llvm-bolt %t.exe -o %t -update-debug-sections +RUN: llvm-bolt %t.exe -o %t --update-debug-sections RUN: llvm-dwarfdump -all %t | FileCheck %s # Check ranges were created/updated for asm compile unit diff --git a/bolt/test/AArch64/constant-island-alignment.s b/bolt/test/AArch64/constant-island-alignment.s index a71d7ce3eba26..3ce0df9d4f290 100644 --- a/bolt/test/AArch64/constant-island-alignment.s +++ b/bolt/test/AArch64/constant-island-alignment.s @@ -6,7 +6,7 @@ # RUN: %s -o %t.o # RUN: %clang %cflags -fPIC -pie %t.o -o %t.exe -Wl,-q \ # RUN: -nostartfiles -nodefaultlibs -Wl,-z,notext -# RUN: llvm-bolt %t.exe -o %t.bolt -use-old-text=0 -lite=0 -trap-old-code +# RUN: llvm-bolt %t.exe -o %t.bolt --use-old-text=0 --lite=0 --trap-old-code # RUN: llvm-objdump -d --disassemble-symbols='$d' %t.bolt | FileCheck %s .text diff --git a/bolt/test/AArch64/constant_island_pie_update.s b/bolt/test/AArch64/constant_island_pie_update.s index 26e4bd5df69ed..f4989b9c021d5 100644 --- a/bolt/test/AArch64/constant_island_pie_update.s +++ b/bolt/test/AArch64/constant_island_pie_update.s @@ -4,7 +4,7 @@ # RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \ # RUN: %s -o %t.o # RUN: %clang %cflags -fPIC -pie %t.o -o %t.exe -Wl,-q -nostdlib -Wl,-z,notext -# RUN: llvm-bolt %t.exe -o %t.bolt -use-old-text=0 -lite=0 +# RUN: llvm-bolt %t.exe -o %t.bolt --use-old-text=0 --lite=0 # RUN: llvm-objdump -j .text -dR %t.bolt | FileCheck %s # CHECK: R_AARCH64_RELATIVE *ABS*+0x[[#%x,ADDR:]] diff --git a/bolt/test/AArch64/data-at-0-offset.c b/bolt/test/AArch64/data-at-0-offset.c new file mode 100644 index 0000000000000..e0c689a19bedd --- /dev/null +++ b/bolt/test/AArch64/data-at-0-offset.c @@ -0,0 +1,17 @@ +// RUN: %clang %cflags -O2 -fPIE -Wl,-q -pie %s -o %t.exe +// RUN: llvm-bolt %t.exe -o %t.bolt 2>&1 | FileCheck %s +// CHECK-NOT: BOLT-WARNING: unable to disassemble instruction at offset + +void extra_space() { + asm volatile(".rept 256\n" + " .byte 0xff\n" + ".endr\n"); + return; +} + +int main(int argc, char **argv) { + void (*fn)(void); + fn = extra_space + 256; + fn(); + return 0; +} diff --git a/bolt/test/AArch64/double_jump.cpp b/bolt/test/AArch64/double_jump.cpp index 1faae9840e091..d18990114da4a 100644 --- a/bolt/test/AArch64/double_jump.cpp +++ b/bolt/test/AArch64/double_jump.cpp @@ -1,7 +1,7 @@ // A contrived example to test the double jump removal peephole. // RUN: %clang %cflags -O0 %s -o %t.exe -// RUN: llvm-bolt %t.exe -o %t.bolt -peepholes=double-jumps | \ +// RUN: llvm-bolt %t.exe -o %t.bolt --peepholes=double-jumps | \ // RUN: FileCheck %s -check-prefix=CHECKBOLT // RUN: llvm-objdump -d %t.bolt | FileCheck %s diff --git a/bolt/test/AArch64/ext-double-jump.s b/bolt/test/AArch64/ext-double-jump.s index a039cd424c9e0..5cb1701fb11ef 100644 --- a/bolt/test/AArch64/ext-double-jump.s +++ b/bolt/test/AArch64/ext-double-jump.s @@ -3,7 +3,7 @@ # RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o # RUN: %clang %cflags -nostartfiles -nodefaultlibs %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -peepholes=double-jumps +# RUN: llvm-bolt %t.exe -o %t.bolt --peepholes=double-jumps .text .align 4 diff --git a/bolt/test/AArch64/go_dwarf.test b/bolt/test/AArch64/go_dwarf.test index 7cc672bc2e6fc..c901835cf69a8 100644 --- a/bolt/test/AArch64/go_dwarf.test +++ b/bolt/test/AArch64/go_dwarf.test @@ -3,7 +3,7 @@ # - DW_AT_high_pc is in the form of DW_FORM_addr. RUN: yaml2obj %p/Inputs/go_dwarf.yaml &> %t.exe -RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections +RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections # Check the original binary values. RUN: llvm-dwarfdump -debug-info %t.exe 2>&1 | \ diff --git a/bolt/test/AArch64/plt-gnu-ld.test b/bolt/test/AArch64/plt-gnu-ld.test index 9dc37cd9b8462..f8f300fecaa6a 100644 --- a/bolt/test/AArch64/plt-gnu-ld.test +++ b/bolt/test/AArch64/plt-gnu-ld.test @@ -4,8 +4,8 @@ // to the symbol name e.g. memcpy@@GLIBC_2.17 // RUN: yaml2obj %p/Inputs/plt-gnu-ld.yaml &> %t.exe -// RUN: llvm-bolt %t.exe -o %t.bolt.exe -use-old-text=0 -lite=0 \ -// RUN: -print-cfg -print-only=main | FileCheck %s +// RUN: llvm-bolt %t.exe -o %t.bolt.exe --use-old-text=0 --lite=0 \ +// RUN: --print-cfg --print-only=main | FileCheck %s // CHECK: memcpy@PLT // CHECK: memset@PLT diff --git a/bolt/test/AArch64/runtime-relocs.test b/bolt/test/AArch64/runtime-relocs.test index 8f73e671cb2df..a8347b531c144 100644 --- a/bolt/test/AArch64/runtime-relocs.test +++ b/bolt/test/AArch64/runtime-relocs.test @@ -2,8 +2,8 @@ RUN: yaml2obj %p/Inputs/rels-so.yaml &> %t.so RUN: yaml2obj %p/Inputs/rels-exe.yaml &> %t.exe -RUN: llvm-bolt %t.so -o %t.bolt.so -use-old-text=0 -lite=0 -RUN: llvm-bolt %t.exe -o %t.bolt.exe -use-old-text=0 -lite=0 +RUN: llvm-bolt %t.so -o %t.bolt.so --use-old-text=0 --lite=0 +RUN: llvm-bolt %t.exe -o %t.bolt.exe --use-old-text=0 --lite=0 // Check relocations in library: @@ -27,7 +27,7 @@ CHECKEXE: {{.*}} R_AARCH64_JUMP_SLOT {{.*}} inc + 0 // the initial binary was built with gcc and ld with -mtls-dialect=trad flag. RUN: yaml2obj %p/Inputs/tls-trad.yaml &> %t.trad.so -RUN: llvm-bolt %t.trad.so -o %t.trad.bolt.so -use-old-text=0 -lite=0 +RUN: llvm-bolt %t.trad.so -o %t.trad.bolt.so --use-old-text=0 --lite=0 RUN: llvm-readelf -rW %t.trad.so | FileCheck %s -check-prefix=CHECKTRAD CHECKTRAD: {{.*}} R_AARCH64_TLS_DTPMOD64 {{.*}} t1 + 0 @@ -37,7 +37,7 @@ CHECKTRAD: {{.*}} R_AARCH64_TLS_DTPREL64 {{.*}} t1 + 0 // it is emitted correctly. RUN: yaml2obj %p/Inputs/tls-ld.yaml &> %t.ld.so -RUN: llvm-bolt %t.ld.so -o %t.ld.bolt.so -use-old-text=0 -lite=0 +RUN: llvm-bolt %t.ld.so -o %t.ld.bolt.so --use-old-text=0 --lite=0 RUN: llvm-readelf -rW %t.ld.bolt.so | FileCheck %s -check-prefix=CHECKLD CHECKLD: {{.*}} R_AARCH64_TLSDESC {{.*}} t1 + 0 diff --git a/bolt/test/AArch64/skip-got-rel.test b/bolt/test/AArch64/skip-got-rel.test index 4acf397d7bf43..3c36df00b1c82 100644 --- a/bolt/test/AArch64/skip-got-rel.test +++ b/bolt/test/AArch64/skip-got-rel.test @@ -3,6 +3,6 @@ // normally. RUN: yaml2obj %p/Inputs/skip-got-rel.yaml &> %t.exe -RUN: llvm-bolt %t.exe -o /dev/null -print-cfg -print-only=_start | FileCheck %s +RUN: llvm-bolt %t.exe -o /dev/null --print-cfg --print-only=_start | FileCheck %s CHECK: adr x0, foo2 diff --git a/bolt/test/AArch64/tailcall_traps.s b/bolt/test/AArch64/tailcall_traps.s index 26f0a39169490..95009cd784f70 100644 --- a/bolt/test/AArch64/tailcall_traps.s +++ b/bolt/test/AArch64/tailcall_traps.s @@ -3,8 +3,8 @@ # RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \ # RUN: %s -o %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -peepholes=tailcall-traps \ -# RUN: -print-peepholes -funcs=foo,bar 2>&1 | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t.bolt --peepholes=tailcall-traps \ +# RUN: --print-peepholes --funcs=foo,bar 2>&1 | FileCheck %s # CHECK: Binary Function "foo" # CHECK: br x0 # TAILCALL diff --git a/bolt/test/AArch64/text-data.c b/bolt/test/AArch64/text-data.c index ccba6e752c233..2986fe7840078 100644 --- a/bolt/test/AArch64/text-data.c +++ b/bolt/test/AArch64/text-data.c @@ -2,7 +2,7 @@ // is properly emitted in the new section. // RUN: %clang %cflags %s -o %t.exe -Wl,-q -// RUN: llvm-bolt %t.exe -o %t.bolt -lite=0 -use-old-text=0 +// RUN: llvm-bolt %t.exe -o %t.bolt --lite=0 --use-old-text=0 // RUN: llvm-objdump -j .text -d --disassemble-symbols=arr %t.bolt | \ // RUN: FileCheck %s diff --git a/bolt/test/AArch64/unmarked-data.test b/bolt/test/AArch64/unmarked-data.test new file mode 100644 index 0000000000000..4045e711bb00d --- /dev/null +++ b/bolt/test/AArch64/unmarked-data.test @@ -0,0 +1,34 @@ +// This test checks that multiple data objects in text of which only first is marked get disassembled properly + +// RUN: yaml2obj %S/Inputs/unmarked-data.yaml -o %t.exe +// RUN: llvm-bolt %t.exe -o %t.bolt --lite=0 --use-old-text=0 2>&1 | FileCheck %s +// CHECK-NOT: BOLT-WARNING +// RUN: llvm-objdump -j .text -d --disassemble-symbols=first,second %t.bolt | FileCheck %s -check-prefix=CHECK-SYMBOL +// CHECK-SYMBOL: : +// CHECK-SYMBOL: : + +// YAML is based in the following assembly: + + .equ val, 0x070b0f03 // we use constant that is not a valid instruction so that it can't be silently dissassembled + .text + +first: + .xword val + .size first, .-first + +second: + .xword val + .size second, .-second + + .globl dummy + .type dummy, %function +dummy: // dummy function to force relocations + ret + + .globl _start + .type _start, %function +_start: + bl dummy + mov x0, #0 + mov w8, #93 + svc #0 diff --git a/bolt/test/AArch64/update-debug-reloc.test b/bolt/test/AArch64/update-debug-reloc.test index 873a886ae1ee8..d57f42a3852a5 100644 --- a/bolt/test/AArch64/update-debug-reloc.test +++ b/bolt/test/AArch64/update-debug-reloc.test @@ -2,7 +2,7 @@ # update-debug-sections option. RUN: %clang %cflags -g %p/../Inputs/asm_foo.s %p/../Inputs/asm_main.c -o %t.exe -RUN: llvm-bolt %t.exe -o %t -update-debug-sections +RUN: llvm-bolt %t.exe -o %t --update-debug-sections CHECK: BOLT-INFO: Target architecture: aarch64 CHECK-NOT: Reloc num: 10 diff --git a/bolt/test/CMakeLists.txt b/bolt/test/CMakeLists.txt index 298303e33ad04..2ac5b470e28be 100644 --- a/bolt/test/CMakeLists.txt +++ b/bolt/test/CMakeLists.txt @@ -40,6 +40,7 @@ list(APPEND BOLT_TEST_DEPS llvm-boltdiff llvm-bolt-heatmap llvm-dwarfdump + llvm-dwp llvm-mc llvm-nm llvm-objdump diff --git a/bolt/test/R_ABS.pic.lld.cpp b/bolt/test/R_ABS.pic.lld.cpp index 606ece60ba8c2..e07c9d1632371 100644 --- a/bolt/test/R_ABS.pic.lld.cpp +++ b/bolt/test/R_ABS.pic.lld.cpp @@ -3,7 +3,7 @@ * against _Z6myfuncv. The same address has a dynamic relocation against it. * * RUN: %clang %cflags -fPIC -shared %s -o %t.so -Wl,-q -fuse-ld=lld - * RUN: llvm-bolt %t.so -o %t.so.bolt -relocs + * RUN: llvm-bolt %t.so -o %t.so.bolt --relocs */ unsigned long long myfunc(); diff --git a/bolt/test/X86/Inputs/dwarf4-ftypes-split-dwarf.s b/bolt/test/X86/Inputs/dwarf4-ftypes-split-dwarf.s new file mode 100644 index 0000000000000..354f6eeb5ded2 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-ftypes-split-dwarf.s @@ -0,0 +1,546 @@ +# clang++ main.cpp -g2 -gsplit-dwarf=split -gdwarf-4 -fdebug-types-section +# struct Foo { +# char *c1; +# char *c2; +# char *c3; +# }; +# +# struct Foo2 { +# char *c1; +# char *c2; +# }; +# +# int main(int argc, char *argv[]) { +# Foo f; +# f.c1 = argv[argc]; +# f.c2 = argv[argc + 1]; +# f.c3 = argv[argc + 2]; +# Foo2 f2; +# f.c1 = argv[argc + 3]; +# f.c2 = argv[argc + 4]; +# return 0; +# } + + .text + .file "main.cpp" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 1 "." "main.cpp" + .loc 1 12 0 # main.cpp:12:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movl $0, -4(%rbp) + movl %edi, -8(%rbp) + movq %rsi, -16(%rbp) +.Ltmp0: + .loc 1 14 10 prologue_end # main.cpp:14:10 + movq -16(%rbp), %rax + movslq -8(%rbp), %rcx + movq (%rax,%rcx,8), %rax + .loc 1 14 8 is_stmt 0 # main.cpp:14:8 + movq %rax, -40(%rbp) + .loc 1 15 10 is_stmt 1 # main.cpp:15:10 + movq -16(%rbp), %rax + .loc 1 15 15 is_stmt 0 # main.cpp:15:15 + movl -8(%rbp), %ecx + .loc 1 15 20 # main.cpp:15:20 + addl $1, %ecx + .loc 1 15 10 # main.cpp:15:10 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 15 8 # main.cpp:15:8 + movq %rax, -32(%rbp) + .loc 1 16 10 is_stmt 1 # main.cpp:16:10 + movq -16(%rbp), %rax + .loc 1 16 15 is_stmt 0 # main.cpp:16:15 + movl -8(%rbp), %ecx + .loc 1 16 20 # main.cpp:16:20 + addl $2, %ecx + .loc 1 16 10 # main.cpp:16:10 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 16 8 # main.cpp:16:8 + movq %rax, -24(%rbp) + .loc 1 18 10 is_stmt 1 # main.cpp:18:10 + movq -16(%rbp), %rax + .loc 1 18 15 is_stmt 0 # main.cpp:18:15 + movl -8(%rbp), %ecx + .loc 1 18 20 # main.cpp:18:20 + addl $3, %ecx + .loc 1 18 10 # main.cpp:18:10 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 18 8 # main.cpp:18:8 + movq %rax, -40(%rbp) + .loc 1 19 10 is_stmt 1 # main.cpp:19:10 + movq -16(%rbp), %rax + .loc 1 19 15 is_stmt 0 # main.cpp:19:15 + movl -8(%rbp), %ecx + .loc 1 19 20 # main.cpp:19:20 + addl $4, %ecx + .loc 1 19 10 # main.cpp:19:10 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 19 8 # main.cpp:19:8 + movq %rax, -32(%rbp) + .loc 1 20 3 is_stmt 1 # main.cpp:20:3 + xorl %eax, %eax + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .section .debug_types.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 7448148824980338162 # Type Signature + .long 30 # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x33 DW_TAG_type_unit + .short 33 # DW_AT_language + .long 0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1e:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 9 # DW_AT_name + .byte 24 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x24:0x9 DW_TAG_member + .byte 6 # DW_AT_name + .long 64 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x2d:0x9 DW_TAG_member + .byte 7 # DW_AT_name + .long 64 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x36:0x9 DW_TAG_member + .byte 8 # DW_AT_name + .long 64 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 16 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x40:0x5 DW_TAG_pointer_type + .long 69 # DW_AT_type + .byte 5 # Abbrev [5] 0x45:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end0: + .long .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit +.Ldebug_info_dwo_start1: + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 5322170643381124694 # Type Signature + .long 30 # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x2a DW_TAG_type_unit + .short 33 # DW_AT_language + .long 0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1e:0x19 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 11 # DW_AT_name + .byte 16 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x24:0x9 DW_TAG_member + .byte 6 # DW_AT_name + .long 55 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x2d:0x9 DW_TAG_member + .byte 7 # DW_AT_name + .long 55 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x37:0x5 DW_TAG_pointer_type + .long 60 # DW_AT_type + .byte 5 # Abbrev [5] 0x3c:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end1: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 0 # DW_CHILDREN_no + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .ascii "\264B" # DW_AT_GNU_pubnames + .byte 25 # DW_FORM_flag_present + .ascii "\260B" # DW_AT_GNU_dwo_name + .byte 14 # DW_FORM_strp + .ascii "\261B" # DW_AT_GNU_dwo_id + .byte 7 # DW_FORM_data8 + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .ascii "\263B" # DW_AT_GNU_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x25 DW_TAG_compile_unit + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lskel_string0 # DW_AT_comp_dir + # DW_AT_GNU_pubnames + .long .Lskel_string1 # DW_AT_GNU_dwo_name + .quad 4780348136649610820 # DW_AT_GNU_dwo_id + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_GNU_addr_base +.Ldebug_info_end0: + .section .debug_str,"MS",@progbits,1 +.Lskel_string0: + .asciz "." # string offset=0 +.Lskel_string1: + .asciz "main.dwo" # string offset=38 + .section .debug_str.dwo,"eMS",@progbits,1 +.Linfo_string0: + .asciz "main" # string offset=0 +.Linfo_string1: + .asciz "int" # string offset=5 +.Linfo_string2: + .asciz "argc" # string offset=9 +.Linfo_string3: + .asciz "argv" # string offset=14 +.Linfo_string4: + .asciz "char" # string offset=19 +.Linfo_string5: + .asciz "f" # string offset=24 +.Linfo_string6: + .asciz "c1" # string offset=26 +.Linfo_string7: + .asciz "c2" # string offset=29 +.Linfo_string8: + .asciz "c3" # string offset=32 +.Linfo_string9: + .asciz "Foo" # string offset=35 +.Linfo_string10: + .asciz "f2" # string offset=39 +.Linfo_string11: + .asciz "Foo2" # string offset=42 +.Linfo_string12: + .asciz "clang version 15.0.0" # string offset=47 +.Linfo_string13: + .asciz "main.cpp" # string offset=68 +.Linfo_string14: + .asciz "main.dwo" # string offset=77 + .section .debug_str_offsets.dwo,"e",@progbits + .long 0 + .long 5 + .long 9 + .long 14 + .long 19 + .long 24 + .long 26 + .long 29 + .long 32 + .long 35 + .long 39 + .long 42 + .long 47 + .long 68 + .long 77 + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end2-.Ldebug_info_dwo_start2 # Length of Unit +.Ldebug_info_dwo_start2: + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 6 # Abbrev [6] 0xb:0x6f DW_TAG_compile_unit + .byte 12 # DW_AT_producer + .short 33 # DW_AT_language + .byte 13 # DW_AT_name + .byte 14 # DW_AT_GNU_dwo_name + .quad 4780348136649610820 # DW_AT_GNU_dwo_id + .byte 7 # Abbrev [7] 0x19:0x3c DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 0 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 12 # DW_AT_decl_line + .long 85 # DW_AT_type + # DW_AT_external + .byte 8 # Abbrev [8] 0x28:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .byte 2 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 12 # DW_AT_decl_line + .long 85 # DW_AT_type + .byte 8 # Abbrev [8] 0x33:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 112 + .byte 3 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 12 # DW_AT_decl_line + .long 89 # DW_AT_type + .byte 9 # Abbrev [9] 0x3e:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 88 + .byte 5 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 13 # DW_AT_decl_line + .long 103 # DW_AT_type + .byte 9 # Abbrev [9] 0x49:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 72 + .byte 10 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 17 # DW_AT_decl_line + .long 112 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x55:0x4 DW_TAG_base_type + .byte 1 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 4 # Abbrev [4] 0x59:0x5 DW_TAG_pointer_type + .long 94 # DW_AT_type + .byte 4 # Abbrev [4] 0x5e:0x5 DW_TAG_pointer_type + .long 99 # DW_AT_type + .byte 5 # Abbrev [5] 0x63:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 10 # Abbrev [10] 0x67:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 7448148824980338162 # DW_AT_signature + .byte 10 # Abbrev [10] 0x70:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 5322170643381124694 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end2: + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .ascii "\260B" # DW_AT_GNU_dwo_name + .ascii "\202>" # DW_FORM_GNU_str_index + .ascii "\261B" # DW_AT_GNU_dwo_id + .byte 7 # DW_FORM_data8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .ascii "\201>" # DW_FORM_GNU_addr_index + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_line.dwo,"e",@progbits +.Ltmp2: + .long .Ldebug_line_end0-.Ldebug_line_start0 # unit length +.Ldebug_line_start0: + .short 4 + .long .Lprologue_end0-.Lprologue_start0 +.Lprologue_start0: + .byte 1 + .byte 1 + .byte 1 + .byte -5 + .byte 14 + .byte 1 + .byte 0 + .ascii "main.cpp" + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 +.Lprologue_end0: +.Ldebug_line_end0: + .section .debug_addr,"",@progbits +.Laddr_table_base0: + .quad .Lfunc_begin0 + .section .debug_gnu_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info +.LpubNames_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 48 # Compilation Unit Length + .long 25 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "main" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_gnu_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info +.LpubTypes_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 48 # Compilation Unit Length + .long 103 # DIE offset + .byte 16 # Attributes: TYPE, EXTERNAL + .asciz "Foo" # External Name + .long 112 # DIE offset + .byte 16 # Attributes: TYPE, EXTERNAL + .asciz "Foo2" # External Name + .long 85 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "int" # External Name + .long 99 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "char" # External Name + .long 0 # End Mark +.LpubTypes_end0: + .ident "clang version 15.0.0" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf5-ftypes-split-dwarf.s b/bolt/test/X86/Inputs/dwarf5-ftypes-split-dwarf.s new file mode 100644 index 0000000000000..08c26ae52e8ec --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-ftypes-split-dwarf.s @@ -0,0 +1,583 @@ +# clang++ main.cpp -g2 -gsplit-dwarf=split -gdwarf-5 -fdebug-types-section -S +# struct Foo { +# char *c1; +# char *c2; +# char *c3; +# }; +# +# struct Foo2 { +# char *c1; +# char *c2; +# }; +# +# int main(int argc, char *argv[]) { +# Foo f; +# f.c1 = argv[argc]; +# f.c2 = argv[argc + 1]; +# f.c3 = argv[argc + 2]; +# Foo2 f2; +# f.c1 = argv[argc + 3]; +# f.c2 = argv[argc + 4]; +# return 0; +# } + + .text + .file "main.cpp" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 0 "." "main.cpp" md5 0xa832f464c853be0f9c52da29cd913807 + .loc 0 12 0 # main.cpp:12:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movl $0, -4(%rbp) + movl %edi, -8(%rbp) + movq %rsi, -16(%rbp) +.Ltmp0: + .loc 0 14 10 prologue_end # main.cpp:14:10 + movq -16(%rbp), %rax + movslq -8(%rbp), %rcx + movq (%rax,%rcx,8), %rax + .loc 0 14 8 is_stmt 0 # main.cpp:14:8 + movq %rax, -40(%rbp) + .loc 0 15 10 is_stmt 1 # main.cpp:15:10 + movq -16(%rbp), %rax + .loc 0 15 15 is_stmt 0 # main.cpp:15:15 + movl -8(%rbp), %ecx + .loc 0 15 20 # main.cpp:15:20 + addl $1, %ecx + .loc 0 15 10 # main.cpp:15:10 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 0 15 8 # main.cpp:15:8 + movq %rax, -32(%rbp) + .loc 0 16 10 is_stmt 1 # main.cpp:16:10 + movq -16(%rbp), %rax + .loc 0 16 15 is_stmt 0 # main.cpp:16:15 + movl -8(%rbp), %ecx + .loc 0 16 20 # main.cpp:16:20 + addl $2, %ecx + .loc 0 16 10 # main.cpp:16:10 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 0 16 8 # main.cpp:16:8 + movq %rax, -24(%rbp) + .loc 0 18 10 is_stmt 1 # main.cpp:18:10 + movq -16(%rbp), %rax + .loc 0 18 15 is_stmt 0 # main.cpp:18:15 + movl -8(%rbp), %ecx + .loc 0 18 20 # main.cpp:18:20 + addl $3, %ecx + .loc 0 18 10 # main.cpp:18:10 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 0 18 8 # main.cpp:18:8 + movq %rax, -40(%rbp) + .loc 0 19 10 is_stmt 1 # main.cpp:19:10 + movq -16(%rbp), %rax + .loc 0 19 15 is_stmt 0 # main.cpp:19:15 + movl -8(%rbp), %ecx + .loc 0 19 20 # main.cpp:19:20 + addl $4, %ecx + .loc 0 19 10 # main.cpp:19:10 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 0 19 8 # main.cpp:19:8 + movq %rax, -32(%rbp) + .loc 0 20 3 is_stmt 1 # main.cpp:20:3 + xorl %eax, %eax + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 5 # DWARF version number + .byte 6 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad 7448148824980338162 # Type Signature + .long 31 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x33 DW_TAG_type_unit + .short 33 # DW_AT_language + .long 0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1f:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 9 # DW_AT_name + .byte 24 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x25:0x9 DW_TAG_member + .byte 6 # DW_AT_name + .long 65 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x2e:0x9 DW_TAG_member + .byte 7 # DW_AT_name + .long 65 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x37:0x9 DW_TAG_member + .byte 8 # DW_AT_name + .long 65 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 16 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x41:0x5 DW_TAG_pointer_type + .long 70 # DW_AT_type + .byte 5 # Abbrev [5] 0x46:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end0: + .long .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit +.Ldebug_info_dwo_start1: + .short 5 # DWARF version number + .byte 6 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad 5322170643381124694 # Type Signature + .long 31 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x2a DW_TAG_type_unit + .short 33 # DW_AT_language + .long 0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1f:0x19 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 11 # DW_AT_name + .byte 16 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x25:0x9 DW_TAG_member + .byte 6 # DW_AT_name + .long 56 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x2e:0x9 DW_TAG_member + .byte 7 # DW_AT_name + .long 56 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x38:0x5 DW_TAG_pointer_type + .long 61 # DW_AT_type + .byte 5 # Abbrev [5] 0x3d:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end1: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 74 # DW_TAG_skeleton_unit + .byte 0 # DW_CHILDREN_no + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .ascii "\264B" # DW_AT_GNU_pubnames + .byte 25 # DW_FORM_flag_present + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 4 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 4780348136649610820 + .byte 1 # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 0 # DW_AT_comp_dir + # DW_AT_GNU_pubnames + .byte 1 # DW_AT_dwo_name + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 12 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Lskel_string0: + .asciz "." # string offset=0 +.Lskel_string1: + .asciz "main.dwo" # string offset=38 + .section .debug_str_offsets,"",@progbits + .long .Lskel_string0 + .long .Lskel_string1 + .section .debug_str_offsets.dwo,"e",@progbits + .long 64 # Length of String Offsets Set + .short 5 + .short 0 + .section .debug_str.dwo,"eMS",@progbits,1 +.Linfo_string0: + .asciz "main" # string offset=0 +.Linfo_string1: + .asciz "int" # string offset=5 +.Linfo_string2: + .asciz "argc" # string offset=9 +.Linfo_string3: + .asciz "argv" # string offset=14 +.Linfo_string4: + .asciz "char" # string offset=19 +.Linfo_string5: + .asciz "f" # string offset=24 +.Linfo_string6: + .asciz "c1" # string offset=26 +.Linfo_string7: + .asciz "c2" # string offset=29 +.Linfo_string8: + .asciz "c3" # string offset=32 +.Linfo_string9: + .asciz "Foo" # string offset=35 +.Linfo_string10: + .asciz "f2" # string offset=39 +.Linfo_string11: + .asciz "Foo2" # string offset=42 +.Linfo_string12: + .asciz "clang version 15.0.0" # string offset=47 +.Linfo_string13: + .asciz "main.cpp" # string offset=68 +.Linfo_string14: + .asciz "main.dwo" # string offset=77 + .section .debug_str_offsets.dwo,"e",@progbits + .long 0 + .long 5 + .long 9 + .long 14 + .long 19 + .long 24 + .long 26 + .long 29 + .long 32 + .long 35 + .long 39 + .long 42 + .long 47 + .long 68 + .long 77 + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end2-.Ldebug_info_dwo_start2 # Length of Unit +.Ldebug_info_dwo_start2: + .short 5 # DWARF version number + .byte 5 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad 4780348136649610820 + .byte 6 # Abbrev [6] 0x14:0x67 DW_TAG_compile_unit + .byte 12 # DW_AT_producer + .short 33 # DW_AT_language + .byte 13 # DW_AT_name + .byte 14 # DW_AT_dwo_name + .byte 7 # Abbrev [7] 0x1a:0x3c DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 0 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 12 # DW_AT_decl_line + .long 86 # DW_AT_type + # DW_AT_external + .byte 8 # Abbrev [8] 0x29:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .byte 2 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 12 # DW_AT_decl_line + .long 86 # DW_AT_type + .byte 8 # Abbrev [8] 0x34:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 112 + .byte 3 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 12 # DW_AT_decl_line + .long 90 # DW_AT_type + .byte 9 # Abbrev [9] 0x3f:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 88 + .byte 5 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 13 # DW_AT_decl_line + .long 104 # DW_AT_type + .byte 9 # Abbrev [9] 0x4a:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 72 + .byte 10 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 17 # DW_AT_decl_line + .long 113 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x56:0x4 DW_TAG_base_type + .byte 1 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 4 # Abbrev [4] 0x5a:0x5 DW_TAG_pointer_type + .long 95 # DW_AT_type + .byte 4 # Abbrev [4] 0x5f:0x5 DW_TAG_pointer_type + .long 100 # DW_AT_type + .byte 5 # Abbrev [5] 0x64:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 10 # Abbrev [10] 0x68:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 7448148824980338162 # DW_AT_signature + .byte 10 # Abbrev [10] 0x71:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 5322170643381124694 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end2: + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_line.dwo,"e",@progbits +.Ltmp2: + .long .Ldebug_line_end0-.Ldebug_line_start0 # unit length +.Ldebug_line_start0: + .short 5 + .byte 8 + .byte 0 + .long .Lprologue_end0-.Lprologue_start0 +.Lprologue_start0: + .byte 1 + .byte 1 + .byte 1 + .byte -5 + .byte 14 + .byte 1 + .byte 1 + .byte 1 + .byte 8 + .byte 1 + .ascii "/home/ayermolo/local/tasks/T104766233" + .byte 0 + .byte 3 + .byte 1 + .byte 8 + .byte 2 + .byte 15 + .byte 5 + .byte 30 + .byte 1 + .ascii "main.cpp" + .byte 0 + .byte 0 + .byte 0xa8, 0x32, 0xf4, 0x64 + .byte 0xc8, 0x53, 0xbe, 0x0f + .byte 0x9c, 0x52, 0xda, 0x29 + .byte 0xcd, 0x91, 0x38, 0x07 +.Lprologue_end0: +.Ldebug_line_end0: + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + .section .debug_gnu_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info +.LpubNames_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 40 # Compilation Unit Length + .long 26 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "main" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_gnu_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info +.LpubTypes_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 40 # Compilation Unit Length + .long 104 # DIE offset + .byte 16 # Attributes: TYPE, EXTERNAL + .asciz "Foo" # External Name + .long 113 # DIE offset + .byte 16 # Attributes: TYPE, EXTERNAL + .asciz "Foo2" # External Name + .long 86 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "int" # External Name + .long 100 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "char" # External Name + .long 0 # End Mark +.LpubTypes_end0: + .ident "clang version 15.0.0" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf5-loclist-offset-form-helper.s b/bolt/test/X86/Inputs/dwarf5-loclist-offset-form-helper.s new file mode 100644 index 0000000000000..5f4b74a04a61c --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-loclist-offset-form-helper.s @@ -0,0 +1,420 @@ +# int fooVar = 0; +# void useFoo(int * x) { +# *x += 4; +# } +# int foo(int argc) { +# int x = argc; +# useFoo(&x); +# return x; +# } + + .text + .file "helper.cpp" + .file 0 "." "helper.cpp" md5 0xf1508be63cfcbaf913e2dfef3cd5bccc + .globl _Z6useFooPi # -- Begin function _Z6useFooPi + .p2align 4, 0x90 + .type _Z6useFooPi,@function +_Z6useFooPi: # @_Z6useFooPi +.Lfunc_begin0: + .loc 0 2 0 # helper.cpp:2:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: useFoo:x <- $rdi + .loc 0 3 5 prologue_end # helper.cpp:3:5 + addl $4, (%rdi) + .loc 0 4 2 # helper.cpp:4:2 + retq +.Ltmp0: +.Lfunc_end0: + .size _Z6useFooPi, .Lfunc_end0-_Z6useFooPi + .cfi_endproc + # -- End function + .globl _Z3fooi # -- Begin function _Z3fooi + .p2align 4, 0x90 + .type _Z3fooi,@function +_Z3fooi: # @_Z3fooi +.Lfunc_begin1: + .loc 0 6 0 # helper.cpp:6:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: foo:argc <- $edi + #DEBUG_VALUE: foo:x <- $edi + # kill: def $edi killed $edi def $rdi + #DEBUG_VALUE: useFoo:x <- undef + .loc 0 3 5 prologue_end # helper.cpp:3:5 + leal 4(%rdi), %eax +.Ltmp1: + #DEBUG_VALUE: foo:x <- $eax + .loc 0 9 5 # helper.cpp:9:5 + retq +.Ltmp2: +.Lfunc_end1: + .size _Z3fooi, .Lfunc_end1-_Z3fooi + .cfi_endproc + # -- End function + .type fooVar,@object # @fooVar + .bss + .globl fooVar + .p2align 2 +fooVar: + .long 0 # 0x0 + .size fooVar, 4 + + .section .debug_loclists,"",@progbits + .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length +.Ldebug_list_header_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 1 # Offset entry count +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin1-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end1-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 80 # super-register DW_OP_reg0 + .byte 0 # DW_LLE_end_of_list +.Ldebug_list_header_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 32 # DW_AT_inline + .byte 33 # DW_FORM_implicit_const + .byte 1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 11 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 23 # DW_FORM_sec_offset + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 12 # Abbreviation Code + .byte 29 # DW_TAG_inlined_subroutine + .byte 0 # DW_CHILDREN_no + .byte 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 88 # DW_AT_call_file + .byte 11 # DW_FORM_data1 + .byte 89 # DW_AT_call_line + .byte 11 # DW_FORM_data1 + .byte 87 # DW_AT_call_column + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x83 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 2 # Abbrev [2] 0x27:0xb DW_TAG_variable + .byte 3 # DW_AT_name + .long 50 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 3 # Abbrev [3] 0x32:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 4 # Abbrev [4] 0x36:0x14 DW_TAG_subprogram + .byte 1 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_call_all_calls + .long 74 # DW_AT_abstract_origin + .byte 5 # Abbrev [5] 0x42:0x7 DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .long 79 # DW_AT_abstract_origin + .byte 0 # End Of Children Mark + .byte 6 # Abbrev [6] 0x4a:0xe DW_TAG_subprogram + .byte 5 # DW_AT_linkage_name + .byte 6 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + # DW_AT_external + # DW_AT_inline + .byte 7 # Abbrev [7] 0x4f:0x8 DW_TAG_formal_parameter + .byte 7 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 88 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 8 # Abbrev [8] 0x58:0x5 DW_TAG_pointer_type + .long 50 # DW_AT_type + .byte 9 # Abbrev [9] 0x5d:0x31 DW_TAG_subprogram + .byte 2 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_call_all_calls + .byte 8 # DW_AT_linkage_name + .byte 9 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 50 # DW_AT_type + # DW_AT_external + .byte 10 # Abbrev [10] 0x6d:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .byte 10 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 50 # DW_AT_type + .byte 11 # Abbrev [11] 0x77:0x9 DW_TAG_variable + .long .Ldebug_loc0 # DW_AT_location + .byte 7 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .long 50 # DW_AT_type + .byte 12 # Abbrev [12] 0x80:0xd DW_TAG_inlined_subroutine + .long 74 # DW_AT_abstract_origin + .byte 2 # DW_AT_low_pc + .long .Ltmp1-.Lfunc_begin1 # DW_AT_high_pc + .byte 0 # DW_AT_call_file + .byte 8 # DW_AT_call_line + .byte 5 # DW_AT_call_column + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 48 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 15.0.0" # string offset=0 +.Linfo_string1: + .asciz "helper.cpp" # string offset=134 +.Linfo_string2: + .asciz "." # string offset=145 +.Linfo_string3: + .asciz "fooVar" # string offset=183 +.Linfo_string4: + .asciz "int" # string offset=190 +.Linfo_string5: + .asciz "_Z6useFooPi" # string offset=194 +.Linfo_string6: + .asciz "useFoo" # string offset=206 +.Linfo_string7: + .asciz "x" # string offset=213 +.Linfo_string8: + .asciz "_Z3fooi" # string offset=215 +.Linfo_string9: + .asciz "foo" # string offset=223 +.Linfo_string10: + .asciz "argc" # string offset=227 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .long .Linfo_string10 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad fooVar + .quad .Lfunc_begin0 + .quad .Lfunc_begin1 +.Ldebug_addr_end0: + .ident "clang version 15.0.0" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf5-loclist-offset-form-main.s b/bolt/test/X86/Inputs/dwarf5-loclist-offset-form-main.s new file mode 100644 index 0000000000000..43e934fe6d9b8 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-loclist-offset-form-main.s @@ -0,0 +1,390 @@ +# void use(int * x, int * y) { +# *x += 4; +# *y -= 2; +# } +# +# extern int fooVar; +# int main(int argc, char *argv[]) { +# int x = argc; +# int y = fooVar + 3; +# use(&x, &y); +# return x + y; +# } + + .text + .file "main.cpp" + .globl _Z3usePiS_ # -- Begin function _Z3usePiS_ + .p2align 4, 0x90 + .type _Z3usePiS_,@function +_Z3usePiS_: # @_Z3usePiS_ +.Lfunc_begin0: + .file 0 "." "main.cpp" md5 0x0df8b93231613cae17dbf82c0897c3b3 + .loc 0 1 0 # main.cpp:1:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: use:x <- $rdi + #DEBUG_VALUE: use:y <- $rsi + .loc 0 2 6 prologue_end # main.cpp:2:6 + addl $4, (%rdi) + .loc 0 3 6 # main.cpp:3:6 + addl $-2, (%rsi) + .loc 0 4 1 # main.cpp:4:1 + retq +.Ltmp0: +.Lfunc_end0: + .size _Z3usePiS_, .Lfunc_end0-_Z3usePiS_ + .cfi_endproc + # -- End function + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin1: + .loc 0 7 0 # main.cpp:7:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: main:argc <- $edi + #DEBUG_VALUE: main:argv <- $rsi + #DEBUG_VALUE: main:x <- $edi + # kill: def $edi killed $edi def $rdi + .loc 0 9 13 prologue_end # main.cpp:9:13 + movq fooVar@GOTPCREL(%rip), %rax + movl (%rax), %eax +.Ltmp1: + #DEBUG_VALUE: main:y <- [DW_OP_plus_uconst 3, DW_OP_stack_value] $eax + #DEBUG_VALUE: main:y <- [DW_OP_plus_uconst 1, DW_OP_stack_value] $eax + #DEBUG_VALUE: main:x <- [DW_OP_plus_uconst 4, DW_OP_stack_value] $edi + .loc 0 11 14 # main.cpp:11:14 + addl %edi, %eax +.Ltmp2: + addl $5, %eax + .loc 0 11 5 is_stmt 0 # main.cpp:11:5 + retq +.Ltmp3: +.Lfunc_end1: + .size main, .Lfunc_end1-main + .cfi_endproc + # -- End function + .section .debug_loclists,"",@progbits + .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length +.Ldebug_list_header_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 2 # Offset entry count +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 + .long .Ldebug_loc1-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin1-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end1-.Lfunc_begin0 # ending offset + .byte 10 # Loc expr size + .byte 117 # DW_OP_breg5 + .byte 4 # 4 + .byte 16 # DW_OP_constu + .byte 255 # 4294967295 + .byte 255 # + .byte 255 # + .byte 255 # + .byte 15 # + .byte 26 # DW_OP_and + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_loc1: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp2-.Lfunc_begin0 # ending offset + .byte 10 # Loc expr size + .byte 112 # DW_OP_breg0 + .byte 1 # 1 + .byte 16 # DW_OP_constu + .byte 255 # 4294967295 + .byte 255 # + .byte 255 # + .byte 255 # + .byte 15 # + .byte 26 # DW_OP_and + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_list_header_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 23 # DW_FORM_sec_offset + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x8a DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 0 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 2 # Abbrev [2] 0x27:0x21 DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_call_all_calls + .byte 3 # DW_AT_linkage_name + .byte 4 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + # DW_AT_external + .byte 3 # Abbrev [3] 0x33:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .byte 7 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 130 # DW_AT_type + .byte 3 # Abbrev [3] 0x3d:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 84 + .byte 8 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 130 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x48:0x36 DW_TAG_subprogram + .byte 1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_call_all_calls + .byte 5 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .long 126 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x57:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .byte 9 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .long 126 # DW_AT_type + .byte 3 # Abbrev [3] 0x61:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 84 + .byte 10 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .long 135 # DW_AT_type + .byte 5 # Abbrev [5] 0x6b:0x9 DW_TAG_variable + .long .Ldebug_loc0 # DW_AT_location + .byte 7 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .long 126 # DW_AT_type + .byte 5 # Abbrev [5] 0x74:0x9 DW_TAG_variable + .long .Ldebug_loc1 # DW_AT_location + .byte 8 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 126 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 6 # Abbrev [6] 0x7e:0x4 DW_TAG_base_type + .byte 6 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 7 # Abbrev [7] 0x82:0x5 DW_TAG_pointer_type + .long 126 # DW_AT_type + .byte 7 # Abbrev [7] 0x87:0x5 DW_TAG_pointer_type + .long 140 # DW_AT_type + .byte 7 # Abbrev [7] 0x8c:0x5 DW_TAG_pointer_type + .long 145 # DW_AT_type + .byte 6 # Abbrev [6] 0x91:0x4 DW_TAG_base_type + .byte 11 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 52 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 15.0.0" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=134 +.Linfo_string2: + .asciz "." # string offset=143 +.Linfo_string3: + .asciz "_Z3usePiS_" # string offset=181 +.Linfo_string4: + .asciz "use" # string offset=192 +.Linfo_string5: + .asciz "main" # string offset=196 +.Linfo_string6: + .asciz "int" # string offset=201 +.Linfo_string7: + .asciz "x" # string offset=205 +.Linfo_string8: + .asciz "y" # string offset=207 +.Linfo_string9: + .asciz "argc" # string offset=209 +.Linfo_string10: + .asciz "argv" # string offset=214 +.Linfo_string11: + .asciz "char" # string offset=219 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .long .Linfo_string10 + .long .Linfo_string11 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 + .quad .Lfunc_begin1 +.Ldebug_addr_end0: + .ident "clang version 15.0.0" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/addr32.s b/bolt/test/X86/addr32.s index ebe849c4d62f0..1f926c20c7ba8 100644 --- a/bolt/test/X86/addr32.s +++ b/bolt/test/X86/addr32.s @@ -3,10 +3,10 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: ld.lld %t.o -o %t.exe -nostdlib # RUN: llvm-objdump -d %t.exe | FileCheck %s -# RUN: llvm-bolt %t.exe -o %t.out -lite=0 -x86-strip-redundant-address-size=false +# RUN: llvm-bolt %t.exe -o %t.out --lite=0 --x86-strip-redundant-address-size=false # RUN: llvm-objdump -d %t.out | FileCheck %s # CHECK: 67 e8 {{.*}} addr32 callq {{.*}} -# RUN: llvm-bolt %t.exe -o %t.out -lite=0 -x86-strip-redundant-address-size=true +# RUN: llvm-bolt %t.exe -o %t.out --lite=0 --x86-strip-redundant-address-size=true # remove test name from objdump output, to only search for addr32 in disassembly # RUN: llvm-objdump -d %t.out | grep -v addr32.s | FileCheck %s --check-prefix=CHECK-STRIP # CHECK-STRIP-NOT: addr32 diff --git a/bolt/test/X86/asm-dump.c b/bolt/test/X86/asm-dump.c index 2720bbc5d2c50..5d85e2a0a151c 100644 --- a/bolt/test/X86/asm-dump.c +++ b/bolt/test/X86/asm-dump.c @@ -7,13 +7,13 @@ * RUN: %clang -fPIC %s -o %t.exe -Wl,-q * * Profile collection: instrument the binary - * RUN: llvm-bolt %t.exe -instrument -instrumentation-file=%t.fdata -o %t.instr + * RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata -o %t.instr * * Profile collection: run instrumented binary (and capture output) * RUN: %t.instr > %t.result * * Run BOLT with asm-dump - * RUN: llvm-bolt %t.exe -p %t.fdata -funcs=main -asm-dump=%t -o /dev/null \ + * RUN: llvm-bolt %t.exe -p %t.fdata --funcs=main --asm-dump=%t -o /dev/null \ * RUN: | FileCheck %s --check-prefix=CHECK-BOLT * * Check asm file contents diff --git a/bolt/test/X86/asm-func-debug.test b/bolt/test/X86/asm-func-debug.test index a8bad6e0c2501..617ad6bb4622d 100644 --- a/bolt/test/X86/asm-func-debug.test +++ b/bolt/test/X86/asm-func-debug.test @@ -4,7 +4,7 @@ # The input test case foo() contains nops that we remove. RUN: %clang -gdwarf-4 %cflags -no-pie %p/../Inputs/asm_foo.s %p/../Inputs/asm_main.c -o %t.exe -RUN: llvm-bolt %t.exe -o %t -update-debug-sections +RUN: llvm-bolt %t.exe -o %t --update-debug-sections RUN: llvm-dwarfdump -all %t | FileCheck %s # Check ranges were created/updated for asm compile unit diff --git a/bolt/test/X86/avx512-trap.test b/bolt/test/X86/avx512-trap.test index 4651c676a6b04..68a0fbc8ff52c 100644 --- a/bolt/test/X86/avx512-trap.test +++ b/bolt/test/X86/avx512-trap.test @@ -7,11 +7,11 @@ RUN: ld.lld %t.o -o %t -q RUN: llvm-objdump -d --disassemble-symbols=use_avx512 %t | \ RUN: FileCheck %s --check-prefix=CHECK-DIS-NO-TRAP -RUN: llvm-bolt %t -trap-avx512=1 -o %t.bolt -lite=0 2>&1 | FileCheck %s +RUN: llvm-bolt %t --trap-avx512=1 -o %t.bolt --lite=0 2>&1 | FileCheck %s RUN: llvm-objdump -d --disassemble-symbols=use_avx512 %t.bolt | \ RUN: FileCheck %s --check-prefix=CHECK-DIS -RUN: llvm-bolt %t -trap-avx512=0 -o %t.bolt -lite=0 +RUN: llvm-bolt %t --trap-avx512=0 -o %t.bolt --lite=0 RUN: llvm-objdump -d --disassemble-symbols=use_avx512 %t.bolt | \ RUN: FileCheck %s --check-prefix=CHECK-DIS-NO-TRAP diff --git a/bolt/test/X86/bb-with-two-tail-calls.s b/bolt/test/X86/bb-with-two-tail-calls.s index f23128301d516..caad7b3d735f5 100644 --- a/bolt/test/X86/bb-with-two-tail-calls.s +++ b/bolt/test/X86/bb-with-two-tail-calls.s @@ -8,8 +8,8 @@ # RUN: link_fdata %s %t.o %t.fdata # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib -# RUN: llvm-bolt %t.exe -o %t.out -data %t.fdata -lite=0 -dyno-stats \ -# RUN: -print-sctc -print-only=_start 2>&1 | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t.out --data %t.fdata --lite=0 --dyno-stats \ +# RUN: --print-sctc --print-only=_start 2>&1 | FileCheck %s # CHECK-NOT: Assertion `BranchInfo.size() == 2 && "could only be called for blocks with 2 successors"' failed. # Two tail calls in the same basic block after SCTC: # CHECK: {{.*}}: ja {{.*}} # TAILCALL # CTCTakenCount: {{.*}} diff --git a/bolt/test/X86/block-reordering.test b/bolt/test/X86/block-reordering.test index 800e7a76bb61e..a18a2109d37e2 100644 --- a/bolt/test/X86/block-reordering.test +++ b/bolt/test/X86/block-reordering.test @@ -2,9 +2,9 @@ # according to the new function layout. RUN: yaml2obj %p/Inputs/blarge.yaml &> %t.exe -RUN: llvm-bolt %t.exe -o /dev/null -data %p/Inputs/blarge.fdata \ -RUN: -reorder-blocks=normal -print-finalized 2>&1 | FileCheck %s \ -RUN: -check-prefix=CHECK +RUN: llvm-bolt %t.exe -o /dev/null --data %p/Inputs/blarge.fdata \ +RUN: --reorder-blocks=normal --print-finalized 2>&1 | FileCheck %s \ +RUN: --check-prefix=CHECK CHECK: Binary Function "usqrt" CHECK: BB Layout : .LBB{{.*}}, .Ltmp{{.*}}, .Ltmp{{.*}}, .LFT{{.*}}, .LFT{{.*}} diff --git a/bolt/test/X86/branch-data.test b/bolt/test/X86/branch-data.test index e069ecd7a7c05..24f90f2d8f5e5 100644 --- a/bolt/test/X86/branch-data.test +++ b/bolt/test/X86/branch-data.test @@ -3,7 +3,7 @@ # Also checks that llvm-bolt disassembler and CFG builder is working properly. RUN: yaml2obj %p/Inputs/blarge.yaml &> %t.exe -RUN: llvm-bolt %t.exe -o /dev/null -data %p/Inputs/blarge.fdata -print-cfg +RUN: llvm-bolt %t.exe -o /dev/null --data %p/Inputs/blarge.fdata --print-cfg CHECK: Binary Function "usqrt" CHECK: State : CFG constructed diff --git a/bolt/test/X86/bug-reorder-bb-jrcxz.s b/bolt/test/X86/bug-reorder-bb-jrcxz.s index 71fdfe1991ca3..27cd38bc83069 100644 --- a/bolt/test/X86/bug-reorder-bb-jrcxz.s +++ b/bolt/test/X86/bug-reorder-bb-jrcxz.s @@ -14,10 +14,10 @@ # RUN: link_fdata %s %t.o %t.fdata # RUN: %clang %cflags %t.o -falign-labels -march=native -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolted -data %t.fdata \ -# RUN: -reorder-blocks=cache+ -reorder-functions=hfsort \ -# RUN: -split-functions=2 -split-all-cold -split-eh -dyno-stats \ -# RUN: -print-finalized 2>&1 | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t.bolted --data %t.fdata \ +# RUN: --reorder-blocks=ext-tsp --reorder-functions=hfsort \ +# RUN: --split-functions=2 --split-all-cold --split-eh --dyno-stats \ +# RUN: --print-finalized 2>&1 | FileCheck %s # CHECK-NOT: value of -2105 is too large for field of 1 byte. diff --git a/bolt/test/X86/cfi-expr-rewrite.s b/bolt/test/X86/cfi-expr-rewrite.s index 62d5694fba38e..27628190c6601 100644 --- a/bolt/test/X86/cfi-expr-rewrite.s +++ b/bolt/test/X86/cfi-expr-rewrite.s @@ -3,7 +3,7 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: %clang %cflags %t.o -o %t.exe -# RUN: llvm-bolt %t.exe -o %t && llvm-dwarfdump -eh-frame %t | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t && llvm-dwarfdump --eh-frame %t | FileCheck %s # # CHECK: DW_CFA_advance_loc: 5 # CHECK-NEXT: DW_CFA_def_cfa: R10 +0 diff --git a/bolt/test/X86/cfi-instrs-count.s b/bolt/test/X86/cfi-instrs-count.s index c74e940a41f82..adf28a9e0811f 100644 --- a/bolt/test/X86/cfi-instrs-count.s +++ b/bolt/test/X86/cfi-instrs-count.s @@ -3,7 +3,7 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: %clang %cflags %t.o -o %t.exe -# RUN: llvm-bolt %t.exe -o /dev/null -print-cfg 2>&1 | FileCheck %s +# RUN: llvm-bolt %t.exe -o /dev/null --print-cfg 2>&1 | FileCheck %s # # CHECK: Binary Function "_Z7catchitv" after building cfg { # CHECK: CFI Instrs : 6 diff --git a/bolt/test/X86/cfi-instrs-reordered.s b/bolt/test/X86/cfi-instrs-reordered.s index a5c96b376cbca..8b2fe512f392c 100644 --- a/bolt/test/X86/cfi-instrs-reordered.s +++ b/bolt/test/X86/cfi-instrs-reordered.s @@ -4,8 +4,8 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clangxx %cflags %t.o -o %t.exe -# RUN: llvm-bolt %t.exe -o %t -reorder-blocks=cache -print-after-lowering \ -# RUN: -print-only=_Z10SolveCubicddddPiPd 2>&1 | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t --reorder-blocks=cache --print-after-lowering \ +# RUN: --print-only=_Z10SolveCubicddddPiPd 2>&1 | FileCheck %s # # Entry BB # CHECK: divsd %xmm0, %xmm1 diff --git a/bolt/test/X86/cmov-conversion.s b/bolt/test/X86/cmov-conversion.s index b8766002b151b..ed7aac8bc5be6 100644 --- a/bolt/test/X86/cmov-conversion.s +++ b/bolt/test/X86/cmov-conversion.s @@ -4,9 +4,9 @@ # RUN: link_fdata %s %t.o %t.fdata # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib -# RUN: llvm-bolt %t.exe -data %t.fdata -o %t -lite=0 -v=2 \ -# RUN: -cmov-conversion -cmov-conversion-misprediction-threshold=-1 \ -# RUN: -cmov-conversion-bias-threshold=-1 -print-all | FileCheck %s +# RUN: llvm-bolt %t.exe --data %t.fdata -o %t --lite=0 -v=2 \ +# RUN: --cmov-conversion --cmov-conversion-misprediction-threshold=-1 \ +# RUN: --cmov-conversion-bias-threshold=-1 --print-all | FileCheck %s # CHECK: BOLT-INFO: CMOVConversion: CmovInHotPath, converted static 1/1 # CHECK: BOLT-INFO: CMOVConversion: CmovNotInHotPath, converted static 1/1 # CHECK: BOLT-INFO: CMOVConversion: MaxIndex, converted static 1/1 diff --git a/bolt/test/X86/ctc-and-unreachable.test b/bolt/test/X86/ctc-and-unreachable.test index aab01d6b1cf96..0a0b7fcff4ce9 100644 --- a/bolt/test/X86/ctc-and-unreachable.test +++ b/bolt/test/X86/ctc-and-unreachable.test @@ -2,7 +2,7 @@ # a fall-through to a next function (result of builtin_unreachable()). RUN: %clang %cflags %p/Inputs/ctc_and_unreachable.s -o %t.exe -Wl,-q -RUN: llvm-bolt %t.exe -o %t -print-after-lowering -print-only=foo 2>&1 | FileCheck %s +RUN: llvm-bolt %t.exe -o %t --print-after-lowering --print-only=foo 2>&1 | FileCheck %s CHECK: Binary Function "foo" CHECK: cmpq $0x1, %rdi diff --git a/bolt/test/X86/data-to-data-pcrel.s b/bolt/test/X86/data-to-data-pcrel.s index 079db8717707b..256682655d6d3 100644 --- a/bolt/test/X86/data-to-data-pcrel.s +++ b/bolt/test/X86/data-to-data-pcrel.s @@ -4,7 +4,7 @@ # RUN: llvm-strip --strip-unneeded %t.o # RUN: ld.lld %t.o -o %t.exe -q --unresolved-symbols=ignore-all # RUN: llvm-readelf -Wr %t.exe | FileCheck %s -# RUN: llvm-bolt -strict %t.exe -relocs -o /dev/null +# RUN: llvm-bolt --strict %t.exe --relocs -o /dev/null .text .globl _start diff --git a/bolt/test/X86/debug-fission-single.s b/bolt/test/X86/debug-fission-single.s index d1a050491b616..fe0308902ec6b 100644 --- a/bolt/test/X86/debug-fission-single.s +++ b/bolt/test/X86/debug-fission-single.s @@ -43,7 +43,7 @@ # CHECK-ADDR-SEC: 0x00000000: Addrs: [ # CHECK-ADDR-SEC: 0x0000000000601000 -# RUN: llvm-bolt %t.exe --reorder-blocks=reverse -update-debug-sections -dwarf-output-path=%T -o %t.bolt.2.exe --write-dwp=true +# RUN: llvm-bolt %t.exe --reorder-blocks=reverse --update-debug-sections --dwarf-output-path=%T -o %t.bolt.2.exe --write-dwp=true # RUN: not llvm-dwarfdump --show-form --verbose --debug-info %t.bolt.2.exe.dwp &> %tAddrIndexTestDwp # RUN: cat %tAddrIndexTestDwp | FileCheck %s --check-prefix=CHECK-DWP-DEBUG diff --git a/bolt/test/X86/double-jump.test b/bolt/test/X86/double-jump.test index eb3e9ec3b7489..fa2271bbb7437 100644 --- a/bolt/test/X86/double-jump.test +++ b/bolt/test/X86/double-jump.test @@ -1,8 +1,8 @@ # Test the double jump removqal peephole. RUN: %clang %cflags %p/Inputs/double_jump.cpp -o %t.exe -RUN: (llvm-bolt %t.exe -peepholes=double-jumps \ -RUN: -eliminate-unreachable -o %t 2>&1 \ +RUN: (llvm-bolt %t.exe --peepholes=double-jumps \ +RUN: --eliminate-unreachable -o %t 2>&1 \ RUN: && llvm-objdump -d %t --print-imm-hex --no-show-raw-insn) | FileCheck %s CHECK: BOLT-INFO: Peephole: 1 double jumps patched. diff --git a/bolt/test/X86/double-rel.s b/bolt/test/X86/double-rel.s new file mode 100644 index 0000000000000..2b6ac93cb191d --- /dev/null +++ b/bolt/test/X86/double-rel.s @@ -0,0 +1,42 @@ +## Check that BOLT can correctly use relocations to symbolize instruction +## operands when an instruction can have up to two relocations associated +## with it. + +# REQUIRES: system-linux + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t.o +# RUN: ld.lld %t.o -o %t.exe -q --Tdata=0x80000 +# RUN: llvm-bolt %t.exe --relocs -o /dev/null --print-only=_start --print-disasm \ +# RUN: | FileCheck %s --check-prefix=CHECK-BOLT +# RUN: llvm-objdump -d --print-imm-hex %t.exe \ +# RUN: | FileCheck %s --check-prefix=CHECK-OBJDUMP + + .data + .globl VAR +VAR: + .quad + + .text + .globl _start + .type _start,@function +_start: + .cfi_startproc + +## VAR value is 0x80000. Using relocations, llvm-bolt should correctly +## symbolize the instruction operands. + + movq $VAR, 0x80000 +# CHECK-BOLT: movq $VAR, 0x80000 +# CHECK-OBJDUMP: movq $0x80000, 0x80000 + + movq $0x80000, VAR +# CHECK-BOLT-NEXT: movq $0x80000, VAR +# CHECK-OBJDUMP-NEXT: movq $0x80000, 0x80000 + + movq $VAR, VAR +# CHECK-BOLT-NEXT: movq $VAR, VAR +# CHECK-OBJDUMP-NEXT: movq $0x80000, 0x80000 + + retq + .size _start, .-_start + .cfi_endproc diff --git a/bolt/test/X86/dwarf-handle-visit-loclist-error.s b/bolt/test/X86/dwarf-handle-visit-loclist-error.s index 1d9acf9fc1718..d5ba74fb60166 100644 --- a/bolt/test/X86/dwarf-handle-visit-loclist-error.s +++ b/bolt/test/X86/dwarf-handle-visit-loclist-error.s @@ -4,7 +4,7 @@ # RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o # RUN: %clang %cflags -dwarf-4 %t1.o -o %t.exe # RUN: llvm-objcopy --remove-section=.debug_loc %t.exe -# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections &> file +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections &> file # RUN: cat file | FileCheck --check-prefix=CHECK %s # Making sure we handle error returned by visitLocationList correctly. diff --git a/bolt/test/X86/dwarf4-df-dualcu-loclist.test b/bolt/test/X86/dwarf4-df-dualcu-loclist.test index 010959b5e1e18..2918690c0bf33 100644 --- a/bolt/test/X86/dwarf4-df-dualcu-loclist.test +++ b/bolt/test/X86/dwarf4-df-dualcu-loclist.test @@ -26,13 +26,13 @@ ; BOLT-DWO-MAIN: version = 0x0004 ; BOLT-DWO-MAIN: DW_TAG_formal_parameter [10] -; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000: +; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000010: ; BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000002, 0x0000000000000014) ; BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000003, 0x0000000000000005) ; BOLT-DWO-MAIN: DW_TAG_formal_parameter [10] -; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000016: +; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000026: ; BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000002, 0x000000000000000c) -; BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000005, 0x000000000000000d) +; BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000004, 0x000000000000000d) ; PRE-BOLT-DWO-HELPER: version = 0x0004 @@ -43,6 +43,6 @@ ; BOLT-DWO-HELPER: version = 0x0004 ; BOLT-DWO-HELPER: DW_TAG_formal_parameter [5] -; BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000: +; BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000010: ; BOLT-DWO-HELPER-NEXT: DW_LLE_startx_length (0x0000000000000002, 0x0000000000000008): DW_OP_reg5 RDI ; BOLT-DWO-HELPER-NEXT: DW_LLE_startx_length (0x0000000000000003, 0x0000000000000016) diff --git a/bolt/test/X86/dwarf4-ftypes-dwo-input-dwp-output.test b/bolt/test/X86/dwarf4-ftypes-dwo-input-dwp-output.test new file mode 100644 index 0000000000000..8fd2f19504373 --- /dev/null +++ b/bolt/test/X86/dwarf4-ftypes-dwo-input-dwp-output.test @@ -0,0 +1,30 @@ +# REQUIRES: system-linux +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llvm-mc --split-dwarf-file=main.dwo --triple=x86_64-unknown-linux-gnu \ +; RUN: --filetype=obj %p/Inputs/dwarf4-ftypes-split-dwarf.s -o=main.o +; RUN: %clang %cflags -gdwarf-4 -gsplit-dwarf=split main.o -o main.exe +; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.dwo | FileCheck -check-prefix=PRE-BOLT %s +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections --write-dwp +; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.exe.bolt.dwp | FileCheck -check-prefix=BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-tu-index main.exe.bolt.dwp | FileCheck -check-prefix=BOLT-DWP-TU-INDEX %s + +; Test input into bolt a .dwo file with TU Index. +; Make sure the output .dwp file has a type information. + +; PRE-BOLT: DW_TAG_type_unit +; PRE-BOLT: DW_TAG_type_unit + +; PRE-BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4 +; PRE-BOLT-DWP-TU-INDEX: Index Signature +; PRE-BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2 +; PRE-BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56 + +; BOLT: DW_TAG_type_unit +; BOLT: DW_TAG_type_unit + +; BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4 +; BOLT-DWP-TU-INDEX: Index Signature +; BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2 +; BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56 diff --git a/bolt/test/X86/dwarf4-ftypes-dwp-input-dwo-output.test b/bolt/test/X86/dwarf4-ftypes-dwp-input-dwo-output.test new file mode 100644 index 0000000000000..0fa5577017a18 --- /dev/null +++ b/bolt/test/X86/dwarf4-ftypes-dwp-input-dwo-output.test @@ -0,0 +1,26 @@ +# REQUIRES: system-linux +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llvm-mc --split-dwarf-file=main.dwo --triple=x86_64-unknown-linux-gnu \ +; RUN: --filetype=obj %p/Inputs/dwarf4-ftypes-split-dwarf.s -o=main.o +; RUN: %clang %cflags -gdwarf-4 -gsplit-dwarf=split main.o -o main.exe +; RUN: llvm-dwp -e main.exe -o main.exe.dwp +; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.exe.dwp | FileCheck -check-prefix=PRE-BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-tu-index main.exe.dwp | FileCheck -check-prefix=PRE-BOLT-DWP-TU-INDEX %s +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections +; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.dwo.dwo | FileCheck -check-prefix=BOLT %s + +; Test input into bolt a DWP file with TU Index. +; Make sure output in the .dwo files has type information. + +; PRE-BOLT: DW_TAG_type_unit +; PRE-BOLT: DW_TAG_type_unit + +; PRE-BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4 +; PRE-BOLT-DWP-TU-INDEX: Index Signature +; PRE-BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2 +; PRE-BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56 + +; BOLT: DW_TAG_type_unit +; BOLT: DW_TAG_type_unit diff --git a/bolt/test/X86/dwarf4-ftypes-dwp-input-dwp-output.test b/bolt/test/X86/dwarf4-ftypes-dwp-input-dwp-output.test new file mode 100644 index 0000000000000..52c13a0d66cf0 --- /dev/null +++ b/bolt/test/X86/dwarf4-ftypes-dwp-input-dwp-output.test @@ -0,0 +1,32 @@ +# REQUIRES: system-linux +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llvm-mc --split-dwarf-file=main.dwo --triple=x86_64-unknown-linux-gnu \ +; RUN: --filetype=obj %p/Inputs/dwarf4-ftypes-split-dwarf.s -o=main.o +; RUN: %clang %cflags -gdwarf-4 -gsplit-dwarf=split main.o -o main.exe +; RUN: llvm-dwp -e main.exe -o main.exe.dwp +; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.exe.dwp | FileCheck -check-prefix=PRE-BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-tu-index main.exe.dwp | FileCheck -check-prefix=PRE-BOLT-DWP-TU-INDEX %s +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections --write-dwp +; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.exe.bolt.dwp | FileCheck -check-prefix=BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-tu-index main.exe.bolt.dwp | FileCheck -check-prefix=BOLT-DWP-TU-INDEX %s + +; Test input into bolt a DWP file with TU Index. +; Make sure the output .dwp file has a type information. + +; PRE-BOLT: DW_TAG_type_unit +; PRE-BOLT: DW_TAG_type_unit + +; PRE-BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4 +; PRE-BOLT-DWP-TU-INDEX: Index Signature +; PRE-BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2 +; PRE-BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56 + +; BOLT: DW_TAG_type_unit +; BOLT: DW_TAG_type_unit + +; BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4 +; BOLT-DWP-TU-INDEX: Index Signature +; BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2 +; BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56 diff --git a/bolt/test/X86/dwarf5-debug-info-dwarf4-debug-line.s b/bolt/test/X86/dwarf5-debug-info-dwarf4-debug-line.s index 4e7e7cd7b4b71..6042bbee8948c 100644 --- a/bolt/test/X86/dwarf5-debug-info-dwarf4-debug-line.s +++ b/bolt/test/X86/dwarf5-debug-info-dwarf4-debug-line.s @@ -2,7 +2,7 @@ # RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o # RUN: %clang %cflags -dwarf-5 %t1.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections # RUN: llvm-dwarfdump --show-form --verbose --debug-line %t.exe | FileCheck --check-prefix=PRECHECK %s # RUN: llvm-dwarfdump --show-form --verbose --debug-line %t.bolt | FileCheck --check-prefix=POSTCHECK %s diff --git a/bolt/test/X86/dwarf5-debug-line.s b/bolt/test/X86/dwarf5-debug-line.s index 040a259871086..5b1cdba712a9b 100644 --- a/bolt/test/X86/dwarf5-debug-line.s +++ b/bolt/test/X86/dwarf5-debug-line.s @@ -2,24 +2,28 @@ # RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o # RUN: %clang %cflags -dwarf-5 %t1.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections # RUN: llvm-dwarfdump --show-form --verbose --debug-line %t.exe | FileCheck --check-prefix=PRECHECK %s # RUN: llvm-dwarfdump --show-form --verbose --debug-line %t.bolt | FileCheck --check-prefix=POSTCHECK %s # This test checks that DWARF5 .debug_line is handled correctly. # PRECHECK: version: 5 -# PRECHECK: include_directories[ 0] = .debug_line_str[0x00000000] +# PRECHECK: include_directories[ 0] = .debug_line_str +# PRECHECK-SAME: ] = "." # PRECHECK-NEXT: file_names[ 0]: -# PRECHECK-NEXT: name: .debug_line_str[0x00000002] = "main.cpp" +# PRECHECK-NEXT: name: .debug_line_str +# PRECHECK-SAME: = "main.cpp" # PRECHECK-NEXT: dir_index: 0 # PRECHECK-NEXT: md5_checksum: bb12fec8d002b1f0e06f7dee4604c6cc # PRECHECK-NOT: file_names[ 1]: # POSTCHECK: version: 5 -# POSTCHECK: include_directories[ 0] = .debug_line_str[0x00000000] +# POSTCHECK: include_directories[ 0] = .debug_line_str +# POSTCHECK-SAME: ] = "." # POSTCHECK-NEXT: file_names[ 0]: -# POSTCHECK-NEXT: name: .debug_line_str[0x00000002] = "main.cpp" +# POSTCHECK-NEXT: name: .debug_line_str +# POSTCHECK-SAME: ] = "main.cpp" # POSTCHECK-NEXT: dir_index: 0 # POSTCHECK-NEXT: md5_checksum: bb12fec8d002b1f0e06f7dee4604c6cc # POSTCHECK-NOT: file_names[ 1]: diff --git a/bolt/test/X86/dwarf5-debug-loclists.s b/bolt/test/X86/dwarf5-debug-loclists.s index 440e94115701e..97fa5b828e7f9 100644 --- a/bolt/test/X86/dwarf5-debug-loclists.s +++ b/bolt/test/X86/dwarf5-debug-loclists.s @@ -2,7 +2,7 @@ # RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o # RUN: %clang %cflags -dwarf-5 %t1.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s # RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt > %t.txt # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt >> %t.txt diff --git a/bolt/test/X86/dwarf5-ftypes-dwp-input-dwo-output.test b/bolt/test/X86/dwarf5-ftypes-dwp-input-dwo-output.test new file mode 100644 index 0000000000000..4b928c4b13343 --- /dev/null +++ b/bolt/test/X86/dwarf5-ftypes-dwp-input-dwo-output.test @@ -0,0 +1,27 @@ +# REQUIRES: system-linux +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llvm-mc --split-dwarf-file=main.dwo --triple=x86_64-unknown-linux-gnu \ +; RUN: --filetype=obj %p/Inputs/dwarf5-ftypes-split-dwarf.s -o=main.o +; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o -o main.exe +; RUN: llvm-dwp -e main.exe -o main.exe.dwp +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.exe.dwp | FileCheck -check-prefix=PRE-BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-tu-index main.exe.dwp | FileCheck -check-prefix=PRE-BOLT-DWP-TU-INDEX %s +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo.dwo | FileCheck -check-prefix=BOLT %s + +; Test input into bolt a DWP file with TU Index. +; Make sure output in the .dwo files has type information. + +; PRE-BOLT: DW_TAG_type_unit +; PRE-BOLT: DW_TAG_type_unit + +; PRE-BOLT-DWP-TU-INDEX: version = 5, units = 2, slots = 4 +; PRE-BOLT-DWP-TU-INDEX: Index Signature +; PRE-BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2 +; PRE-BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56 + +; BOLT: DW_TAG_type_unit +; BOLT: DW_TAG_type_unit +; BOLT: DW_TAG_compile_unit diff --git a/bolt/test/X86/dwarf5-label-low-pc.s b/bolt/test/X86/dwarf5-label-low-pc.s index fbcbbe0524377..b713097163348 100644 --- a/bolt/test/X86/dwarf5-label-low-pc.s +++ b/bolt/test/X86/dwarf5-label-low-pc.s @@ -3,7 +3,7 @@ # RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %tmain.o # RUN: %clang %cflags -dwarf-5 %tmain.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s # RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt > %t.txt diff --git a/bolt/test/X86/dwarf5-locexpr-addrx.s b/bolt/test/X86/dwarf5-locexpr-addrx.s index 0e1d1a5c978db..c78c5f0cedb9a 100644 --- a/bolt/test/X86/dwarf5-locexpr-addrx.s +++ b/bolt/test/X86/dwarf5-locexpr-addrx.s @@ -2,7 +2,7 @@ # RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %tmain.o # RUN: %clang %cflags -dwarf-5 %tmain.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt | FileCheck --check-prefix=POSTCHECK %s diff --git a/bolt/test/X86/dwarf5-loclist-offset-form.test b/bolt/test/X86/dwarf5-loclist-offset-form.test new file mode 100644 index 0000000000000..07c29cd641767 --- /dev/null +++ b/bolt/test/X86/dwarf5-loclist-offset-form.test @@ -0,0 +1,56 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-loclist-offset-form-main.s -o %tmain.o +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-loclist-offset-form-helper.s -o %thelper.o +# RUN: %clang %cflags -dwarf-5 %tmain.o %thelper.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s +# RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt > %t.txt +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt >> %t.txt +# RUN: cat %t.txt | FileCheck --check-prefix=POSTCHECK %s + +# Checks we can handle DWARF5 CU with DWARF4 DW_AT_location access pattern. + +# PRECHECK: DW_TAG_compile_unit +# PRECHECK: DW_TAG_variable [5] +# PRECHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] +# PRECHECK: DW_TAG_variable [5] +# PRECHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] +# PRECHECK: DW_TAG_compile_unit +# PRECHECK: DW_TAG_variable [11] +# PRECHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] + +# POSTCHECK: Addrs: [ +# POSTCHECK-NEXT: 0x[[#%.16x,ADDR:]] +# POSTCHECK-NEXT: 0x[[#%.16x,ADDR1:]] +# POSTCHECK-NEXT: 0x[[#%.16x,ADDR2:]] +# POSTCHECK-NEXT: 0x[[#%.16x,ADDR3:]] +# For second CU. +# POSTCHECK: Addrs: [ +# POSTCHECK-NEXT: 0x[[#%.16x,ADDR4:]] +# POSTCHECK-NEXT: 0x[[#%.16x,ADDR5:]] +# POSTCHECK-NEXT: 0x[[#%.16x,ADDR6:]] +# POSTCHECK-NEXT: 0x[[#%.16x,ADDR7:]] +# POSTCHECK-NEXT: 0x[[#%.16x,ADDR8:]] + +# POSTCHECK: DW_TAG_compile_unit +# POSTCHECK: DW_AT_loclists_base [DW_FORM_sec_offset] (0x0000000c) +# POSTCHECK: DW_TAG_variable [5] +# POSTCHECK-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x0) +# POSTCHECK-NEXT: [0x[[#ADDR1]] +# POSTCHECK-SAME: 0x[[#ADDR1 + 9]] +# POSTCHECK-NEXT: [0x[[#ADDR3]] +# POSTCHECK-SAME: 0x[[#ADDR3 + 6]] +# POSTCHECK: DW_TAG_variable [5] +# POSTCHECK-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x1) +# POSTCHECK-NEXT: [0x[[#ADDR3]] +# POSTCHECK-SAME: 0x[[#ADDR3 + 2]] + +# POSTCHECK: DW_TAG_compile_unit +# POSTCHECK: DW_AT_loclists_base [DW_FORM_sec_offset] (0x00000043) +# POSTCHECK: DW_TAG_variable [11] +# POSTCHECK-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x0) +# POSTCHECK-NEXT: [0x[[#ADDR5]] +# POSTCHECK-SAME: 0x[[#ADDR5 + 3]] +# POSTCHECK-NEXT: [0x[[#ADDR8]] +# POSTCHECK-SAME: 0x[[#ADDR8 + 1]] diff --git a/bolt/test/X86/dwarf5-lowpc-highpc-convert.s b/bolt/test/X86/dwarf5-lowpc-highpc-convert.s index 25778131aa472..4bb2b48374481 100644 --- a/bolt/test/X86/dwarf5-lowpc-highpc-convert.s +++ b/bolt/test/X86/dwarf5-lowpc-highpc-convert.s @@ -2,7 +2,7 @@ # RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o # RUN: %clang %cflags -dwarf-5 %t1.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s # RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt > %t.txt # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt >> %t.txt diff --git a/bolt/test/X86/dwarf5-rangeoffset-to-rangeindex.s b/bolt/test/X86/dwarf5-rangeoffset-to-rangeindex.s index 94f01fcc6edc8..0b32a373a9b80 100644 --- a/bolt/test/X86/dwarf5-rangeoffset-to-rangeindex.s +++ b/bolt/test/X86/dwarf5-rangeoffset-to-rangeindex.s @@ -2,7 +2,7 @@ # RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o # RUN: %clang %cflags -dwarf-5 %t1.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s # RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt > %t.txt # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt >> %t.txt diff --git a/bolt/test/X86/dwarf5-two-loclists.test b/bolt/test/X86/dwarf5-two-loclists.test index 54194b46ee5c9..566f63abbf73c 100644 --- a/bolt/test/X86/dwarf5-two-loclists.test +++ b/bolt/test/X86/dwarf5-two-loclists.test @@ -3,7 +3,7 @@ # RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5_main.s -o %tmain.o # RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5_helper.s -o %thelper.o # RUN: %clang %cflags -dwarf-5 %tmain.o %thelper.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s # RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt > %t.txt # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt >> %t.txt diff --git a/bolt/test/X86/dwarf5-two-rnglists.test b/bolt/test/X86/dwarf5-two-rnglists.test index bbf3ab642b1f9..936a216a0ec2f 100644 --- a/bolt/test/X86/dwarf5-two-rnglists.test +++ b/bolt/test/X86/dwarf5-two-rnglists.test @@ -3,7 +3,7 @@ # RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5_main.s -o %tmain.o # RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5_helper.s -o %thelper.o # RUN: %clang %cflags -dwarf-5 %tmain.o %thelper.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s # RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt > %t.txt # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt >> %t.txt diff --git a/bolt/test/X86/exceptions-args.test b/bolt/test/X86/exceptions-args.test index cfcd148fc55db..fe9423896f68d 100644 --- a/bolt/test/X86/exceptions-args.test +++ b/bolt/test/X86/exceptions-args.test @@ -3,7 +3,7 @@ RUN: %clang %cflags %p/../Inputs/stub.c -fPIC -pie -shared -o %t.so RUN: %clangxx %cxxflags -no-pie %p/Inputs/exc_args.s -o %t %t.so -Wl,-z,notext -RUN: llvm-bolt %t -o /dev/null -print-finalized -print-only=main | FileCheck %s +RUN: llvm-bolt %t -o /dev/null --print-finalized --print-only=main | FileCheck %s CHECK: Binary Function "main" after finalize-functions CHECK: callq _Z3fooiiiiiiii {{.*}} GNU_args_size = 16 diff --git a/bolt/test/X86/fallthrough-to-noop.test b/bolt/test/X86/fallthrough-to-noop.test index 577a2a37f7898..909af8ff423a6 100644 --- a/bolt/test/X86/fallthrough-to-noop.test +++ b/bolt/test/X86/fallthrough-to-noop.test @@ -3,11 +3,11 @@ RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \ RUN: %S/Inputs/ft_to_noop.s -o %t.o -RUN: link_fdata %S/Inputs/ft_to_noop.s %t.o %t.fdata +RUN: link_fdata %S/Inputs/ft_to_noop.s %t.o %t.fdata --nmtool llvm-nm RUN: llvm-strip --strip-unneeded %t.o RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -RUN: llvm-bolt %t.exe -o %t -data %t.fdata \ -RUN: -print-cfg -sequential-disassembly 2>&1 | FileCheck %s +RUN: llvm-bolt %t.exe -o %t --data %t.fdata \ +RUN: --print-cfg --sequential-disassembly 2>&1 | FileCheck %s CHECK: Binary Function "foo" after building cfg CHECK: Exec Count : 20 diff --git a/bolt/test/X86/false-jump-table.s b/bolt/test/X86/false-jump-table.s index 8f969b7ec8221..8cb87ed821e0e 100755 --- a/bolt/test/X86/false-jump-table.s +++ b/bolt/test/X86/false-jump-table.s @@ -7,8 +7,8 @@ # RUN: %s -o %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -print-cfg \ -# RUN: -print-only=inc_dup -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --print-cfg \ +# RUN: --print-only=inc_dup -o %t.out | FileCheck %s .file "jump_table.c" .section .rodata diff --git a/bolt/test/X86/fptr-addend-pcrel.s b/bolt/test/X86/fptr-addend-pcrel.s index 722f20ed5157e..0e84a8fd36004 100644 --- a/bolt/test/X86/fptr-addend-pcrel.s +++ b/bolt/test/X86/fptr-addend-pcrel.s @@ -6,7 +6,7 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t.o # RUN: llvm-strip --strip-unneeded %t.o # RUN: ld.lld %t.o -o %t.exe -q -# RUN: llvm-bolt %t.exe -relocs -o /dev/null -print-only=foo -print-disasm \ +# RUN: llvm-bolt %t.exe --relocs -o /dev/null --print-only=foo --print-disasm \ # RUN: | FileCheck %s .text diff --git a/bolt/test/X86/gdbindex.test b/bolt/test/X86/gdbindex.test index f954c9078f402..36c22260e2655 100644 --- a/bolt/test/X86/gdbindex.test +++ b/bolt/test/X86/gdbindex.test @@ -1,7 +1,7 @@ RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %p/Inputs/dwarfdump-gdbindex.s -o %t.o RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %p/Inputs/dwarfdump-gdbindex2.s -o %t2.o RUN: ld.lld --gdb-index %t.o %t2.o -o %tfile.exe -RUN: llvm-bolt %tfile.exe -o %tfile.exe.bolt -update-debug-sections +RUN: llvm-bolt %tfile.exe -o %tfile.exe.bolt --update-debug-sections RUN: llvm-dwarfdump -gdb-index %tfile.exe.bolt | FileCheck %s ; test.cpp: diff --git a/bolt/test/X86/gotpcrelx.s b/bolt/test/X86/gotpcrelx.s index bb6b43e96aade..00937e43effe4 100644 --- a/bolt/test/X86/gotpcrelx.s +++ b/bolt/test/X86/gotpcrelx.s @@ -1,46 +1,69 @@ -# This reproduces a bug with misinterpreting the gotpcrelx reloc - -# Here we use llvm-mc -relax-relocations to produce R_X86_64_REX_GOTPCRELX -# and ld.lld to consume it and optimize it, transforming a CMP -# into CMP . -# Then we check that BOLT updates correctly the imm operand that references -# a function address. Currently XFAIL as we do not support it. - # REQUIRES: system-linux -# XFAIL: * + +## Check that BOLT correctly handles different types of instructions with +## R_X86_64_GOTPCRELX or R_X86_64_REX_GOTPCRELX relocations and different +## kinds of handling of the relocation by the linker (no relaxation, pic, and +## non-pic). # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux \ # RUN: -relax-relocations %s -o %t.o -# RUN: llvm-strip --strip-unneeded %t.o # RUN: ld.lld %t.o -o %t.exe -q -# RUN: llvm-readobj -r %t.exe | FileCheck --check-prefix=READOBJ %s -# RUN: llvm-bolt %t.exe -relocs -o %t.out -lite=0 +# RUN: ld.lld %t.o -o %t.pie.exe -q -pie +# RUN: ld.lld %t.o -o %t.no-relax.exe -q --no-relax +# RUN: llvm-bolt %t.exe --relocs -o %t.out --print-cfg --print-only=_start \ +# RUN: |& FileCheck --check-prefix=BOLT %s +# RUN: llvm-bolt %t.pie.exe -o /dev/null --print-cfg --print-only=_start \ +# RUN: |& FileCheck --check-prefix=PIE-BOLT %s +# RUN: llvm-bolt %t.no-relax.exe -o /dev/null --print-cfg --print-only=_start \ +# RUN: |& FileCheck --check-prefix=NO-RELAX-BOLT %s # RUN: llvm-objdump -d --no-show-raw-insn --print-imm-hex \ # RUN: %t.out | FileCheck --check-prefix=DISASM %s -# Check that R_X86_64_REX_GOTPCRELX is present in the input binary -# READOBJ: 0x[[#%X,]] R_X86_64_REX_GOTPCRELX foo 0x[[#%X,]] - -# DISASM: Disassembly of section .text: -# DISASM-EMPTY: -# DISASM-NEXT: <_start>: -# DISASM-NEXT: leaq 0x[[#%x,ADDR:]], %rax -# DISASM-NEXT: cmpq 0x[[#ADDR]], %rax - .text .globl _start .type _start, %function _start: .cfi_startproc - leaq foo, %rax - cmpq foo@GOTPCREL(%rip), %rax - je b -c: - mov $1, %rdi - callq foo -b: - xorq %rdi, %rdi - callq foo +# DISASM: Disassembly of section .text: +# DISASM-EMPTY: +# DISASM-NEXT: <_start>: + + call *foo@GOTPCREL(%rip) +# NO-RELAX-BOLT: callq *{{.*}}(%rip) +# BOLT: callq foo +# PIE-BOLT: callq foo +# DISASM-NEXT: callq 0x[[#%x,ADDR:]] + + movq foo@GOTPCREL(%rip), %rdi +# NO-RELAX-BOLT-NEXT: movq {{.*}}(%rip), %rdi +# BOLT-NEXT: leaq foo(%rip), %rdi +# PIE-BOLT-NEXT: leaq foo(%rip), %rdi +# DISASM-NEXT: leaq {{.*}}(%rip), %rdi # 0x[[#ADDR]] + + movl foo@GOTPCREL+4(%rip), %edi +# NO-RELAX-BOLT-NEXT: movl {{.*}}(%rip), %edi +# BOLT-NEXT: movl {{.*}}(%rip), %edi +# PIE-BOLT-NEXT: movl {{.*}}(%rip), %edi +# DISASM-NEXT: movl {{.*}}(%rip), %edi + + test %rdi, foo@GOTPCREL(%rip) +# NO-RELAX-BOLT-NEXT: testq %rdi, DATA{{.*}}(%rip) +# BOLT-NEXT: testq $foo, %rdi +# PIE-BOLT-NEXT: testq %rdi, DATA{{.*}}(%rip) +# DISASM-NEXT: testq $0x[[#ADDR]], %rdi + + cmpq foo@GOTPCREL(%rip), %rax +# NO-RELAX-BOLT-NEXT: cmpq DATA{{.*}}(%rip), %rax +# BOLT-NEXT: cmpq $foo, %rax +# PIE-BOLT-NEXT: cmpq DATA{{.*}}(%rip), %rax +# DISASM-NEXT: cmpq $0x[[#ADDR]], %rax + + jmp *foo@GOTPCREL(%rip) +# NO-RELAX-BOLT-NEXT: jmpq *DATA{{.*}}(%rip) +# BOLT-NEXT: jmp foo +# PIE-BOLT-NEXT: jmp foo +# DISASM-NEXT: jmp 0x[[#ADDR]] + ret .cfi_endproc .size _start, .-_start diff --git a/bolt/test/X86/high_pc_udata.s b/bolt/test/X86/high_pc_udata.s index 18db02a5ad8d7..998058df0b059 100644 --- a/bolt/test/X86/high_pc_udata.s +++ b/bolt/test/X86/high_pc_udata.s @@ -2,7 +2,7 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o # RUN: %clang %cflags %t1.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt | FileCheck --check-prefix=POSTCHECK %s diff --git a/bolt/test/X86/icf-jump-tables.test b/bolt/test/X86/icf-jump-tables.test index 50c080021d445..41820008b0133 100644 --- a/bolt/test/X86/icf-jump-tables.test +++ b/bolt/test/X86/icf-jump-tables.test @@ -4,7 +4,7 @@ # REQUIRES: system-linux # RUN: %clang %cflags -O1 -g %p/../Inputs/icf-jump-tables.c -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -icf -o %t.bolt |& FileCheck %s +# RUN: llvm-bolt %t.exe --icf -o %t.bolt |& FileCheck %s ## Check that BOLT successfully folded a function with jump table: # CHECK: ICF folded {{.*}}. {{[^0]}} functions had jump tables. diff --git a/bolt/test/X86/indirect-goto.test b/bolt/test/X86/indirect-goto.test index fcd0d761ab0ab..e2565ff889327 100644 --- a/bolt/test/X86/indirect-goto.test +++ b/bolt/test/X86/indirect-goto.test @@ -1,6 +1,7 @@ # Check llvm-bolt processes binaries compiled from sources that use indirect goto. RUN: %clang %cflags -no-pie %S/Inputs/indirect_goto.c -Wl,-q -o %t -RUN: llvm-bolt %t -o /dev/null -relocs=1 -print-cfg -print-only=main -strict \ +RUN: llvm-bolt %t -o /dev/null --relocs=1 --print-cfg --print-only=main \ +RUN: --strict \ RUN: 2>&1 | FileCheck %s # Check that all possible destinations are included as successors. diff --git a/bolt/test/X86/inline-debug-info.test b/bolt/test/X86/inline-debug-info.test index 950245c7cb7d2..e20e5e31ed9d5 100644 --- a/bolt/test/X86/inline-debug-info.test +++ b/bolt/test/X86/inline-debug-info.test @@ -5,8 +5,9 @@ # RUN: %clang %cflags -O1 -g %p/Inputs/inline-main.c %p/Inputs/inline-foo.c \ # RUN: -I%p/../Inputs -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -update-debug-sections -print-debug-info \ -# RUN: -print-only=main -print-after-lowering -force-inline=foo -o %t.bolt \ +# RUN: llvm-bolt %t.exe --update-debug-sections --print-debug-info \ +# RUN: --print-only=main --print-after-lowering --force-inline=foo \ +# RUN: -o %t.bolt \ # RUN: | FileCheck %s ## The call to puts() should come from inline-foo.c: diff --git a/bolt/test/X86/inlined-function-mixed.test b/bolt/test/X86/inlined-function-mixed.test index 728e3b82e0948..5a87bdde9535e 100644 --- a/bolt/test/X86/inlined-function-mixed.test +++ b/bolt/test/X86/inlined-function-mixed.test @@ -5,7 +5,7 @@ RUN: %clangxx %cxxflags %S/Inputs/inlined.cpp -c -o %T/inlined.o RUN: %clangxx %cxxflags %S/Inputs/inlinee.cpp -c -o %T/inlinee.o -g RUN: %clangxx %cxxflags %T/inlined.o %T/inlinee.o -o %t -RUN: llvm-bolt %t -o %t.bolt -update-debug-sections -reorder-blocks=reverse \ -RUN: -inline-small-functions -force-inline=main | FileCheck %s +RUN: llvm-bolt %t -o %t.bolt --update-debug-sections --reorder-blocks=reverse \ +RUN: --inline-small-functions --force-inline=main | FileCheck %s CHECK-NOT: BOLT: 0 out of {{.*}} functions were overwritten diff --git a/bolt/test/X86/insert-addr-rnglists_base.s b/bolt/test/X86/insert-addr-rnglists_base.s index 76ba7917a727e..800bed27243d1 100644 --- a/bolt/test/X86/insert-addr-rnglists_base.s +++ b/bolt/test/X86/insert-addr-rnglists_base.s @@ -2,7 +2,7 @@ # RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o # RUN: %clang %cflags -dwarf-5 %t1.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt | FileCheck --check-prefix=POSTCHECK %s diff --git a/bolt/test/X86/internal-call-instrument-so.s b/bolt/test/X86/internal-call-instrument-so.s index 67a6e4ec6478d..b8903fc7f8223 100644 --- a/bolt/test/X86/internal-call-instrument-so.s +++ b/bolt/test/X86/internal-call-instrument-so.s @@ -6,7 +6,7 @@ # Delete our BB symbols so BOLT doesn't mark them as entry points # RUN: llvm-strip --strip-unneeded %t.o # RUN: ld.lld %t.o -o %t.exe -q -shared -fini=_fini -# RUN: llvm-bolt -instrument %t.exe -relocs -o %t.out +# RUN: llvm-bolt --instrument %t.exe --relocs -o %t.out .text .globl _start diff --git a/bolt/test/X86/internal-call-instrument.s b/bolt/test/X86/internal-call-instrument.s index 9915049210f35..c13717472be40 100644 --- a/bolt/test/X86/internal-call-instrument.s +++ b/bolt/test/X86/internal-call-instrument.s @@ -7,7 +7,7 @@ # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt -instrument %t.exe -relocs -o %t.out +# RUN: llvm-bolt --instrument %t.exe --relocs -o %t.out .text .globl main diff --git a/bolt/test/X86/interprocedural-ref-entry-point.s b/bolt/test/X86/interprocedural-ref-entry-point.s index 5ff5ca265f4b4..0e1cca5c9bfe6 100644 --- a/bolt/test/X86/interprocedural-ref-entry-point.s +++ b/bolt/test/X86/interprocedural-ref-entry-point.s @@ -19,7 +19,8 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: %clangxx %cxxflags -no-pie %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.out -dump-dot-all -funcs=main.* 2>&1 | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t.out --dump-dot-all --funcs=main.* \ +# RUN: 2>&1 | FileCheck %s # # CHECK-NOT: Assertion `isValid()' failed. diff --git a/bolt/test/X86/issue20.s b/bolt/test/X86/issue20.s index 8894f816c4fd7..ea57df1f92a8d 100755 --- a/bolt/test/X86/issue20.s +++ b/bolt/test/X86/issue20.s @@ -7,7 +7,7 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \ # RUN: %s -o %t.o # RUN: %clang %cflags -no-pie %t.o -o %t.exe -# RUN: llvm-bolt %t.exe -relocs=0 -jump-tables=move -print-finalized \ +# RUN: llvm-bolt %t.exe --relocs=0 --jump-tables=move --print-finalized \ # RUN: -o %t.out | FileCheck %s # CHECK: BOLT-INFO: UCE removed 0 blocks and 0 bytes of code. diff --git a/bolt/test/X86/issue20.test b/bolt/test/X86/issue20.test index de9c39b947da3..d01a3bf0380a5 100755 --- a/bolt/test/X86/issue20.test +++ b/bolt/test/X86/issue20.test @@ -3,7 +3,7 @@ # in a JT" # RUN: yaml2obj %p/Inputs/issue20.yaml &> %t.exe -# RUN: llvm-bolt %t.exe -relocs=0 -jump-tables=move -print-finalized \ +# RUN: llvm-bolt %t.exe --relocs=0 --jump-tables=move --print-finalized \ # RUN: -o %t.out | FileCheck %s CHECK: BOLT-INFO: UCE removed 0 blocks and 0 bytes of code. diff --git a/bolt/test/X86/issue26.s b/bolt/test/X86/issue26.s index bf383eb47bbee..a6e38b6e4ceff 100755 --- a/bolt/test/X86/issue26.s +++ b/bolt/test/X86/issue26.s @@ -7,7 +7,7 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \ # RUN: %s -o %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -relocs -print-cfg -o %t.out \ +# RUN: llvm-bolt %t.exe --relocs --print-cfg -o %t.out \ # RUN: | FileCheck %s # CHECK-NOT: BOLT-WARNING: CFG invalid in XYZ @ .LBB0 diff --git a/bolt/test/X86/issue26.test b/bolt/test/X86/issue26.test index 423edd3a35d28..5bf25e6a59bab 100755 --- a/bolt/test/X86/issue26.test +++ b/bolt/test/X86/issue26.test @@ -1,7 +1,7 @@ # This reproduces issue 26 from our github repo # RUN: yaml2obj %p/Inputs/issue26.yaml &> %t.exe -# RUN: llvm-bolt %t.exe -relocs -print-cfg -o %t.out \ +# RUN: llvm-bolt %t.exe --relocs --print-cfg -o %t.out \ # RUN: | FileCheck %s CHECK-NOT: BOLT-WARNING: CFG invalid in XYZ @ .LBB0 diff --git a/bolt/test/X86/jmpjmp.test b/bolt/test/X86/jmpjmp.test index 81817f95f184a..b512001c3c446 100644 --- a/bolt/test/X86/jmpjmp.test +++ b/bolt/test/X86/jmpjmp.test @@ -3,7 +3,7 @@ RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %S/Inputs/jmpjmp.s -o %t.o RUN: %clang %cflags %t.o -o %t.exe -RUN: llvm-bolt %t.exe -o /dev/null -print-cfg 2>&1 | FileCheck %s +RUN: llvm-bolt %t.exe -o /dev/null --print-cfg 2>&1 | FileCheck %s CHECK: Binary Function "testfunc" CHECK: State : CFG constructed diff --git a/bolt/test/X86/jump-table-footprint-reduction.test b/bolt/test/X86/jump-table-footprint-reduction.test index f646cefa785a7..5a007c626eca8 100644 --- a/bolt/test/X86/jump-table-footprint-reduction.test +++ b/bolt/test/X86/jump-table-footprint-reduction.test @@ -3,11 +3,11 @@ RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \ RUN: %S/Inputs/jump_table_footprint_reduction.s -o %t.o -RUN: link_fdata %S/Inputs/jump_table_footprint_reduction.s %t.o %t.fdata +RUN: link_fdata %S/Inputs/jump_table_footprint_reduction.s %t.o %t.fdata --nmtool llvm-nm RUN: llvm-strip --strip-unneeded %t.o RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -RUN: llvm-bolt %t.exe -data %t.fdata -o /dev/null \ -RUN: -jump-tables=move -jt-footprint-reduction -assume-abi -relocs \ +RUN: llvm-bolt %t.exe --data %t.fdata -o /dev/null \ +RUN: --jump-tables=move --jt-footprint-reduction --assume-abi --relocs \ RUN: | FileCheck %s CHECK: 100.00% of dynamic JT entries were reduced. diff --git a/bolt/test/X86/jump-table-icp.test b/bolt/test/X86/jump-table-icp.test index 22e228f38e40e..0deeba459cda9 100644 --- a/bolt/test/X86/jump-table-icp.test +++ b/bolt/test/X86/jump-table-icp.test @@ -1,17 +1,17 @@ RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \ RUN: %p/Inputs/jump_table_icp.s -o %t.o -RUN: link_fdata %p/Inputs/jump_table_icp.s %t.o %t.fdata +RUN: link_fdata %p/Inputs/jump_table_icp.s %t.o %t.fdata --nmtool llvm-nm RUN: llvm-strip --strip-unneeded %t.o RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -RUN: (llvm-bolt %t.exe -data %t.fdata -o %t -relocs \ -RUN: -reorder-blocks=cache -split-functions=3 -split-all-cold \ -RUN: -use-gnu-stack -dyno-stats -indirect-call-promotion=jump-tables \ -RUN: -print-icp -v=0 \ -RUN: -icp-jt-remaining-percent-threshold=10 \ -RUN: -icp-jt-total-percent-threshold=2 \ -RUN: -indirect-call-promotion-topn=1 \ -RUN: -icp-jump-tables-targets -align-functions-max-bytes=7 2>&1 && \ +RUN: (llvm-bolt %t.exe --data %t.fdata -o %t --relocs \ +RUN: --reorder-blocks=cache --split-functions=3 --split-all-cold \ +RUN: --use-gnu-stack --dyno-stats --indirect-call-promotion=jump-tables \ +RUN: --print-icp -v=0 \ +RUN: --icp-jt-remaining-percent-threshold=10 \ +RUN: --icp-jt-total-percent-threshold=2 \ +RUN: --indirect-call-promotion-topn=1 \ +RUN: --icp-jump-tables-targets --align-functions-max-bytes=7 2>&1 && \ RUN: llvm-objdump -d %t --print-imm-hex) | FileCheck %s BOLT-INFO: ICP total indirect callsites = 0 diff --git a/bolt/test/X86/jump-table-pic-order.test b/bolt/test/X86/jump-table-pic-order.test index 5edf9bf24744c..0206e831f2441 100644 --- a/bolt/test/X86/jump-table-pic-order.test +++ b/bolt/test/X86/jump-table-pic-order.test @@ -2,7 +2,7 @@ # in the same order as they appear in the input code. RUN: %clang %cflags %S/Inputs/jump-table-pic.s -o %t.exe -Wl,-q -RUN: llvm-bolt %t.exe -strict -print-cfg -print-only=main -o /dev/null \ +RUN: llvm-bolt %t.exe --strict --print-cfg --print-only=main -o /dev/null \ RUN: | FileCheck %s CHECK: BB Layout : {{.*, .*, .*,}} [[BB4to6:.*, .*, .*]] diff --git a/bolt/test/X86/jump-table-reference.test b/bolt/test/X86/jump-table-reference.test index 60ff2f8012928..6a019b26cf63d 100644 --- a/bolt/test/X86/jump-table-reference.test +++ b/bolt/test/X86/jump-table-reference.test @@ -1,6 +1,6 @@ # Verifies that BOLT detects fixed destination of indirect jump RUN: %clang %cflags -no-pie %S/Inputs/jump_table_reference.s -Wl,-q -o %t -RUN: llvm-bolt %t -relocs -o /dev/null 2>&1 | FileCheck %s +RUN: llvm-bolt %t --relocs -o /dev/null 2>&1 | FileCheck %s CHECK: BOLT-INFO: fixed indirect branch detected in main diff --git a/bolt/test/X86/layout-heuristic.test b/bolt/test/X86/layout-heuristic.test index fd2e635dd1ffd..bec0ef01c85f6 100644 --- a/bolt/test/X86/layout-heuristic.test +++ b/bolt/test/X86/layout-heuristic.test @@ -5,9 +5,10 @@ # Also checks that llvm-bolt disassembler and CFG builder is working properly. RUN: yaml2obj %p/Inputs/blarge.yaml &> %t.exe -RUN: llvm-bolt %t.exe -o /dev/null -data %p/Inputs/blarge.fdata \ -RUN: -reorder-blocks=normal -print-cfg -print-reordered \ -RUN: -funcs=main,SolveCubic,usqrt -sequential-disassembly 2>&1 | FileCheck %s +RUN: llvm-bolt %t.exe -o /dev/null --data %p/Inputs/blarge.fdata \ +RUN: --reorder-blocks=normal --print-cfg --print-reordered \ +RUN: --funcs=main,SolveCubic,usqrt --sequential-disassembly \ +RUN: 2>&1 | FileCheck %s # Original order CHECK: Binary Function "main" diff --git a/bolt/test/X86/line-number.test b/bolt/test/X86/line-number.test index dc061ba0bc871..9c9d98df2f1db 100644 --- a/bolt/test/X86/line-number.test +++ b/bolt/test/X86/line-number.test @@ -1,9 +1,9 @@ # Verifies that the extraction of DWARF line number information is correct. RUN: %clangxx %cxxflags %S/Inputs/linenumber.cpp -g -o %t -RUN: llvm-bolt %t -o /dev/null -print-reordered -update-debug-sections \ -RUN: -print-debug-info -reorder-blocks=reverse -sequential-disassembly 2>&1 \ -RUN: | FileCheck %s +RUN: llvm-bolt %t -o /dev/null --print-reordered --update-debug-sections \ +RUN: --print-debug-info --reorder-blocks=reverse --sequential-disassembly \ +RUN: 2>&1 | FileCheck %s # Local variable in f() CHECK: movl $0xbeef, -0x4(%rbp) # debug line {{.*}}linenumber.cpp:9 diff --git a/bolt/test/X86/loop-inversion-pass.s b/bolt/test/X86/loop-inversion-pass.s index d203a3bb5a38d..cb241110cf70d 100644 --- a/bolt/test/X86/loop-inversion-pass.s +++ b/bolt/test/X86/loop-inversion-pass.s @@ -6,12 +6,15 @@ # RUN: link_fdata %s %t.o %t.fdata2 "FDATA2" # RUN: link_fdata %s %t.o %t.fdata3 "FDATA3" # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -data %t.fdata -reorder-blocks=cache+ -print-finalized \ -# RUN: -loop-inversion-opt -o %t.out | FileCheck %s -# RUN: llvm-bolt %t.exe -data %t.fdata2 -reorder-blocks=cache+ -print-finalized \ -# RUN: -loop-inversion-opt -o %t.out2 | FileCheck --check-prefix="CHECK2" %s -# RUN: llvm-bolt %t.exe -data %t.fdata3 -reorder-blocks=none -print-finalized \ -# RUN: -loop-inversion-opt -o %t.out3 | FileCheck --check-prefix="CHECK3" %s +# RUN: llvm-bolt %t.exe --data %t.fdata --reorder-blocks=ext-tsp \ +# RUN: --print-finalized --loop-inversion-opt -o %t.out \ +# RUN: | FileCheck %s +# RUN: llvm-bolt %t.exe --data %t.fdata2 --reorder-blocks=ext-tsp \ +# RUN: --print-finalized --loop-inversion-opt -o %t.out2 \ +# RUN: | FileCheck --check-prefix="CHECK2" %s +# RUN: llvm-bolt %t.exe --data %t.fdata3 --reorder-blocks=none \ +# RUN: --print-finalized --loop-inversion-opt -o %t.out3 \ +# RUN: | FileCheck --check-prefix="CHECK3" %s # The case where the loop is used: # FDATA: 1 main 2 1 main #.J1# 0 420 diff --git a/bolt/test/X86/loop-nest.test b/bolt/test/X86/loop-nest.test index 50284ccc2a39c..24fde1004b007 100644 --- a/bolt/test/X86/loop-nest.test +++ b/bolt/test/X86/loop-nest.test @@ -2,12 +2,13 @@ RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \ RUN: %p/Inputs/loop_nest.s -o %t.o -RUN: link_fdata %p/Inputs/loop_nest.s %t.o %t.fdata +RUN: link_fdata %p/Inputs/loop_nest.s %t.o %t.fdata --nmtool llvm-nm RUN: llvm-strip --strip-unneeded %t.o RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -RUN: llvm-bolt %t.exe -o %t -data=%t.fdata \ -RUN: -print-cfg -print-loops -sequential-disassembly -lite=0 2>&1 | FileCheck %s +RUN: llvm-bolt %t.exe -o %t --data=%t.fdata \ +RUN: --print-cfg --print-loops --sequential-disassembly --lite=0 \ +RUN: 2>&1 | FileCheck %s CHECK: Binary Function "main{{.*}}" after building cfg CHECK: Loop Info for Function "main{{.*}}" diff --git a/bolt/test/X86/lto-name-match.s b/bolt/test/X86/lto-name-match.s index 0bc5066488fa9..a4dde00321d2f 100644 --- a/bolt/test/X86/lto-name-match.s +++ b/bolt/test/X86/lto-name-match.s @@ -4,7 +4,7 @@ # RUN: link_fdata %s %t.o %t.fdata # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags %t.o -o %t.exe -# RUN: llvm-bolt %t.exe -data %t.fdata -o /dev/null | FileCheck %s +# RUN: llvm-bolt %t.exe --data %t.fdata -o /dev/null | FileCheck %s ## Check that profile is correctly matched by functions with variable suffixes. ## E.g., LTO-generated name foo.llvm.123 should match foo.llvm.*. diff --git a/bolt/test/X86/merge-fdata-bat-mode.test b/bolt/test/X86/merge-fdata-bat-mode.test index 911fe8f4d57a0..ea3e4c3e4afcc 100644 --- a/bolt/test/X86/merge-fdata-bat-mode.test +++ b/bolt/test/X86/merge-fdata-bat-mode.test @@ -1,11 +1,8 @@ # Check merge-fdata tool correctly processes fdata files with header strings # such as the ones produced by BAT mode (boltedcollection) RUN: merge-fdata %S/Inputs/bat_profile_1.fdata \ -RUN: %S/Inputs/bat_profile_2.fdata 2> %t.error \ +RUN: %S/Inputs/bat_profile_2.fdata \ RUN: | FileCheck %s --check-prefix=CHECK-FDATA -RUN: cat %t.error |& FileCheck %s --check-prefix=CHECK-ERROR - -CHECK-ERROR-NOT: Malformed CHECK-FDATA: 1 main 451 1 SolveCubic 0 0 302 diff --git a/bolt/test/X86/merge-fdata-output.test b/bolt/test/X86/merge-fdata-output.test new file mode 100644 index 0000000000000..17050e48a95f9 --- /dev/null +++ b/bolt/test/X86/merge-fdata-output.test @@ -0,0 +1,16 @@ +# Check merge-fdata tool correctly handles `-o` option. +RUN: merge-fdata %S/Inputs/bat_profile_1.fdata \ +RUN: %S/Inputs/bat_profile_2.fdata \ +RUN: | FileCheck %s + +RUN: merge-fdata %S/Inputs/bat_profile_1.fdata \ +RUN: %S/Inputs/bat_profile_2.fdata \ +RUN: -o - \ +RUN: | FileCheck %s + +RUN: merge-fdata %S/Inputs/bat_profile_1.fdata \ +RUN: %S/Inputs/bat_profile_2.fdata \ +RUN: -o %t +RUN: FileCheck %s < %t + +CHECK: 1 main 451 1 SolveCubic 0 0 302 \ No newline at end of file diff --git a/bolt/test/X86/no-entry-reordering.test b/bolt/test/X86/no-entry-reordering.test index d96a31cc80ab3..8f2e2c41a4c34 100644 --- a/bolt/test/X86/no-entry-reordering.test +++ b/bolt/test/X86/no-entry-reordering.test @@ -2,10 +2,10 @@ # entry point even if there is a hot edge from a block to entry point RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %S/Inputs/entry.s -o %t.o -RUN: link_fdata %S/Inputs/entry.s %t.o %t.fdata +RUN: link_fdata %S/Inputs/entry.s %t.o %t.fdata --nmtool llvm-nm RUN: llvm-strip --strip-unneeded %t.o RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib -RUN: llvm-bolt %t.exe -data %t.fdata -o /dev/null -reorder-blocks=normal \ -RUN: -funcs=_start -print-reordered -sequential-disassembly | FileCheck %s +RUN: llvm-bolt %t.exe --data %t.fdata -o /dev/null --reorder-blocks=normal \ +RUN: --funcs=_start --print-reordered --sequential-disassembly | FileCheck %s CHECK: BB Layout : .LBB00, {{.*}} diff --git a/bolt/test/X86/no-output.test b/bolt/test/X86/no-output.test index 1638a3db70de5..523bdf25f5217 100644 --- a/bolt/test/X86/no-output.test +++ b/bolt/test/X86/no-output.test @@ -7,8 +7,8 @@ # RUN: link_fdata %s %t.o %t.fdata # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -print-profile-stats -o /dev/null \ -# RUN: -data %t.fdata | FileCheck %s +# RUN: llvm-bolt %t.exe --print-profile-stats -o /dev/null \ +# RUN: --data %t.fdata | FileCheck %s .text .globl main diff --git a/bolt/test/X86/plt-sec-8-byte.test b/bolt/test/X86/plt-sec-8-byte.test index 409ca35d9bd7e..d32faefe7cbb0 100644 --- a/bolt/test/X86/plt-sec-8-byte.test +++ b/bolt/test/X86/plt-sec-8-byte.test @@ -1,6 +1,6 @@ ## Check correctness of processing .plt.sec with 8-byte entries. # RUN: yaml2obj %p/Inputs/plt-sec-8-byte.yaml &> %t.exe -# RUN: llvm-bolt %t.exe -print-cfg -print-only=main -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --print-cfg --print-only=main -o %t.out | FileCheck %s CHECK: callq printf@PLT CHECK: callq exit@PLT diff --git a/bolt/test/X86/plt-sec.test b/bolt/test/X86/plt-sec.test index f47ac5411bbc1..6bff5f35138c0 100644 --- a/bolt/test/X86/plt-sec.test +++ b/bolt/test/X86/plt-sec.test @@ -1,11 +1,11 @@ ## Check that llvm-bolt correctly identifies functions in .plt.sec # RUN: yaml2obj %p/Inputs/plt-sec.yaml &> %t.exe -# RUN: llvm-bolt %t.exe -print-cfg -print-only=foo -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --print-cfg --print-only=foo -o %t.out | FileCheck %s ## Check that llvm-bolt correctly identifies functions in .plt.got that has ## endbr instruction at the start of its entries. # RUN: yaml2obj %p/Inputs/plt-got-sec.yaml &> %t.exe -# RUN: llvm-bolt %t.exe -print-cfg -print-only=foo -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --print-cfg --print-only=foo -o %t.out | FileCheck %s ## The only call instruction in function foo() should be a call to PLT. CHECK: callq puts@PLT diff --git a/bolt/test/X86/reader.test b/bolt/test/X86/reader.test index 925f908a09ef0..cc0bfe43511d3 100644 --- a/bolt/test/X86/reader.test +++ b/bolt/test/X86/reader.test @@ -1,7 +1,7 @@ # This script checks that DataReader in llvm-bolt is reading data correctly RUN: yaml2obj %p/Inputs/blarge.yaml &> %t.exe -RUN: llvm-bolt %t.exe -o /dev/null -data %p/Inputs/blarge.fdata --dump-data \ +RUN: llvm-bolt %t.exe -o /dev/null --data %p/Inputs/blarge.fdata --dump-data \ RUN: 2>&1 | sort | FileCheck %s -check-prefix=CHECK CHECK: main 1105 SolveCubic 0 0 151 diff --git a/bolt/test/X86/relaxed-tailcall.test b/bolt/test/X86/relaxed-tailcall.test index 00d4b178705a6..d303c4255ae7e 100644 --- a/bolt/test/X86/relaxed-tailcall.test +++ b/bolt/test/X86/relaxed-tailcall.test @@ -3,7 +3,7 @@ RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-unknown -o %t.o \ RUN: %S/Inputs/relaxed_tc.s RUN: ld.lld %t.o -o %t.exe -q -RUN: llvm-bolt %t.exe -relocs -o %t +RUN: llvm-bolt %t.exe --relocs -o %t RUN: llvm-objdump -d --disassemble-symbols=foo %t | FileCheck %s CHECK: eb 00 jmp {{.*}} diff --git a/bolt/test/X86/remove-unused.test b/bolt/test/X86/remove-unused.test index e7a4cd0efb3d9..45e9f428e91d6 100644 --- a/bolt/test/X86/remove-unused.test +++ b/bolt/test/X86/remove-unused.test @@ -2,12 +2,12 @@ # the BB reordering ignores dead BBs. RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %S/Inputs/entry.s -o %t.o -RUN: link_fdata %S/Inputs/entry.s %t.o %t.fdata +RUN: link_fdata %S/Inputs/entry.s %t.o %t.fdata --nmtool llvm-nm RUN: llvm-strip --strip-unneeded %t.o RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib -RUN: llvm-bolt %t.exe -data %t.fdata -o %t -funcs=_start \ -RUN: -eliminate-unreachable -reorder-blocks=none \ -RUN: -print-finalized -sequential-disassembly 2>&1 | FileCheck %s +RUN: llvm-bolt %t.exe --data %t.fdata -o %t --funcs=_start \ +RUN: --eliminate-unreachable --reorder-blocks=none \ +RUN: --print-finalized --sequential-disassembly 2>&1 | FileCheck %s # Optimized CHECK: BB Layout : .LBB00, .Ltmp0, .Ltmp2, .Ltmp3, .Ltmp4, .Ltmp5, .Ltmp6, .Ltmp7, .Ltmp8, .Ltmp9, .Ltmp10, .Ltmp11 diff --git a/bolt/test/X86/rodata-simpl-loads.test b/bolt/test/X86/rodata-simpl-loads.test index 82d499c41f6db..8018ad75e5d69 100644 --- a/bolt/test/X86/rodata-simpl-loads.test +++ b/bolt/test/X86/rodata-simpl-loads.test @@ -1,7 +1,7 @@ # Check for the simplification of .rodata loads. RUN: %clang %cflags %p/Inputs/rodata_simpl_loads.s -o %t.exe -RUN: llvm-bolt %t.exe -o %t -simplify-rodata-loads +RUN: llvm-bolt %t.exe -o %t --simplify-rodata-loads RUN: FileCheck %s --check-prefix=ORIGINAL --input-file %p/Inputs/rodata_simpl_loads.s RUN: llvm-objdump -d %t --print-imm-hex --disassemble-symbols=main | FileCheck %s diff --git a/bolt/test/X86/sctc-bug.test b/bolt/test/X86/sctc-bug.test index 687b8cae8d810..a4568aca14144 100644 --- a/bolt/test/X86/sctc-bug.test +++ b/bolt/test/X86/sctc-bug.test @@ -1,7 +1,8 @@ # Check that we don't accidentally optimize out a tail call. RUN: %clang %cflags %S/Inputs/sctc_bug.s -o %t -RUN: llvm-bolt %t -o /dev/null -funcs=main -print-after-lowering 2>&1 | FileCheck %s +RUN: llvm-bolt %t -o /dev/null --funcs=main --print-after-lowering \ +RUN: 2>&1 | FileCheck %s CHECK: jp .L{{.*}} CHECK: je foo # TAILCALL diff --git a/bolt/test/X86/sctc-bug2.test b/bolt/test/X86/sctc-bug2.test index 9bf412d73130f..cf23b38249ace 100644 --- a/bolt/test/X86/sctc-bug2.test +++ b/bolt/test/X86/sctc-bug2.test @@ -1,8 +1,8 @@ # Check that conditional tail call is not treated as a regular tail call by SCTC. RUN: %clang %cflags %S/Inputs/sctc_bug2.s -o %t -RUN: llvm-bolt %t -o /dev/null -funcs=main -print-after-lowering \ -RUN: -sequential-disassembly 2>&1 | FileCheck %s +RUN: llvm-bolt %t -o /dev/null --funcs=main --print-after-lowering \ +RUN: --sequential-disassembly 2>&1 | FileCheck %s CHECK: .LFT1 CHECK: ja .Ltmp0 diff --git a/bolt/test/X86/sctc-bug3.test b/bolt/test/X86/sctc-bug3.test index 48cc4e077f7bd..fce69bf86a466 100644 --- a/bolt/test/X86/sctc-bug3.test +++ b/bolt/test/X86/sctc-bug3.test @@ -1,8 +1,8 @@ # Check that we don't accidentally optimize out a tail call. RUN: %clang %cflags %S/Inputs/sctc_bug3.s -o %t -RUN: llvm-bolt %t -o /dev/null -funcs=main -print-after-lowering \ -RUN: -sequential-disassembly 2>&1 | FileCheck %s +RUN: llvm-bolt %t -o /dev/null --funcs=main --print-after-lowering \ +RUN: --sequential-disassembly 2>&1 | FileCheck %s CHECK: .LBB00 (1 instructions, align : 1) CHECK: cmpq %rdi, 0x0 diff --git a/bolt/test/X86/shared-abbrev.s b/bolt/test/X86/shared-abbrev.s index 0975a005a400e..7559604213639 100644 --- a/bolt/test/X86/shared-abbrev.s +++ b/bolt/test/X86/shared-abbrev.s @@ -2,7 +2,7 @@ # RUN: mkdir %t # RUN: llvm-mc -filetype=obj -triple=x86_64 -dwarf-version=4 %s -o %t/shared-abbrev.o # RUN: %clang %cflags %t/shared-abbrev.o -o %t/shared-abbrev.exe -# RUN: llvm-bolt %t/shared-abbrev.exe -o %t/shared-abbrev.exe.bolt -update-debug-sections +# RUN: llvm-bolt %t/shared-abbrev.exe -o %t/shared-abbrev.exe.bolt --update-debug-sections # RUN: llvm-dwarfdump --debug-info %t/shared-abbrev.exe.bolt | FileCheck %s # CHECK: 0x00000000: diff --git a/bolt/test/X86/shrinkwrapping-and-rsp.s b/bolt/test/X86/shrinkwrapping-and-rsp.s index 2228c6037e9c5..2e5918e857e62 100644 --- a/bolt/test/X86/shrinkwrapping-and-rsp.s +++ b/bolt/test/X86/shrinkwrapping-and-rsp.s @@ -8,9 +8,9 @@ # RUN: link_fdata %s %t.o %t.fdata # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib -# RUN: llvm-bolt %t.exe -o %t.out -data %t.fdata \ -# RUN: -frame-opt=all -simplify-conditional-tail-calls=false \ -# RUN: -eliminate-unreachable=false | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t.out --data %t.fdata \ +# RUN: --frame-opt=all --simplify-conditional-tail-calls=false \ +# RUN: --eliminate-unreachable=false | FileCheck %s # Here we have a function that aligns the stack at prologue. Stack pointer # analysis can't try to infer offset positions after AND because that depends diff --git a/bolt/test/X86/shrinkwrapping-critedge.s b/bolt/test/X86/shrinkwrapping-critedge.s index fb00ffa658f37..ed9a206dec41f 100644 --- a/bolt/test/X86/shrinkwrapping-critedge.s +++ b/bolt/test/X86/shrinkwrapping-critedge.s @@ -8,9 +8,9 @@ # RUN: link_fdata %s %t.o %t.fdata # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -nostdlib -# RUN: llvm-bolt %t.exe -relocs -o %t.out -data %t.fdata \ -# RUN: -frame-opt=all -simplify-conditional-tail-calls=false \ -# RUN: -eliminate-unreachable=false +# RUN: llvm-bolt %t.exe --relocs -o %t.out --data %t.fdata \ +# RUN: --frame-opt=all --simplify-conditional-tail-calls=false \ +# RUN: --eliminate-unreachable=false .globl _start _start: diff --git a/bolt/test/X86/shrinkwrapping-insertcfi.s b/bolt/test/X86/shrinkwrapping-insertcfi.s index 2acc5a23a5ef3..57b43cf4b6623 100644 --- a/bolt/test/X86/shrinkwrapping-insertcfi.s +++ b/bolt/test/X86/shrinkwrapping-insertcfi.s @@ -7,8 +7,8 @@ # RUN: link_fdata %s %t.o %t.fdata # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib -# RUN: llvm-bolt %t.exe -o %t.out -data %t.fdata -frame-opt=all -lite=0 \ -# RUN: -print-fop 2>&1 | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t.out --data %t.fdata --frame-opt=all --lite=0 \ +# RUN: --print-fop 2>&1 | FileCheck %s # Check shrink wrapping results: # CHECK: BOLT-INFO: Shrink wrapping moved 0 spills inserting load/stores and 1 spills inserting push/pops diff --git a/bolt/test/X86/shrinkwrapping-pop-order.s b/bolt/test/X86/shrinkwrapping-pop-order.s index f2453ebde2e2a..5045ba20bac78 100644 --- a/bolt/test/X86/shrinkwrapping-pop-order.s +++ b/bolt/test/X86/shrinkwrapping-pop-order.s @@ -8,8 +8,8 @@ # RUN: link_fdata %s %t.o %t.fdata # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib -# RUN: llvm-bolt %t.exe -o %t.out -data %t.fdata -frame-opt=all -lite=0 \ -# RUN: -print-fop 2>&1 | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t.out --data %t.fdata --frame-opt=all --lite=0 \ +# RUN: --print-fop 2>&1 | FileCheck %s .globl _start _start: diff --git a/bolt/test/X86/shrinkwrapping-popf.s b/bolt/test/X86/shrinkwrapping-popf.s index bf0c8a189f5f3..975702df0179c 100644 --- a/bolt/test/X86/shrinkwrapping-popf.s +++ b/bolt/test/X86/shrinkwrapping-popf.s @@ -6,7 +6,7 @@ # RUN: link_fdata %s %t.o %t.fdata # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib -# RUN: llvm-bolt %t.exe -o %t.out -data %t.fdata -frame-opt=all -lite=0 +# RUN: llvm-bolt %t.exe -o %t.out --data %t.fdata --frame-opt=all --lite=0 .globl _start diff --git a/bolt/test/X86/shrinkwrapping.test b/bolt/test/X86/shrinkwrapping.test index 33802d53ac4b1..594a87ed78446 100644 --- a/bolt/test/X86/shrinkwrapping.test +++ b/bolt/test/X86/shrinkwrapping.test @@ -3,8 +3,8 @@ # frame pointers. RUN: %clangxx %cxxflags -no-pie %S/Inputs/exc4sw.S -o %t.exe -Wl,-q -RUN: llvm-bolt %t.exe -o %t -relocs -frame-opt=all \ -RUN: -data=%p/Inputs/exc4sw.fdata -reorder-blocks=cache 2>&1 | \ +RUN: llvm-bolt %t.exe -o %t --relocs --frame-opt=all \ +RUN: --data=%p/Inputs/exc4sw.fdata --reorder-blocks=cache 2>&1 | \ RUN: FileCheck %s --check-prefix=CHECK-BOLT RUN: llvm-objdump --dwarf=frames %t.exe | grep -A20 -e \ diff --git a/bolt/test/X86/split-func-icf.s b/bolt/test/X86/split-func-icf.s index 00fe62860d466..eac4174fefd5b 100644 --- a/bolt/test/X86/split-func-icf.s +++ b/bolt/test/X86/split-func-icf.s @@ -8,15 +8,17 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.out -lite=0 -v=1 2>&1 | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t.out -v=1 --print-only=main2.cold.1 --print-disasm 2>&1 | FileCheck %s # CHECK-NOT: unclaimed PC-relative relocations left in data # CHECK-DAG: BOLT-INFO: marking main2.cold.1(*2) as a fragment of main # CHECK-DAG: BOLT-INFO: marking main2.cold.1(*2) as a fragment of main2 +# CHECK: Binary Function "main2.cold.1(*2)" after disassembly +# CHECK: End of Function "main2.cold.1(*2)" # CHECK-DAG: BOLT-WARNING: Ignoring main2 # CHECK-DAG: BOLT-WARNING: Ignoring main # CHECK-DAG: BOLT-WARNING: Ignoring main2.cold.1(*2) -# CHECK: BOLT-WARNING: ignored 3 functions due to cold fragments +# CHECK: BOLT-WARNING: skipped 3 functions due to cold fragments .text .globl main .type main, %function diff --git a/bolt/test/X86/split-func-jump-table-fragment-noparent.s b/bolt/test/X86/split-func-jump-table-fragment-noparent.s index 148639e99c81c..a3ac643ee1376 100644 --- a/bolt/test/X86/split-func-jump-table-fragment-noparent.s +++ b/bolt/test/X86/split-func-jump-table-fragment-noparent.s @@ -7,7 +7,7 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.out -lite=0 -v=1 2>&1 | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t.out --lite=0 -v=1 2>&1 | FileCheck %s # CHECK-NOT: unclaimed PC-relative relocations left in data # CHECK: BOLT-INFO: marking main.cold.1 as a fragment of main diff --git a/bolt/test/X86/split-func-jump-table-fragment-reverse.s b/bolt/test/X86/split-func-jump-table-fragment-reverse.s index 4b9b511321702..639c800a795b1 100644 --- a/bolt/test/X86/split-func-jump-table-fragment-reverse.s +++ b/bolt/test/X86/split-func-jump-table-fragment-reverse.s @@ -7,7 +7,7 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.out -lite=0 -v=1 2>&1 | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t.out --lite=0 -v=1 2>&1 | FileCheck %s # CHECK-NOT: unclaimed PC-relative relocations left in data # CHECK: BOLT-INFO: marking main.cold as a fragment of main diff --git a/bolt/test/X86/split-func-jump-table-fragment.s b/bolt/test/X86/split-func-jump-table-fragment.s index 891466dcdcac8..6b6dc227ace1d 100644 --- a/bolt/test/X86/split-func-jump-table-fragment.s +++ b/bolt/test/X86/split-func-jump-table-fragment.s @@ -6,7 +6,7 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.out -lite=0 -v=1 2>&1 | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t.out --lite=0 -v=1 2>&1 | FileCheck %s # CHECK-NOT: unclaimed PC-relative relocations left in data # CHECK: BOLT-INFO: marking main.cold.1 as a fragment of main diff --git a/bolt/test/X86/srol-bug.test b/bolt/test/X86/srol-bug.test index a6abbea4a2f27..10b7a61322611 100644 --- a/bolt/test/X86/srol-bug.test +++ b/bolt/test/X86/srol-bug.test @@ -1,6 +1,6 @@ # RUN: yaml2obj %p/Inputs/srol-bug-input.yaml &> %t.exe -# RUN: llvm-bolt %t.exe -simplify-rodata-loads -print-finalized -relocs=0 \ -# RUN: -print-disasm -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --simplify-rodata-loads --print-finalized --relocs=0 \ +# RUN: --print-disasm -o %t.out | FileCheck %s CHECK: Binary Function "myfunc" after disassembly { CHECK: 00000000: addl mydata(%rip), %edx diff --git a/bolt/test/X86/symtab-secondary-entries.test b/bolt/test/X86/symtab-secondary-entries.test index 4e4ea85eb1566..6e05129340a0f 100644 --- a/bolt/test/X86/symtab-secondary-entries.test +++ b/bolt/test/X86/symtab-secondary-entries.test @@ -3,8 +3,8 @@ RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \ RUN: %p/Inputs/user-order.S -o %t.o RUN: ld.lld %t.o --emit-relocs --nostdlib -o %t.exe -RUN: llvm-bolt %t.exe -o %t -reorder-functions=user \ -RUN: -function-order=%p/Inputs/order.txt +RUN: llvm-bolt %t.exe -o %t --reorder-functions=user \ +RUN: --function-order=%p/Inputs/order.txt RUN: llvm-readelf -Ws %t | cut -d':' -f2- | sort -u | FileCheck %s diff --git a/bolt/test/X86/tail-duplication-cache.s b/bolt/test/X86/tail-duplication-cache.s new file mode 100644 index 0000000000000..d7955eff9ead9 --- /dev/null +++ b/bolt/test/X86/tail-duplication-cache.s @@ -0,0 +1,60 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \ +# RUN: %s -o %t.o +# RUN: link_fdata %s %t.o %t.fdata +# RUN: link_fdata %s %t.o %t.fdata2 "FDATA2" +# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe --data %t.fdata --reorder-blocks=none \ +# RUN: --print-finalized --tail-duplication=cache -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --data %t.fdata2 --reorder-blocks=none \ +# RUN: --print-finalized --tail-duplication=cache -o %t.out2 \ +# RUN: | FileCheck --check-prefix="CHECK2" %s + +# A test where the tail is duplicated to eliminate an uncoditional jump +# FDATA: 1 main #.BB0_br# 1 main #.BB4# 0 100 +# FDATA: 1 main #.BB0_br# 1 main #.BB1# 0 100 +# FDATA: 1 main #.BB1_br# 1 main #.BB3# 0 50 +# FDATA: 1 main #.BB1_br# 1 main #.BB2# 0 50 +# FDATA: 1 main #.BB3_br# 1 main #.BB2# 0 50 +# CHECK: BOLT-INFO: tail duplication modified 1 ({{.*}}%) functions; duplicated 1 blocks (13 bytes) responsible for 50 dynamic executions ({{.*}}% of all block executions) +# CHECK: BB Layout : .LBB00, .Ltmp0, .Ltmp1, .Ltmp2, .Ltmp3, .Ltmp4, .Ltmp5, .Ltail-dup0, .Ltmp6 + +# A test where the tail is not duplicated due to the cache score +# FDATA2: 1 main #.BB0_br# 1 main #.BB4# 0 100 +# FDATA2: 1 main #.BB0_br# 1 main #.BB1# 0 2 +# FDATA2: 1 main #.BB1_br# 1 main #.BB3# 0 1 +# FDATA2: 1 main #.BB1_br# 1 main #.BB2# 0 1 +# FDATA2: 1 main #.BB3_br# 1 main #.BB2# 0 1 +# CHECK2: BOLT-INFO: tail duplication modified 0 (0.00%) functions; duplicated 0 blocks (0 bytes) responsible for 0 dynamic executions (0.00% of all block executions) +# CHECK2: BB Layout : .LBB00, .Ltmp0, .Ltmp1, .Ltmp2, .Ltmp3, .Ltmp4, .Ltmp5, .Ltmp6 + + .text + .globl main + .type main, %function + .size main, .Lend-main +main: +.BB0: + xor %eax, %eax + cmpl %eax, %ebx +.BB0_br: + je .BB4 +.BB1: + inc %rax +.BB1_br: + je .BB3 +.BB2: + inc %rax + inc %rax + inc %rax + inc %rax + retq +.BB3: + inc %rax +.BB3_br: + jmp .BB2 +.BB4: + retq +# For relocations against .text + call exit +.Lend: diff --git a/bolt/test/X86/tail-duplication-cacheline.s b/bolt/test/X86/tail-duplication-cacheline.s index 7cc0d9c5636d4..acc49dc348340 100644 --- a/bolt/test/X86/tail-duplication-cacheline.s +++ b/bolt/test/X86/tail-duplication-cacheline.s @@ -8,8 +8,8 @@ # RUN: link_fdata %s %t.o %t.fdata # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -nostdlib -# RUN: llvm-bolt %t.exe -o %t.out -data %t.fdata -relocs \ -# RUN: -tail-duplication=1 -tail-duplication-aggressive=1 +# RUN: llvm-bolt %t.exe -o %t.out --data %t.fdata --relocs \ +# RUN: --tail-duplication=aggressive .globl _start _start: jmp d diff --git a/bolt/test/X86/tail-duplication-complex.s b/bolt/test/X86/tail-duplication-complex.s index a86233088386b..ced59aea7a4c4 100644 --- a/bolt/test/X86/tail-duplication-complex.s +++ b/bolt/test/X86/tail-duplication-complex.s @@ -5,15 +5,16 @@ # RUN: link_fdata %s %t.o %t.fdata # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -data %t.fdata -print-finalized \ -# RUN: -tail-duplication -tail-duplication-minimum-offset 1 -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --data %t.fdata --print-finalized \ +# RUN: --tail-duplication=moderate --tail-duplication-minimum-offset=1 \ +# RUN: -o %t.out | FileCheck %s # FDATA: 1 main f 1 main 19 0 10 # FDATA: 1 main f 1 main 11 0 13 # FDATA: 1 main 17 1 main 3c 0 10 # FDATA: 1 main 39 1 main 3c 0 10 -# CHECK: tail duplication possible duplications: 1 +# CHECK: tail duplication modified 1 ({{.*}}%) functions; duplicated 1 blocks ({{.*}} bytes) responsible for {{.*}} dynamic executions ({{.*}} of all block executions) # CHECK: BB Layout : .LBB00, .Ltmp0, .Ltail-dup0, .Ltmp1, .Ltmp2 # This is the C++ code fed to Clang diff --git a/bolt/test/X86/tail-duplication-jt.s b/bolt/test/X86/tail-duplication-jt.s index 9a6382ec6fe67..03211b399ba67 100644 --- a/bolt/test/X86/tail-duplication-jt.s +++ b/bolt/test/X86/tail-duplication-jt.s @@ -7,10 +7,10 @@ # RUN: %s -o %t.o # RUN: link_fdata %s %t.o %t.fdata # RUN: llvm-strip --strip-unneeded %t.o -# RUN: %clangxx %cflags -no-pie %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.out -data %t.fdata -relocs \ -# RUN: -tail-duplication=1 -tail-duplication-aggressive=1 \ -# RUN: -print-cfg | FileCheck %s +# RUN: %clangxx %cflags -no-pie %t.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.out --data %t.fdata --relocs \ +# RUN: --tail-duplication=aggressive \ +# RUN: --print-cfg | FileCheck %s # CHECK: Jump table {{.*}} for function a at {{.*}} with a total count of 3 .globl main main: diff --git a/bolt/test/X86/tail-duplication-pass.s b/bolt/test/X86/tail-duplication-pass.s index 81c4515a9d1e9..677f4986eb890 100644 --- a/bolt/test/X86/tail-duplication-pass.s +++ b/bolt/test/X86/tail-duplication-pass.s @@ -4,12 +4,13 @@ # RUN: %s -o %t.o # RUN: link_fdata %s %t.o %t.fdata # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -data %t.fdata -reorder-blocks=cache+ -print-finalized \ -# RUN: -tail-duplication -tail-duplication-minimum-offset 1 -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --data %t.fdata --reorder-blocks=ext-tsp \ +# RUN: --print-finalized --tail-duplication=moderate \ +# RUN: --tail-duplication-minimum-offset=1 -o %t.out | FileCheck %s # FDATA: 1 main 2 1 main #.BB2# 0 10 # FDATA: 1 main 4 1 main #.BB2# 0 20 -# CHECK: tail duplication possible duplications: 1 +# CHECK: BOLT-INFO: tail duplication modified 1 ({{.*}}%) functions; duplicated 1 blocks (1 bytes) responsible for {{.*}} dynamic executions ({{.*}}% of all block executions) # CHECK: BB Layout : .LBB00, .Ltail-dup0, .Ltmp0, .Ltmp1 .text diff --git a/bolt/test/X86/tail-duplication-prop-bug.s b/bolt/test/X86/tail-duplication-prop-bug.s index b91e85ddd27a3..5e9efc87fa2f2 100644 --- a/bolt/test/X86/tail-duplication-prop-bug.s +++ b/bolt/test/X86/tail-duplication-prop-bug.s @@ -5,9 +5,9 @@ # RUN: link_fdata %s %t.o %t.fdata # RUN: llvm-strip --strip-unneeded %t.o # RUN: ld.lld %t.o -o %t.exe -q -nostdlib -# RUN: llvm-bolt %t.exe -o %t.out -data %t.fdata -relocs \ -# RUN: -tail-duplication=1 -tail-duplication-aggressive=1 \ -# RUN: -tail-duplication-const-copy-propagation=1 +# RUN: llvm-bolt %t.exe -o %t.out --data %t.fdata --relocs \ +# RUN: --tail-duplication=aggressive \ +# RUN: --tail-duplication-const-copy-propagation=1 .text .type a, %function diff --git a/bolt/test/X86/tailcall-traps.test b/bolt/test/X86/tailcall-traps.test index 5f075cf204778..7ce6d61a738b5 100644 --- a/bolt/test/X86/tailcall-traps.test +++ b/bolt/test/X86/tailcall-traps.test @@ -1,8 +1,8 @@ # Tests the peephole that adds trap instructions following indirect tail calls. RUN: %clang %cflags %p/Inputs/tailcall_traps.s -o %t.exe -RUN: llvm-bolt %t.exe -o %t -peepholes=tailcall-traps \ -RUN: -print-peepholes -funcs=foo,bar 2>&1 | FileCheck %s +RUN: llvm-bolt %t.exe -o %t --peepholes=tailcall-traps \ +RUN: --print-peepholes --funcs=foo,bar 2>&1 | FileCheck %s CHECK: Binary Function "foo" CHECK: jmpl *%rax # TAILCALL diff --git a/bolt/test/X86/tailcall.test b/bolt/test/X86/tailcall.test index 4f2fbb0897057..09a31a6016078 100644 --- a/bolt/test/X86/tailcall.test +++ b/bolt/test/X86/tailcall.test @@ -2,7 +2,7 @@ # in control flow graph. RUN: %clang %cflags %S/Inputs/tailcall.s -o %t.exe -RUN: llvm-bolt %t.exe -o /dev/null -print-cfg 2>&1 | FileCheck %s +RUN: llvm-bolt %t.exe -o /dev/null --print-cfg 2>&1 | FileCheck %s CHECK: Binary Function "foo" CHECK: jmp bar # TAILCALL diff --git a/bolt/test/X86/vararg.test b/bolt/test/X86/vararg.test index 0530d670b425c..bfbc23efb9dcd 100644 --- a/bolt/test/X86/vararg.test +++ b/bolt/test/X86/vararg.test @@ -5,7 +5,7 @@ REQUIRES: x86_64-linux RUN: %clangxx %cxxflags -no-pie %p/../Inputs/vararg.s -o %t -Wl,-q -RUN: llvm-bolt %t -o /dev/null -print-cfg -print-only=.*printf.* |& FileCheck %s +RUN: llvm-bolt %t -o /dev/null --print-cfg --print-only=.*printf.* |& FileCheck %s CHECK: IsSimple : 0 CHECK: Entry Point diff --git a/bolt/test/X86/zero-sized-object.s b/bolt/test/X86/zero-sized-object.s index f942747144719..1f3522bce213c 100755 --- a/bolt/test/X86/zero-sized-object.s +++ b/bolt/test/X86/zero-sized-object.s @@ -7,8 +7,8 @@ # RUN: %s -o %t.o # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -print-cfg \ -# RUN: -print-only=main -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --print-cfg \ +# RUN: --print-only=main -o %t.out | FileCheck %s .file "rust_bug.c" .section .rodata diff --git a/bolt/test/bolt-icf.test b/bolt/test/bolt-icf.test index ebbe28b6d6808..f7b056e2ddb0e 100644 --- a/bolt/test/bolt-icf.test +++ b/bolt/test/bolt-icf.test @@ -3,7 +3,7 @@ REQUIRES: system-linux RUN: %clangxx %p/Inputs/bolt_icf.cpp -g -Wl,-q -o %t.exe -RUN: llvm-bolt %t.exe -relocs -o %t -icf 2>&1 | FileCheck %s +RUN: llvm-bolt %t.exe --relocs -o %t --icf 2>&1 | FileCheck %s RUN: llvm-nm -n %t | FileCheck %s -check-prefix=CHECK-SYM CHECK: BOLT-INFO: ICF folded [[#]] out of [[#]] functions in [[#]] passes. diff --git a/bolt/test/cache+-deprecated.test b/bolt/test/cache+-deprecated.test new file mode 100644 index 0000000000000..c320ea8816e75 --- /dev/null +++ b/bolt/test/cache+-deprecated.test @@ -0,0 +1,8 @@ + + +REQUIRES: system-linux + +RUN: %clangxx %p/Inputs/bolt_icf.cpp -g -Wl,-q -o %t.exe +RUN: llvm-bolt %t.exe --reorder-blocks=cache+ --relocs -o %t 2>&1 | FileCheck %s + +CHECK: '-reorder-blocks=cache+' is deprecated, please use '-reorder-blocks=ext-tsp' instead diff --git a/bolt/test/invalid-profile.test b/bolt/test/invalid-profile.test index d26a3f5de4c51..dfb4fb0e427f4 100644 --- a/bolt/test/invalid-profile.test +++ b/bolt/test/invalid-profile.test @@ -1,6 +1,6 @@ # Check that llvm-bolt detects bad profile data and aborts RUN: %clang %S/Inputs/icf-jump-tables.c -o %t -RUN: not llvm-bolt %t -o %t.bolt -data %t 2>&1 | FileCheck %s +RUN: not llvm-bolt %t -o %t.bolt --data %t 2>&1 | FileCheck %s CHECK: no valid profile data found diff --git a/bolt/test/keep-aranges.test b/bolt/test/keep-aranges.test index ada08b54f0105..5a9d932bc1af2 100644 --- a/bolt/test/keep-aranges.test +++ b/bolt/test/keep-aranges.test @@ -5,7 +5,7 @@ REQUIRES: system-linux RUN: %clang %cflags %S/Inputs/icf_baz.c %S/Inputs/icf_main.c -Wl,--icf=all,--gdb-index \ RUN: -g -o %t.exe -fuse-ld=lld -RUN: llvm-bolt %t.exe -o %t -update-debug-sections -keep-aranges +RUN: llvm-bolt %t.exe -o %t --update-debug-sections --keep-aranges RUN: llvm-dwarfdump -debug-aranges %t | FileCheck %s CHECK: Address Range Header: length = {{.*}}, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00 diff --git a/bolt/test/link_fdata.py b/bolt/test/link_fdata.py index 35fa5ea0c5035..e54125f4f51b5 100755 --- a/bolt/test/link_fdata.py +++ b/bolt/test/link_fdata.py @@ -98,7 +98,7 @@ def replace_symbol(matchobj): assert symname in symbols, f"ERROR: symbol {symname} is not defined in binary" return symbols[symname] -with open(args.output, 'w') as f: +with open(args.output, 'w', newline='\n') as f: for etype, expr in exprs: if etype == 'FDATA': issym1, anchor1, offsym1, issym2, anchor2, offsym2, execnt, mispred = expr diff --git a/bolt/test/lit.cfg.py b/bolt/test/lit.cfg.py index 78077921fcd6a..526458e9a74d9 100644 --- a/bolt/test/lit.cfg.py +++ b/bolt/test/lit.cfg.py @@ -88,9 +88,10 @@ ToolSubst('llvm-objcopy', unresolved='fatal'), ToolSubst('llvm-strip', unresolved='fatal'), ToolSubst('llvm-readelf', unresolved='fatal'), - ToolSubst('link_fdata', command=link_fdata_cmd, unresolved='fatal'), + ToolSubst('link_fdata', command=sys.executable, unresolved='fatal', extra_args=[link_fdata_cmd]), ToolSubst('merge-fdata', unresolved='fatal'), ToolSubst('llvm-readobj', unresolved='fatal'), + ToolSubst('llvm-dwp', unresolved='fatal'), ] llvm_config.add_tool_substitutions(tools, tool_dirs) diff --git a/bolt/test/no-relocs.test b/bolt/test/no-relocs.test index ff2af84e470c3..97168cb17b4e2 100644 --- a/bolt/test/no-relocs.test +++ b/bolt/test/no-relocs.test @@ -1,6 +1,6 @@ # Verifies that input without relocations is rejected in relocs mode. RUN: %clang %cflags %S/Inputs/icf-jump-tables.c -o %t -RUN: not llvm-bolt %t -o /dev/null -relocs 2>&1 | FileCheck %s +RUN: not llvm-bolt %t -o /dev/null --relocs 2>&1 | FileCheck %s CHECK: BOLT-ERROR: relocations against code are missing from the input file. diff --git a/bolt/test/non-empty-debug-line.test b/bolt/test/non-empty-debug-line.test index 50c215ab91d19..e3de8335238d9 100644 --- a/bolt/test/non-empty-debug-line.test +++ b/bolt/test/non-empty-debug-line.test @@ -4,7 +4,7 @@ REQUIRES: system-linux RUN: %clang %cflags %S/Inputs/hello.c -g -o %t -RUN: llvm-bolt %t -o %t1 -update-debug-sections -funcs=_start +RUN: llvm-bolt %t -o %t1 --update-debug-sections --funcs=_start RUN: llvm-readobj -S %t > %t2 RUN: llvm-readobj -S %t1 >> %t2 RUN: FileCheck %s --input-file %t2 diff --git a/bolt/test/runtime/AArch64/adrrelaxationpass.s b/bolt/test/runtime/AArch64/adrrelaxationpass.s index 1abb3ee19b734..b8790d50f7b56 100644 --- a/bolt/test/runtime/AArch64/adrrelaxationpass.s +++ b/bolt/test/runtime/AArch64/adrrelaxationpass.s @@ -6,7 +6,7 @@ # RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \ # RUN: %s -o %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -adr-relaxation=true +# RUN: llvm-bolt %t.exe -o %t.bolt --adr-relaxation=true # RUN: llvm-objdump -d --disassemble-symbols=main %t.bolt | FileCheck %s # RUN: %t.bolt diff --git a/bolt/test/runtime/AArch64/constant-island-relocations.s b/bolt/test/runtime/AArch64/constant-island-relocations.s index 82bd4f206d2c8..a2c4123126b5f 100644 --- a/bolt/test/runtime/AArch64/constant-island-relocations.s +++ b/bolt/test/runtime/AArch64/constant-island-relocations.s @@ -6,7 +6,7 @@ # RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \ # RUN: %s -o %t.o # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -use-old-text=0 -lite=0 -trap-old-code +# RUN: llvm-bolt %t.exe -o %t.bolt --use-old-text=0 --lite=0 --trap-old-code # RUN: %t.bolt .text diff --git a/bolt/test/runtime/AArch64/controlflow.s b/bolt/test/runtime/AArch64/controlflow.s index fd66e443c6055..fe9aab88f0c74 100644 --- a/bolt/test/runtime/AArch64/controlflow.s +++ b/bolt/test/runtime/AArch64/controlflow.s @@ -5,7 +5,7 @@ # RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \ # RUN: %s -o %t.o # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -use-old-text=0 -lite=0 -trap-old-code +# RUN: llvm-bolt %t.exe -o %t.bolt --use-old-text=0 --lite=0 --trap-old-code # RUN: %t.bolt .macro panic diff --git a/bolt/test/runtime/AArch64/issue177.s b/bolt/test/runtime/AArch64/issue177.s index 1fddaf7806b93..3ed8d7cbf50c4 100644 --- a/bolt/test/runtime/AArch64/issue177.s +++ b/bolt/test/runtime/AArch64/issue177.s @@ -4,7 +4,7 @@ # REQUIRES: system-linux # RUN: %clang %cflags -no-pie %s -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.bolt -use-old-text=0 -lite=0 -trap-old-code +# RUN: llvm-bolt %t.exe -o %t.bolt --use-old-text=0 --lite=0 --trap-old-code # RUN: %t.bolt .text diff --git a/bolt/test/runtime/X86/basic-instrumentation.test b/bolt/test/runtime/X86/basic-instrumentation.test index cb99868b1e439..c64dc279df7e6 100644 --- a/bolt/test/runtime/X86/basic-instrumentation.test +++ b/bolt/test/runtime/X86/basic-instrumentation.test @@ -3,9 +3,9 @@ REQUIRES: system-linux RUN: %clang %p/Inputs/basic-instrumentation.s -Wl,-q -o %t.exe -RUN: llvm-bolt %t.exe -o %t -instrument \ -RUN: -instrumentation-file=%t \ -RUN: -instrumentation-file-append-pid +RUN: llvm-bolt %t.exe -o %t --instrument \ +RUN: --instrumentation-file=%t \ +RUN: --instrumentation-file-append-pid # Execute program to collect profile RUN: rm %t.*.fdata || echo Nothing to remove @@ -16,7 +16,7 @@ RUN: mv %t.*.fdata %t.fdata RUN: cat %t.fdata | FileCheck -check-prefix=CHECK %s # Check BOLT works with this profile -RUN: llvm-bolt %t.exe -data %t.fdata -o %t.2 -reorder-blocks=cache +RUN: llvm-bolt %t.exe --data %t.fdata -o %t.2 --reorder-blocks=cache # The instrumented profile should at least say main was called once CHECK: main 0 0 1{{$}} diff --git a/bolt/test/runtime/X86/exceptions-instrumentation.test b/bolt/test/runtime/X86/exceptions-instrumentation.test index 77021927eddab..db26bdefc54c3 100644 --- a/bolt/test/runtime/X86/exceptions-instrumentation.test +++ b/bolt/test/runtime/X86/exceptions-instrumentation.test @@ -3,13 +3,14 @@ REQUIRES: system-linux RUN: %clangxx %cxxflags -no-pie %p/Inputs/exceptions_split.cpp -Wl,-q -g -o %t_exc_split -RUN: llvm-bolt %t_exc_split -o %t.exc -instrument -instrumentation-file=%t.fdata +RUN: llvm-bolt %t_exc_split -o %t.exc --instrument --instrumentation-file=%t.fdata RUN: %t.exc arg1 arg2 arg3 -RUN: llvm-bolt %t_exc_split -o %t.exc.bolted -data %t.fdata \ -RUN: -reorder-blocks=cache+ -reorder-functions=hfsort+ -split-functions=3 \ -RUN: -split-eh=1 | FileCheck --check-prefix=EXCEPTIONS %s +RUN: llvm-bolt %t_exc_split -o %t.exc.bolted --data %t.fdata \ +RUN: --reorder-blocks=ext-tsp --reorder-functions=hfsort+ \ +RUN: --split-functions=3 --split-eh=1 \ +RUN: | FileCheck --check-prefix=EXCEPTIONS %s EXCEPTIONS-NOT: invalid (possibly stale) profile # Check that cold symbols are emitted with local binding. diff --git a/bolt/test/runtime/X86/exceptions-pic.test b/bolt/test/runtime/X86/exceptions-pic.test index 9a1b050cbea09..e65f86050fee6 100644 --- a/bolt/test/runtime/X86/exceptions-pic.test +++ b/bolt/test/runtime/X86/exceptions-pic.test @@ -4,7 +4,7 @@ REQUIRES: x86_64-linux RUN: %clangxx -fpic -Wl,-q %S/Inputs/exception4.cpp -o %t.pic RUN: llvm-bolt %t.pic -o %t && %t 2>&1 | FileCheck %s -RUN: llvm-bolt -relocs -use-old-text %t.pic -o %t && %t 2>&1 | FileCheck %s +RUN: llvm-bolt --relocs --use-old-text %t.pic -o %t && %t 2>&1 | FileCheck %s CHECK: catch 2 CHECK-NEXT: catch 1 diff --git a/bolt/test/runtime/X86/exceptions-run.test b/bolt/test/runtime/X86/exceptions-run.test index 88e0ecccb6e17..45702ef358a09 100644 --- a/bolt/test/runtime/X86/exceptions-run.test +++ b/bolt/test/runtime/X86/exceptions-run.test @@ -4,8 +4,8 @@ REQUIRES: x86_64-linux RUN: %clangxx -g %S/Inputs/exception3.cpp -o %t.exe -RUN: llvm-bolt -align-blocks=0 %t.exe -o %t && %t 2>&1 | FileCheck %s -RUN: llvm-bolt -reorder-blocks=reverse -align-blocks=0 %t.exe -o %t && %t 2>&1 \ +RUN: llvm-bolt --align-blocks=0 %t.exe -o %t && %t 2>&1 | FileCheck %s +RUN: llvm-bolt --reorder-blocks=reverse --align-blocks=0 %t.exe -o %t && %t 2>&1 \ RUN: | FileCheck %s CHECK: catch 2 diff --git a/bolt/test/runtime/X86/fdata-escape-chars.ll b/bolt/test/runtime/X86/fdata-escape-chars.ll index 757a8b6092808..3f0bb12c33baa 100644 --- a/bolt/test/runtime/X86/fdata-escape-chars.ll +++ b/bolt/test/runtime/X86/fdata-escape-chars.ll @@ -56,18 +56,18 @@ define internal void @static_symb_backslash_b() #0 { ; RUN: %clang %cflags -O0 %t.s -o %t.exe -Wl,-q ; RUN: llvm-objcopy --redefine-syms=%p/Inputs/fdata-escape-chars-syms.txt %t.exe ; -; RUN: llvm-bolt %t.exe -o %t.exe.instrumented -instrument \ -; RUN: -instrumentation-file=%t.fdata +; RUN: llvm-bolt %t.exe -o %t.exe.instrumented --instrument \ +; RUN: --instrumentation-file=%t.fdata ; RUN: %t.exe.instrumented ; RUN: cat %t.fdata | \ ; RUN: FileCheck --check-prefix="FDATA_CHECK" %s -; RUN: llvm-bolt %t.exe -o %t.fdata.exe -data %t.fdata -print-finalized | \ +; RUN: llvm-bolt %t.exe -o %t.fdata.exe --data %t.fdata --print-finalized | \ ; RUN: FileCheck --check-prefix="INSTR_CHECK" %s ; ; RUN: link_fdata %p/Inputs/fdata-escape-chars.txt %t.exe %t.pre "PREAGR" ; RUN: perf2bolt %t.exe -o %t.pre.fdata -pa -p %t.pre ; RUN: cat %t.pre.fdata | FileCheck --check-prefix="PREAGR_FDATA_CHECK" %s -; RUN: llvm-bolt %t.exe -o %t.pre.fdata.exe -data %t.pre.fdata -print-finalized | \ +; RUN: llvm-bolt %t.exe -o %t.pre.fdata.exe --data %t.pre.fdata --print-finalized | \ ; RUN: FileCheck --check-prefix="PREAGR_CHECK" %s ; FDATA_CHECK: 1 symb\ backslash\\ {{([[:xdigit:]]+)}} 1 symb\ whitespace 0 0 2 diff --git a/bolt/test/runtime/X86/fix-branches-jrcxz.s b/bolt/test/runtime/X86/fix-branches-jrcxz.s index 47f2b2d9205ce..7ad34c7471b32 100755 --- a/bolt/test/runtime/X86/fix-branches-jrcxz.s +++ b/bolt/test/runtime/X86/fix-branches-jrcxz.s @@ -7,8 +7,8 @@ # RUN: link_fdata %s %t.o %t.fdata # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -relocs=1 -reorder-blocks=cache+ -print-finalized \ -# RUN: -o %t.out -data %t.fdata | FileCheck %s +# RUN: llvm-bolt %t.exe --relocs=1 --reorder-blocks=ext-tsp --print-finalized \ +# RUN: -o %t.out --data %t.fdata | FileCheck %s # RUN: %t.out 1 2 3 # CHECK: BOLT-INFO diff --git a/bolt/test/runtime/X86/hot-end-symbol.s b/bolt/test/runtime/X86/hot-end-symbol.s index f8ac01b3f7b8c..e6d83d77167ac 100755 --- a/bolt/test/runtime/X86/hot-end-symbol.s +++ b/bolt/test/runtime/X86/hot-end-symbol.s @@ -11,8 +11,8 @@ # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -relocs=1 -hot-text -reorder-functions=hfsort \ -# RUN: -data %t.fdata -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --relocs=1 --hot-text --reorder-functions=hfsort \ +# RUN: --data %t.fdata -o %t.out | FileCheck %s # RUN: %t.out 1 diff --git a/bolt/test/runtime/X86/indirect-goto-pie.test b/bolt/test/runtime/X86/indirect-goto-pie.test index 0280f88478dbe..76089fda3abfb 100644 --- a/bolt/test/runtime/X86/indirect-goto-pie.test +++ b/bolt/test/runtime/X86/indirect-goto-pie.test @@ -2,7 +2,7 @@ REQUIRES: x86_64-linux RUN: %clang %S/Inputs/indirect_goto.c -o %t -fpic -pie -Wl,-q -RUN: llvm-bolt %t -o %t.bolt -relocs=1 -print-cfg -print-only=main \ +RUN: llvm-bolt %t -o %t.bolt --relocs=1 --print-cfg --print-only=main \ RUN: |& FileCheck %s # The test fails as we don't update corresponding dynamic relocations. RUN: not %t.bolt diff --git a/bolt/test/runtime/X86/instrumentation-dup-jts.s b/bolt/test/runtime/X86/instrumentation-dup-jts.s index f4da375c83227..26f3ab3c2a431 100755 --- a/bolt/test/runtime/X86/instrumentation-dup-jts.s +++ b/bolt/test/runtime/X86/instrumentation-dup-jts.s @@ -48,16 +48,16 @@ # RUN: %s -o %t.o # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -instrument -instrumentation-file=%t.fdata \ +# RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata \ # RUN: -o %t.instrumented # Instrumented program needs to finish returning zero # RUN: %t.instrumented 120 # Test that the instrumented data makes sense -# RUN: llvm-bolt %t.exe -o %t.bolted -data %t.fdata \ -# RUN: -reorder-blocks=cache+ -reorder-functions=hfsort+ \ -# RUN: -print-only=interp -print-finalized | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t.bolted --data %t.fdata \ +# RUN: --reorder-blocks=ext-tsp --reorder-functions=hfsort+ \ +# RUN: --print-only=interp --print-finalized | FileCheck %s # RUN: %t.bolted 120 diff --git a/bolt/test/runtime/X86/instrumentation-ind-calls.s b/bolt/test/runtime/X86/instrumentation-ind-calls.s index d51f9fae7b3d5..60f0d82236bdf 100755 --- a/bolt/test/runtime/X86/instrumentation-ind-calls.s +++ b/bolt/test/runtime/X86/instrumentation-ind-calls.s @@ -12,16 +12,16 @@ # RUN: %s -o %t.o # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -instrument -instrumentation-file=%t.fdata \ +# RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata \ # RUN: -o %t.instrumented # Instrumented program needs to finish returning zero # RUN: %t.instrumented arg1 arg2 # Test that the instrumented data makes sense -# RUN: llvm-bolt %t.exe -o %t.bolted -data %t.fdata \ -# RUN: -reorder-blocks=cache+ -reorder-functions=hfsort+ \ -# RUN: -print-only=main -print-finalized | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t.bolted --data %t.fdata \ +# RUN: --reorder-blocks=ext-tsp --reorder-functions=hfsort+ \ +# RUN: --print-only=main --print-finalized | FileCheck %s # RUN: %t.bolted arg1 arg2 diff --git a/bolt/test/runtime/X86/instrumentation-indirect.c b/bolt/test/runtime/X86/instrumentation-indirect.c index 768c510cdee43..54f1b676ef523 100644 --- a/bolt/test/runtime/X86/instrumentation-indirect.c +++ b/bolt/test/runtime/X86/instrumentation-indirect.c @@ -40,24 +40,24 @@ REQUIRES: system-linux && lit-max-individual-test-time RUN: %clang %cflags %s -o %t.exe -Wl,-q -pie -fpie -RUN: llvm-bolt %t.exe -instrument -instrumentation-file=%t.fdata \ -RUN: -instrumentation-wait-forks=1 -conservative-instrumentation \ +RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata \ +RUN: --instrumentation-wait-forks=1 --conservative-instrumentation \ RUN: -o %t.instrumented_conservative # Instrumented program needs to finish returning zero RUN: %t.instrumented_conservative | FileCheck %s -check-prefix=CHECK-OUTPUT -RUN: llvm-bolt %t.exe -instrument -instrumentation-file=%t.fdata \ -RUN: -instrumentation-wait-forks=1 \ +RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata \ +RUN: --instrumentation-wait-forks=1 \ RUN: -o %t.instrumented # Instrumented program needs to finish returning zero RUN: %t.instrumented | FileCheck %s -check-prefix=CHECK-OUTPUT # Test that the instrumented data makes sense -RUN: llvm-bolt %t.exe -o %t.bolted -data %t.fdata \ -RUN: -reorder-blocks=cache+ -reorder-functions=hfsort+ \ -RUN: -print-only=interp -print-finalized +RUN: llvm-bolt %t.exe -o %t.bolted --data %t.fdata \ +RUN: --reorder-blocks=ext-tsp --reorder-functions=hfsort+ \ +RUN: --print-only=interp --print-finalized RUN: %t.bolted | FileCheck %s -check-prefix=CHECK-OUTPUT diff --git a/bolt/test/runtime/X86/instrumentation-pie.c b/bolt/test/runtime/X86/instrumentation-pie.c index 2f267252c7d82..6c51f4c8cfb0b 100644 --- a/bolt/test/runtime/X86/instrumentation-pie.c +++ b/bolt/test/runtime/X86/instrumentation-pie.c @@ -23,15 +23,15 @@ REQUIRES: system-linux,bolt-runtime RUN: %clang %cflags %s -o %t.exe -Wl,-q -pie -fpie -RUN: llvm-bolt %t.exe -instrument -instrumentation-file=%t.fdata \ +RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata \ RUN: -o %t.instrumented # Instrumented program needs to finish returning zero RUN: %t.instrumented 1 2 3 | FileCheck %s -check-prefix=CHECK-OUTPUT # Test that the instrumented data makes sense -RUN: llvm-bolt %t.exe -o %t.bolted -data %t.fdata \ -RUN: -reorder-blocks=cache+ -reorder-functions=hfsort+ +RUN: llvm-bolt %t.exe -o %t.bolted --data %t.fdata \ +RUN: --reorder-blocks=ext-tsp --reorder-functions=hfsort+ RUN: %t.bolted 1 2 3 | FileCheck %s -check-prefix=CHECK-OUTPUT diff --git a/bolt/test/runtime/X86/instrumentation-shlib.c b/bolt/test/runtime/X86/instrumentation-shlib.c index f3124270574d3..b59b6dbbad903 100644 --- a/bolt/test/runtime/X86/instrumentation-shlib.c +++ b/bolt/test/runtime/X86/instrumentation-shlib.c @@ -52,7 +52,7 @@ REQUIRES: system-linux,bolt-runtime RUN: %clang %cflags %s -o %t.so -Wl,-q -fpie -fPIC -shared -DLIB RUN: %clang %cflags %s -o %t.exe -Wl,-q -ldl -RUN: llvm-bolt %t.so -instrument -instrumentation-file=%t.so.fdata \ +RUN: llvm-bolt %t.so --instrument --instrumentation-file=%t.so.fdata \ RUN: -o %t.so.instrumented # Program with instrumented shared library needs to finish returning zero @@ -60,8 +60,8 @@ RUN: %t.exe %t.so.instrumented 1 2 | FileCheck %s -check-prefix=CHECK-OUTPUT RUN: test -f %t.so.fdata # Test that the instrumented data makes sense -RUN: llvm-bolt %t.so -o %t.so.bolted -data %t.so.fdata \ -RUN: -reorder-blocks=cache+ -reorder-functions=hfsort+ +RUN: llvm-bolt %t.so -o %t.so.bolted --data %t.so.fdata \ +RUN: --reorder-blocks=ext-tsp --reorder-functions=hfsort+ RUN: %t.exe %t.so.bolted 1 2 | FileCheck %s -check-prefix=CHECK-OUTPUT diff --git a/bolt/test/runtime/X86/internal-call-instrument.test b/bolt/test/runtime/X86/internal-call-instrument.test index 8d359bad14413..ebc61cf5a3bf0 100644 --- a/bolt/test/runtime/X86/internal-call-instrument.test +++ b/bolt/test/runtime/X86/internal-call-instrument.test @@ -4,7 +4,7 @@ REQUIRES: x86_64-linux,bolt-runtime RUN: %clang -O3 %S/Inputs/internalcall-main.c %S/Inputs/internalcall.S -Wl,-q \ RUN: -o %t.exe -RUN: llvm-bolt -instrument %t.exe -instrumentation-file=%t.fdata \ +RUN: llvm-bolt --instrument %t.exe --instrumentation-file=%t.fdata \ RUN: -o %t -relocs -lite=0 RUN: %t | FileCheck %s diff --git a/bolt/test/runtime/X86/internal-call.test b/bolt/test/runtime/X86/internal-call.test index a09a8a730c317..ecd74e972b8c5 100644 --- a/bolt/test/runtime/X86/internal-call.test +++ b/bolt/test/runtime/X86/internal-call.test @@ -6,7 +6,7 @@ REQUIRES: x86_64-linux RUN: %clang -O3 %S/Inputs/internalcall-main.c %S/Inputs/internalcall.S -Wl,-q \ RUN: -o %t.exe -RUN: llvm-bolt %t.exe -o %t -relocs -lite=0 +RUN: llvm-bolt %t.exe -o %t --relocs --lite=0 RUN: %t | FileCheck %s CHECK: Case 1: Result is: DEADBEEF diff --git a/bolt/test/runtime/X86/interp-overwrite-bug.s b/bolt/test/runtime/X86/interp-overwrite-bug.s index eb1f5e8524f2a..574061d68a9db 100644 --- a/bolt/test/runtime/X86/interp-overwrite-bug.s +++ b/bolt/test/runtime/X86/interp-overwrite-bug.s @@ -12,7 +12,8 @@ # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags -no-pie -nostartfiles -nostdlib -lc %t.o -o %t.exe -# RUN: llvm-bolt %t.exe -o %t.exe.bolt -relocs=0 -lite=0 -reorder-blocks=reverse +# RUN: llvm-bolt %t.exe -o %t.exe.bolt --relocs=0 --lite=0 \ +# RUN: --reorder-blocks=reverse # RUN: %t.exe.bolt 1 2 3 diff --git a/bolt/test/runtime/X86/retpoline-synthetic.test b/bolt/test/runtime/X86/retpoline-synthetic.test index 4798244575c30..6cae6a85fbe78 100644 --- a/bolt/test/runtime/X86/retpoline-synthetic.test +++ b/bolt/test/runtime/X86/retpoline-synthetic.test @@ -5,7 +5,7 @@ REQUIRES: x86_64-linux RUN: %clangxx %S/Inputs/retpoline_synthetic.cpp -fno-jump-tables -Wl,-q,-znow \ RUN: -O2 -o %t.exe -RUN: llvm-bolt %t.exe -o %t -insert-retpolines -trap-old-code +RUN: llvm-bolt %t.exe -o %t --insert-retpolines --trap-old-code # Check indirect calls in the original binary RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix=CHECK-CALL-ORIG diff --git a/bolt/test/runtime/X86/section-reloc-with-addend.s b/bolt/test/runtime/X86/section-reloc-with-addend.s index b2be6afb069f2..97b4710db8a10 100755 --- a/bolt/test/runtime/X86/section-reloc-with-addend.s +++ b/bolt/test/runtime/X86/section-reloc-with-addend.s @@ -13,7 +13,7 @@ # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -relocs=1 -print-finalized -print-only=main -o %t.out +# RUN: llvm-bolt %t.exe --relocs=1 --print-finalized --print-only=main -o %t.out # RUN: %t.out 1 2 diff --git a/bolt/test/runtime/X86/shrinkwrapping-alignment.s b/bolt/test/runtime/X86/shrinkwrapping-alignment.s index e1e5f6bfc4ec4..1a16b40b0f8bf 100755 --- a/bolt/test/runtime/X86/shrinkwrapping-alignment.s +++ b/bolt/test/runtime/X86/shrinkwrapping-alignment.s @@ -13,8 +13,8 @@ # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -relocs=1 -frame-opt=all -print-finalized \ -# RUN: -lite=0 -print-only=main -data %t.fdata -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --relocs=1 --frame-opt=all --print-finalized \ +# RUN: --lite=0 --print-only=main --data %t.fdata -o %t.out | FileCheck %s # RUN: %t.out diff --git a/bolt/test/runtime/X86/shrinkwrapping-lock.s b/bolt/test/runtime/X86/shrinkwrapping-lock.s index 050e8f02c5d71..43853b559f07c 100755 --- a/bolt/test/runtime/X86/shrinkwrapping-lock.s +++ b/bolt/test/runtime/X86/shrinkwrapping-lock.s @@ -11,8 +11,8 @@ # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -relocs=1 -frame-opt=all -print-fop \ -# RUN: -print-only=main -data %t.fdata -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --relocs=1 --frame-opt=all --print-fop \ +# RUN: --print-only=main --data %t.fdata -o %t.out | FileCheck %s # RUN: %t.out 1 diff --git a/bolt/test/runtime/X86/shrinkwrapping-pushpop.s b/bolt/test/runtime/X86/shrinkwrapping-pushpop.s index 79641f83d5f47..fc8e3ce9e5c32 100755 --- a/bolt/test/runtime/X86/shrinkwrapping-pushpop.s +++ b/bolt/test/runtime/X86/shrinkwrapping-pushpop.s @@ -12,8 +12,8 @@ # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -relocs=1 -frame-opt=all -print-finalized \ -# RUN: -print-only=main -data %t.fdata -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --relocs=1 --frame-opt=all --print-finalized \ +# RUN: --print-only=main --data %t.fdata -o %t.out | FileCheck %s # RUN: %t.out diff --git a/bolt/test/runtime/X86/tail-duplication-constant-prop.s b/bolt/test/runtime/X86/tail-duplication-constant-prop.s index 0a074d1dc9e3a..863c6ff92d222 100644 --- a/bolt/test/runtime/X86/tail-duplication-constant-prop.s +++ b/bolt/test/runtime/X86/tail-duplication-constant-prop.s @@ -4,14 +4,16 @@ # RUN: %s -o %t.o # RUN: link_fdata %s %t.o %t.fdata # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -data %t.fdata -reorder-blocks=cache+ -print-finalized \ -# RUN: -tail-duplication -tail-duplication-minimum-offset 1 -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --data %t.fdata --reorder-blocks=ext-tsp \ +# RUN: --print-finalized \ +# RUN: --tail-duplication=moderate --tail-duplication-minimum-offset=1 \ +# RUN: --tail-duplication-const-copy-propagation=1 -o %t.out | FileCheck %s # RUN: %t.exe; echo $? # RUN: %t.out; echo $? # FDATA: 1 main 14 1 main #.BB2# 0 10 # FDATA: 1 main 16 1 main #.BB2# 0 20 -# CHECK: tail duplication possible duplications: 1 +# CHECK: BOLT-INFO: tail duplication modified 1 ({{.*}}%) functions; duplicated 1 blocks ({{.*}} bytes) responsible for {{.*}} dynamic executions ({{.*}}% of all block executions) # CHECK: BB Layout : .LBB00, .Ltail-dup0, .Ltmp0, .Ltmp1 # CHECK-NOT: mov $0x2, %rbx @@ -31,7 +33,7 @@ main: mov %rbx, %rax mov $0x5, %rbx add %rsi, %rax - jmp .BB4 + retq .BB3: mov $0x9, %rbx .BB4: diff --git a/bolt/test/runtime/X86/three-way-branch-pass.s b/bolt/test/runtime/X86/three-way-branch-pass.s index 953a60e08ef1d..bf5273fbbaee4 100644 --- a/bolt/test/runtime/X86/three-way-branch-pass.s +++ b/bolt/test/runtime/X86/three-way-branch-pass.s @@ -4,8 +4,8 @@ # RUN: %s -o %t.o # RUN: link_fdata %s %t.o %t.fdata # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -data %t.fdata -print-finalized \ -# RUN: -o %t.out -three-way-branch | FileCheck %s +# RUN: llvm-bolt %t.exe --data %t.fdata --print-finalized \ +# RUN: -o %t.out --three-way-branch | FileCheck %s # RUN: %t.exe # RUN: %t.out diff --git a/bolt/test/runtime/X86/user-func-reorder.c b/bolt/test/runtime/X86/user-func-reorder.c index b027bd28c6d55..fcb92bca16259 100644 --- a/bolt/test/runtime/X86/user-func-reorder.c +++ b/bolt/test/runtime/X86/user-func-reorder.c @@ -29,8 +29,8 @@ REQUIRES: system-linux,bolt-runtime RUN: %clang %cflags -no-pie %s -o %t.exe -Wl,-q -RUN: llvm-bolt %t.exe -relocs=1 -lite -reorder-functions=user \ -RUN: -hugify -function-order=%p/Inputs/user_func_order.txt -o %t +RUN: llvm-bolt %t.exe --relocs=1 --lite --reorder-functions=user \ +RUN: --hugify --function-order=%p/Inputs/user_func_order.txt -o %t RUN: llvm-nm --numeric-sort --print-armap %t | \ RUN: FileCheck %s -check-prefix=CHECK-NM RUN: %t 1 2 3 | FileCheck %s -check-prefix=CHECK-OUTPUT diff --git a/bolt/test/runtime/fptr.test b/bolt/test/runtime/fptr.test index 66b46ffea3a2f..c9e9de4ef0b98 100644 --- a/bolt/test/runtime/fptr.test +++ b/bolt/test/runtime/fptr.test @@ -1,7 +1,7 @@ # Make sure BOLT correctly updates values based on function pointer. RUN: %clang %cflags -no-pie %p/Inputs/fptr.c -Wl,-q -o %t.exe -RUN: llvm-bolt %t.exe -o %t -lite=0 +RUN: llvm-bolt %t.exe -o %t --lite=0 RUN: %t | FileCheck %s CHECK: Global = 0x[[#%x,ADDR:]] diff --git a/bolt/test/runtime/iplt.c b/bolt/test/runtime/iplt.c index fb6420f828f68..b0e2e6d250700 100644 --- a/bolt/test/runtime/iplt.c +++ b/bolt/test/runtime/iplt.c @@ -2,7 +2,7 @@ // RUN: %clang %cflags -no-pie %s -fuse-ld=lld \ // RUN: -o %t.exe -Wl,-q -// RUN: llvm-bolt %t.exe -o %t.bolt.exe -use-old-text=0 -lite=0 +// RUN: llvm-bolt %t.exe -o %t.bolt.exe --use-old-text=0 --lite=0 // RUN: %t.bolt.exe | FileCheck %s // CHECK: foo diff --git a/bolt/test/runtime/meta-merge-fdata.test b/bolt/test/runtime/meta-merge-fdata.test index 87fb9d768ec6d..57a8a54dcc26e 100644 --- a/bolt/test/runtime/meta-merge-fdata.test +++ b/bolt/test/runtime/meta-merge-fdata.test @@ -7,7 +7,8 @@ REQUIRES: x86_64-linux # - Direct branches # - Unmapped calls coming from uninstrumented code (libc) # - Direct calls -RUN: llvm-bolt merge-fdata -o %t.inst -instrument -instrumentation-file=%t.fdata +RUN: llvm-bolt merge-fdata -o %t.inst --instrument \ +RUN: --instrumentation-file=%t.fdata # Execute with no input RUN: %t.inst --version @@ -19,9 +20,10 @@ RUN: cat %t.fdata1 | FileCheck %s --check-prefix=CHECK-FDATA CHECK-FDATA: 0 [unknown] 0 1 _start 0 0 1 # Check that BOLT works with this profile -RUN: llvm-bolt merge-fdata -o %t.bolt -data %t.fdata1 \ -RUN: -reorder-blocks=cache+ -reorder-functions=hfsort+ -split-functions=3 | \ -RUN: FileCheck %s --check-prefix=CHECK-BOLT1 +RUN: llvm-bolt merge-fdata -o %t.bolt --data %t.fdata1 \ +RUN: --reorder-blocks=ext-tsp --reorder-functions=hfsort+ \ +RUN: --split-functions=3 \ +RUN: | FileCheck %s --check-prefix=CHECK-BOLT1 CHECK-BOLT1-NOT: invalid (possibly stale) profile # Execute again @@ -30,7 +32,7 @@ RUN: mv %t.fdata %t.fdata2 # Check profile coverage RUN: llvm-boltdiff merge-fdata merge-fdata \ -RUN: -data %t.fdata1 -data2 %t.fdata2 -display-count=20 | \ +RUN: --data %t.fdata1 --data2 %t.fdata2 --display-count=20 | \ RUN: FileCheck %s --check-prefix=CHECK-BOLTDIFF CHECK-BOLTDIFF: Inputs share [[#]] functions @@ -40,9 +42,10 @@ RUN: %t.inst %t.fdata1 %t.fdata2 > %t.fdata.inst RUN: cmp %t.fdata.base %t.fdata.inst # Optimize using merged fdata -RUN: llvm-bolt merge-fdata -o %t.opt -data %t.fdata.base \ -RUN: -reorder-blocks=cache+ -reorder-functions=hfsort+ -split-functions=3 | \ -RUN: FileCheck %s --check-prefix=CHECK-BOLT2 +RUN: llvm-bolt merge-fdata -o %t.opt --data %t.fdata.base \ +RUN: --reorder-blocks=ext-tsp --reorder-functions=hfsort+ \ +RUN: --split-functions=3 \ +RUN: | FileCheck %s --check-prefix=CHECK-BOLT2 CHECK-BOLT2-NOT: invalid (possibly stale) profile # Check that optimized binary produces the same result diff --git a/bolt/test/runtime/plt-gnu-ld.test b/bolt/test/runtime/plt-gnu-ld.test index c1d945884733f..50bdc7125ea52 100644 --- a/bolt/test/runtime/plt-gnu-ld.test +++ b/bolt/test/runtime/plt-gnu-ld.test @@ -6,7 +6,7 @@ // RUN: %clang %cflags %p/../Inputs/plt.c -fuse-ld=bfd \ // RUN: -o %t.bfd.exe -Wl,-q -// RUN: llvm-bolt %t.bfd.exe -o %t.bfd.bolt.exe -use-old-text=0 -lite=0 +// RUN: llvm-bolt %t.bfd.exe -o %t.bfd.bolt.exe --use-old-text=0 --lite=0 // RUN: %t.bfd.bolt.exe | FileCheck %s // CHECK: Test completed diff --git a/bolt/test/runtime/plt-lld.test b/bolt/test/runtime/plt-lld.test index b52652f606dd6..b505a191f90ab 100644 --- a/bolt/test/runtime/plt-lld.test +++ b/bolt/test/runtime/plt-lld.test @@ -4,13 +4,13 @@ // Non-PIE: RUN: %clang %cflags -no-pie %p/../Inputs/plt.c -fuse-ld=lld \ RUN: -o %t.lld.exe -Wl,-q -RUN: llvm-bolt %t.lld.exe -o %t.lld.bolt.exe -use-old-text=0 -lite=0 +RUN: llvm-bolt %t.lld.exe -o %t.lld.bolt.exe --use-old-text=0 --lite=0 RUN: %t.lld.bolt.exe | FileCheck %s // PIE: RUN: %clang %cflags -fPIC -pie %p/../Inputs/plt.c -fuse-ld=lld \ RUN: -o %t.lld.pie.exe -Wl,-q -RUN: llvm-bolt %t.lld.pie.exe -o %t.lld.bolt.pie.exe -use-old-text=0 -lite=0 +RUN: llvm-bolt %t.lld.pie.exe -o %t.lld.bolt.pie.exe --use-old-text=0 --lite=0 RUN: %t.lld.bolt.pie.exe | FileCheck %s CHECK: Test completed diff --git a/bolt/tools/merge-fdata/merge-fdata.cpp b/bolt/tools/merge-fdata/merge-fdata.cpp index b28ac91e1d559..3cb6c910a8b54 100644 --- a/bolt/tools/merge-fdata/merge-fdata.cpp +++ b/bolt/tools/merge-fdata/merge-fdata.cpp @@ -15,6 +15,7 @@ #include "bolt/Profile/ProfileYAMLMapping.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" @@ -63,6 +64,12 @@ SuppressMergedDataOutput("q", cl::Optional, cl::cat(MergeFdataCategory)); +static cl::opt +OutputFilePath("o", + cl::value_desc("file"), + cl::desc("Write output to "), + cl::cat(MergeFdataCategory)); + } // namespace opts namespace { @@ -80,6 +87,18 @@ static void report_error(Twine Message, StringRef CustomError) { exit(1); } +static raw_fd_ostream &output() { + if (opts::OutputFilePath.empty() || opts::OutputFilePath == "-") + return outs(); + else { + std::error_code EC; + static raw_fd_ostream Output(opts::OutputFilePath, EC); + if (EC) + report_error(opts::OutputFilePath, EC); + return Output; + } +} + void mergeProfileHeaders(BinaryProfileHeader &MergedHeader, const BinaryProfileHeader &Header) { if (MergedHeader.FileName.empty()) @@ -235,7 +254,7 @@ bool isYAML(const StringRef Filename) { return false; } -void mergeLegacyProfiles(const cl::list &Filenames) { +void mergeLegacyProfiles(const SmallVectorImpl &Filenames) { errs() << "Using legacy profile format.\n"; bool BoltedCollection = false; bool First = true; @@ -282,9 +301,9 @@ void mergeLegacyProfiles(const cl::list &Filenames) { } if (BoltedCollection) - outs() << "boltedcollection\n"; + output() << "boltedcollection\n"; for (const auto &Entry : Entries) - outs() << Entry.getKey() << " " << Entry.getValue() << "\n"; + output() << Entry.getKey() << " " << Entry.getValue() << "\n"; errs() << "Profile from " << Filenames.size() << " files merged.\n"; } @@ -305,8 +324,28 @@ int main(int argc, char **argv) { ToolName = argv[0]; - if (!isYAML(opts::InputDataFilenames.front())) { - mergeLegacyProfiles(opts::InputDataFilenames); + // Recursively expand input directories into input file lists. + SmallVector Inputs; + for (std::string &InputDataFilename : opts::InputDataFilenames) { + if (!llvm::sys::fs::exists(InputDataFilename)) + report_error(InputDataFilename, + std::make_error_code(std::errc::no_such_file_or_directory)); + if (llvm::sys::fs::is_regular_file(InputDataFilename)) + Inputs.emplace_back(InputDataFilename); + else if (llvm::sys::fs::is_directory(InputDataFilename)) { + std::error_code EC; + for (llvm::sys::fs::recursive_directory_iterator F(InputDataFilename, EC), + E; + F != E && !EC; F.increment(EC)) + if (llvm::sys::fs::is_regular_file(F->path())) + Inputs.emplace_back(F->path()); + if (EC) + report_error(InputDataFilename, EC); + } + } + + if (!isYAML(Inputs.front())) { + mergeLegacyProfiles(Inputs); return 0; } @@ -317,7 +356,7 @@ int main(int argc, char **argv) { // Merged information for all functions. StringMap MergedBFs; - for (std::string &InputDataFilename : opts::InputDataFilenames) { + for (std::string &InputDataFilename : Inputs) { ErrorOr> MB = MemoryBuffer::getFileOrSTDIN(InputDataFilename); if (std::error_code EC = MB.getError()) @@ -354,7 +393,7 @@ int main(int argc, char **argv) { } if (!opts::SuppressMergedDataOutput) { - yaml::Output YamlOut(outs()); + yaml::Output YamlOut(output()); BinaryProfile MergedProfile; MergedProfile.Header = MergedHeader; diff --git a/bolt/utils/dot2html/d3-graphviz-template.html b/bolt/utils/dot2html/d3-graphviz-template.html new file mode 100644 index 0000000000000..c86f779f8562d --- /dev/null +++ b/bolt/utils/dot2html/d3-graphviz-template.html @@ -0,0 +1,85 @@ + + + + + + +
+ diff --git a/bolt/utils/dot2html/dot2html.py b/bolt/utils/dot2html/dot2html.py new file mode 100755 index 0000000000000..07a1faad3050c --- /dev/null +++ b/bolt/utils/dot2html/dot2html.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +import argparse +import os +import sys + +BASE_PATH = os.path.dirname(os.path.abspath(__file__)) +HTML_TEMPLATE_NAME = 'd3-graphviz-template.html' +HTML_TEMPLATE_PATH = os.path.join(BASE_PATH, HTML_TEMPLATE_NAME) + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('dotfile', nargs='?', type=argparse.FileType('r'), + default=sys.stdin, + help='Input .dot file, reads from stdin if not set') + parser.add_argument('htmlfile', nargs='?', type=argparse.FileType('w'), + default=sys.stdout, + help='Output .html file, writes to stdout if not set') + args = parser.parse_args() + + template = open(HTML_TEMPLATE_PATH, 'r') + + for line in template: + if "" in line: + print(args.dotfile.read(), file=args.htmlfile, end='') + else: + print(line, file=args.htmlfile, end='') + +if __name__ == "__main__": + main() diff --git a/bolt/utils/nfc-check-setup.py b/bolt/utils/nfc-check-setup.py old mode 100644 new mode 100755 index 46570b642c0ce..d3f0354e739be --- a/bolt/utils/nfc-check-setup.py +++ b/bolt/utils/nfc-check-setup.py @@ -7,6 +7,17 @@ import sys import textwrap +def get_git_ref_or_rev(dir: str) -> str: + # Run 'git symbolic-ref -q --short HEAD || git rev-parse --short HEAD' + cmd_ref = 'git symbolic-ref -q --short HEAD' + ref = subprocess.run(shlex.split(cmd_ref), cwd=dir, text=True, + stdout=subprocess.PIPE) + if not ref.returncode: + return ref.stdout.strip() + cmd_rev = 'git rev-parse --short HEAD' + return subprocess.check_output(shlex.split(cmd_rev), cwd=dir, + text=True).strip() + def main(): parser = argparse.ArgumentParser(description=textwrap.dedent(''' @@ -29,16 +40,22 @@ def main(): if not source_dir: sys.exit("Source directory is not found") - wrapper_path = os.path.abspath( - f'{source_dir}/../bolt/utils/llvm-bolt-wrapper.py') + script_dir = os.path.dirname(os.path.abspath(__file__)) + wrapper_path = f'{script_dir}/llvm-bolt-wrapper.py' # build the current commit subprocess.run(shlex.split("cmake --build . --target llvm-bolt"), cwd=args.build_dir) # rename llvm-bolt os.replace(bolt_path, f'{bolt_path}.new') + # memorize the old hash for logging + old_ref = get_git_ref_or_rev(source_dir) + + # save local changes before checkout + subprocess.run(shlex.split("git stash"), cwd=source_dir) # check out the previous commit - subprocess.run(shlex.split("git checkout -f HEAD^"), - cwd=source_dir) + subprocess.run(shlex.split("git checkout -f HEAD^"), cwd=source_dir) + # get the parent commit hash for logging + new_ref = get_git_ref_or_rev(source_dir) # build the previous commit subprocess.run(shlex.split("cmake --build . --target llvm-bolt"), cwd=args.build_dir) @@ -53,6 +70,12 @@ def main(): f.write(ini) # symlink llvm-bolt-wrapper os.symlink(wrapper_path, bolt_path) + print(f"The repository {source_dir} has been switched from rev {old_ref} " + f"to {new_ref}. Local changes were stashed. Switch back using\n\t" + f"git checkout {old_ref}\n" + "Current build directory is ready to run BOLT tests, e.g.\n\t" + "bin/llvm-lit -sv tools/bolt/test\nor\n\t" + "bin/llvm-lit -sv tools/bolttests") if __name__ == "__main__": diff --git a/clang-tools-extra/README.txt b/clang-tools-extra/README.txt index 9c859a052c4b4..6891e4078997f 100644 --- a/clang-tools-extra/README.txt +++ b/clang-tools-extra/README.txt @@ -7,9 +7,6 @@ that are developed as part of the LLVM compiler infrastructure project and the Clang frontend. These tools are kept in a separate "extra" repository to allow lighter weight checkouts of the core Clang codebase. -This repository is only intended to be checked out inside of a full LLVM+Clang -tree, and in the 'tools/extra' subdirectory of the Clang checkout. - All discussion regarding Clang, Clang-based tools, and code in this repository should be held using the standard Clang forum: https://discourse.llvm.org/c/clang @@ -19,4 +16,4 @@ commit lists: http://lists.llvm.org/mailman/listinfo/cfe-commits If you find a bug in these tools, please file it in the LLVM bug tracker: - http://llvm.org/bugs/ + https://github.com/llvm/llvm-project/issues/ diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index cd0cbfda3dc5a..57b19bd30c1c3 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -441,9 +441,7 @@ ClangTidyASTConsumerFactory::createASTConsumer( Context, Context.canEnableAnalyzerAlphaCheckers()); if (!AnalyzerOptions->CheckersAndPackages.empty()) { setStaticAnalyzerCheckerOpts(Context.getOptions(), *AnalyzerOptions); - AnalyzerOptions->AnalysisStoreOpt = RegionStoreModel; AnalyzerOptions->AnalysisDiagOpt = PD_NONE; - AnalyzerOptions->AnalyzeNestedBlocks = true; AnalyzerOptions->eagerlyAssumeBinOpBifurcation = true; std::unique_ptr AnalysisConsumer = ento::CreateAnalysisConsumer(Compiler); diff --git a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp index 064b6ae19784e..c67efa341f629 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp @@ -158,9 +158,12 @@ bool UseAfterMoveFinder::findInternal(const CFGBlock *Block, // Ignore all reinitializations where the move potentially comes after the // reinit. + // If `Reinit` is identical to `MovingCall`, we're looking at a move-to-self + // (e.g. `a = std::move(a)`). Count these as reinitializations. llvm::SmallVector ReinitsToDelete; for (const Stmt *Reinit : Reinits) { - if (MovingCall && Sequence->potentiallyAfter(MovingCall, Reinit)) + if (MovingCall && Reinit != MovingCall && + Sequence->potentiallyAfter(MovingCall, Reinit)) ReinitsToDelete.push_back(Reinit); } for (const Stmt *Reinit : ReinitsToDelete) { @@ -400,7 +403,8 @@ void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) { auto CallMoveMatcher = callExpr(callee(functionDecl(hasName("::std::move"))), argumentCountIs(1), hasArgument(0, declRefExpr().bind("arg")), - anyOf(hasAncestor(lambdaExpr().bind("containing-lambda")), + anyOf(hasAncestor(compoundStmt( + hasParent(lambdaExpr().bind("containing-lambda")))), hasAncestor(functionDecl().bind("containing-func"))), unless(inDecltypeOrTemplateArg()), // try_emplace is a common maybe-moving function that returns a diff --git a/clang-tools-extra/clang-tidy/cert/NonTrivialTypesLibcMemoryCallsCheck.cpp b/clang-tools-extra/clang-tidy/cert/NonTrivialTypesLibcMemoryCallsCheck.cpp index 8e6acea290826..5c8da5b4cacf7 100644 --- a/clang-tools-extra/clang-tidy/cert/NonTrivialTypesLibcMemoryCallsCheck.cpp +++ b/clang-tools-extra/clang-tidy/cert/NonTrivialTypesLibcMemoryCallsCheck.cpp @@ -80,7 +80,7 @@ void NonTrivialTypesLibcMemoryCallsCheck::registerMatchers( auto IsRecordSizeOf = expr(sizeOfExpr(hasArgumentOfType(equalsBoundNode("Record")))); auto ArgChecker = [&](Matcher RecordConstraint, - BindableMatcher SecondArg) { + BindableMatcher SecondArg = expr()) { return allOf(argumentCountIs(3), hasArgument(0, IsStructPointer(RecordConstraint, true)), hasArgument(1, SecondArg), hasArgument(2, IsRecordSizeOf)); @@ -89,8 +89,7 @@ void NonTrivialTypesLibcMemoryCallsCheck::registerMatchers( Finder->addMatcher( callExpr(callee(namedDecl(hasAnyName( utils::options::parseListPair(BuiltinMemSet, MemSetNames)))), - ArgChecker(unless(isTriviallyDefaultConstructible()), - expr(integerLiteral(equals(0))))) + ArgChecker(unless(isTriviallyDefaultConstructible()))) .bind("lazyConstruct"), this); Finder->addMatcher( diff --git a/clang-tools-extra/clang-tidy/modernize/IntegralLiteralExpressionMatcher.cpp b/clang-tools-extra/clang-tidy/modernize/IntegralLiteralExpressionMatcher.cpp index 91a10f8956e62..ca0e99fc787a1 100644 --- a/clang-tools-extra/clang-tidy/modernize/IntegralLiteralExpressionMatcher.cpp +++ b/clang-tools-extra/clang-tidy/modernize/IntegralLiteralExpressionMatcher.cpp @@ -8,6 +8,7 @@ #include "IntegralLiteralExpressionMatcher.h" +#include #include #include @@ -81,6 +82,50 @@ bool IntegralLiteralExpressionMatcher::unaryOperator() { return true; } +static LiteralSize literalTokenSize(const Token &Tok) { + unsigned int Length = Tok.getLength(); + if (Length <= 1) + return LiteralSize::Int; + + bool SeenUnsigned = false; + bool SeenLong = false; + bool SeenLongLong = false; + const char *Text = Tok.getLiteralData(); + for (unsigned int End = Length - 1; End > 0; --End) { + if (std::isdigit(Text[End])) + break; + + if (std::toupper(Text[End]) == 'U') + SeenUnsigned = true; + else if (std::toupper(Text[End]) == 'L') { + if (SeenLong) + SeenLongLong = true; + SeenLong = true; + } + } + + if (SeenLongLong) { + if (SeenUnsigned) + return LiteralSize::UnsignedLongLong; + + return LiteralSize::LongLong; + } + if (SeenLong) { + if (SeenUnsigned) + return LiteralSize::UnsignedLong; + + return LiteralSize::Long; + } + if (SeenUnsigned) + return LiteralSize::UnsignedInt; + + return LiteralSize::Int; +} + +static bool operator<(LiteralSize LHS, LiteralSize RHS) { + return static_cast(LHS) < static_cast(RHS); +} + bool IntegralLiteralExpressionMatcher::unaryExpr() { if (!unaryOperator()) return false; @@ -102,7 +147,10 @@ bool IntegralLiteralExpressionMatcher::unaryExpr() { !isIntegralConstant(*Current)) { return false; } + + LargestSize = std::max(LargestSize, literalTokenSize(*Current)); ++Current; + return true; } @@ -217,14 +265,24 @@ bool IntegralLiteralExpressionMatcher::conditionalExpr() { } bool IntegralLiteralExpressionMatcher::commaExpr() { - return nonTerminalChainedExpr( - &IntegralLiteralExpressionMatcher::conditionalExpr); + auto Pred = CommaAllowed + ? std::function( + [](Token Tok) { return Tok.is(tok::TokenKind::comma); }) + : std::function([](Token) { return false; }); + return nonTerminalChainedExpr( + &IntegralLiteralExpressionMatcher::conditionalExpr, Pred); } bool IntegralLiteralExpressionMatcher::expr() { return commaExpr(); } bool IntegralLiteralExpressionMatcher::match() { - return expr() && Current == End; + // Top-level allowed expression is conditionalExpr(), not expr(), because + // comma operators are only valid initializers when used inside parentheses. + return conditionalExpr() && Current == End; +} + +LiteralSize IntegralLiteralExpressionMatcher::largestLiteralSize() const { + return LargestSize; } } // namespace modernize diff --git a/clang-tools-extra/clang-tidy/modernize/IntegralLiteralExpressionMatcher.h b/clang-tools-extra/clang-tidy/modernize/IntegralLiteralExpressionMatcher.h index 9202cc1ed4574..4499ef983ea4e 100644 --- a/clang-tools-extra/clang-tidy/modernize/IntegralLiteralExpressionMatcher.h +++ b/clang-tools-extra/clang-tidy/modernize/IntegralLiteralExpressionMatcher.h @@ -16,15 +16,27 @@ namespace clang { namespace tidy { namespace modernize { +enum class LiteralSize { + Unknown = 0, + Int, + UnsignedInt, + Long, + UnsignedLong, + LongLong, + UnsignedLongLong +}; + // Parses an array of tokens and returns true if they conform to the rules of // C++ for whole expressions involving integral literals. Follows the operator -// precedence rules of C++. +// precedence rules of C++. Optionally exclude comma operator expressions. class IntegralLiteralExpressionMatcher { public: - IntegralLiteralExpressionMatcher(ArrayRef Tokens) - : Current(Tokens.begin()), End(Tokens.end()) {} + IntegralLiteralExpressionMatcher(ArrayRef Tokens, bool CommaAllowed) + : Current(Tokens.begin()), End(Tokens.end()), CommaAllowed(CommaAllowed) { + } bool match(); + LiteralSize largestLiteralSize() const; private: bool advance(); @@ -64,6 +76,8 @@ class IntegralLiteralExpressionMatcher { ArrayRef::iterator Current; ArrayRef::iterator End; + LiteralSize LargestSize{LiteralSize::Unknown}; + bool CommaAllowed; }; } // namespace modernize diff --git a/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp index 5d7daf837007f..1c196a9a92749 100644 --- a/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp @@ -321,8 +321,14 @@ void MacroToEnumCallbacks::FileChanged(SourceLocation Loc, bool MacroToEnumCallbacks::isInitializer(ArrayRef MacroTokens) { - IntegralLiteralExpressionMatcher Matcher(MacroTokens); - return Matcher.match(); + IntegralLiteralExpressionMatcher Matcher(MacroTokens, LangOpts.C99 == 0); + bool Matched = Matcher.match(); + bool isC = !LangOpts.CPlusPlus; + if (isC && (Matcher.largestLiteralSize() != LiteralSize::Int && + Matcher.largestLiteralSize() != LiteralSize::UnsignedInt)) + return false; + + return Matched; } diff --git a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp index e1db4e04f53f7..e6fb4c0a87264 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp @@ -15,6 +15,69 @@ namespace tidy { namespace modernize { namespace { +// Identical to hasAnyName, except it does not take template specifiers into +// account. This is used to match the functions names as in +// DefaultEmplacyFunctions below without caring about the template types of the +// containers. +AST_MATCHER_P(NamedDecl, hasAnyNameIgnoringTemplates, std::vector, + Names) { + const std::string FullName = "::" + Node.getQualifiedNameAsString(); + + // This loop removes template specifiers by only keeping characters not within + // template brackets. We keep a depth count to handle nested templates. For + // example, it'll transform a::b>::e to simply a::b::e. + std::string FullNameTrimmed; + int Depth = 0; + for (const auto &Character : FullName) { + if (Character == '<') { + ++Depth; + } else if (Character == '>') { + --Depth; + } else if (Depth == 0) { + FullNameTrimmed.append(1, Character); + } + } + + // This loop is taken from HasNameMatcher::matchesNodeFullSlow in + // clang/lib/ASTMatchers/ASTMatchersInternal.cpp and checks whether + // FullNameTrimmed matches any of the given Names. + const StringRef FullNameTrimmedRef = FullNameTrimmed; + for (const StringRef Pattern : Names) { + if (Pattern.startswith("::")) { + if (FullNameTrimmed == Pattern) + return true; + } else if (FullNameTrimmedRef.endswith(Pattern) && + FullNameTrimmedRef.drop_back(Pattern.size()).endswith("::")) { + return true; + } + } + + return false; +} + +// Checks if the given matcher is the last argument of the given CallExpr. +AST_MATCHER_P(CallExpr, hasLastArgument, + clang::ast_matchers::internal::Matcher, InnerMatcher) { + if (Node.getNumArgs() == 0) + return false; + + return InnerMatcher.matches(*Node.getArg(Node.getNumArgs() - 1), Finder, + Builder); +} + +// Checks if the given member call has the same number of arguments as the +// function had parameters defined (this is useful to check if there is only one +// variadic argument). +AST_MATCHER(CXXMemberCallExpr, hasSameNumArgsAsDeclNumParams) { + if (Node.getMethodDecl()->isFunctionTemplateSpecialization()) + return Node.getNumArgs() == Node.getMethodDecl() + ->getPrimaryTemplate() + ->getTemplatedDecl() + ->getNumParams(); + + return Node.getNumArgs() == Node.getMethodDecl()->getNumParams(); +} + AST_MATCHER(DeclRefExpr, hasExplicitTemplateArgs) { return Node.hasExplicitTemplateArgs(); } @@ -25,6 +88,20 @@ const auto DefaultSmartPointers = "::std::shared_ptr; ::std::unique_ptr; ::std::auto_ptr; ::std::weak_ptr"; const auto DefaultTupleTypes = "::std::pair; ::std::tuple"; const auto DefaultTupleMakeFunctions = "::std::make_pair; ::std::make_tuple"; +const auto DefaultEmplacyFunctions = + "vector::emplace_back; vector::emplace;" + "deque::emplace; deque::emplace_front; deque::emplace_back;" + "forward_list::emplace_after; forward_list::emplace_front;" + "list::emplace; list::emplace_back; list::emplace_front;" + "set::emplace; set::emplace_hint;" + "map::emplace; map::emplace_hint;" + "multiset::emplace; multiset::emplace_hint;" + "multimap::emplace; multimap::emplace_hint;" + "unordered_set::emplace; unordered_set::emplace_hint;" + "unordered_map::emplace; unordered_map::emplace_hint;" + "unordered_multiset::emplace; unordered_multiset::emplace_hint;" + "unordered_multimap::emplace; unordered_multimap::emplace_hint;" + "stack::emplace; queue::emplace; priority_queue::emplace"; } // namespace UseEmplaceCheck::UseEmplaceCheck(StringRef Name, ClangTidyContext *Context) @@ -37,7 +114,9 @@ UseEmplaceCheck::UseEmplaceCheck(StringRef Name, ClangTidyContext *Context) TupleTypes(utils::options::parseStringList( Options.get("TupleTypes", DefaultTupleTypes))), TupleMakeFunctions(utils::options::parseStringList( - Options.get("TupleMakeFunctions", DefaultTupleMakeFunctions))) {} + Options.get("TupleMakeFunctions", DefaultTupleMakeFunctions))), + EmplacyFunctions(utils::options::parseStringList( + Options.get("EmplacyFunctions", DefaultEmplacyFunctions))) {} void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) { // FIXME: Bunch of functionality that could be easily added: @@ -52,6 +131,13 @@ void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) { hasDeclaration(functionDecl(hasName("push_back"))), on(hasType(cxxRecordDecl(hasAnyName(ContainersWithPushBack))))); + auto CallEmplacy = cxxMemberCallExpr( + hasDeclaration( + functionDecl(hasAnyNameIgnoringTemplates(EmplacyFunctions))), + on(hasType(cxxRecordDecl(has(typedefNameDecl( + hasName("value_type"), hasType(type(hasUnqualifiedDesugaredType( + recordType().bind("value_type")))))))))); + // We can't replace push_backs of smart pointer because // if emplacement fails (f.e. bad_alloc in vector) we will have leak of // passed pointer because smart pointer won't be constructed @@ -73,8 +159,9 @@ void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) { auto ConstructingDerived = hasParent(implicitCastExpr(hasCastKind(CastKind::CK_DerivedToBase))); - // emplace_back can't access private constructor. - auto IsPrivateCtor = hasDeclaration(cxxConstructorDecl(isPrivate())); + // emplace_back can't access private or protected constructors. + auto IsPrivateOrProtectedCtor = + hasDeclaration(cxxConstructorDecl(anyOf(isPrivate(), isProtected()))); auto HasInitList = anyOf(has(ignoringImplicit(initListExpr())), has(cxxStdInitializerListExpr())); @@ -85,7 +172,7 @@ void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) { cxxConstructExpr( unless(anyOf(IsCtorOfSmartPtr, HasInitList, BitFieldAsArgument, InitializerListAsArgument, NewExprAsArgument, - ConstructingDerived, IsPrivateCtor))) + ConstructingDerived, IsPrivateOrProtectedCtor))) .bind("ctor"); auto HasConstructExpr = has(ignoringImplicit(SoughtConstructExpr)); @@ -102,22 +189,64 @@ void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) { hasDeclaration(cxxConstructorDecl(ofClass(hasAnyName(TupleTypes)))))); auto SoughtParam = materializeTemporaryExpr( - anyOf(has(MakeTuple), has(MakeTupleCtor), - HasConstructExpr, has(cxxFunctionalCastExpr(HasConstructExpr)))); + anyOf(has(MakeTuple), has(MakeTupleCtor), HasConstructExpr, + has(cxxFunctionalCastExpr(HasConstructExpr)))); + + auto HasConstructExprWithValueTypeType = + has(ignoringImplicit(cxxConstructExpr( + SoughtConstructExpr, hasType(type(hasUnqualifiedDesugaredType( + type(equalsBoundNode("value_type")))))))); + + auto HasConstructExprWithValueTypeTypeAsLastArgument = + hasLastArgument(materializeTemporaryExpr(anyOf( + HasConstructExprWithValueTypeType, + has(cxxFunctionalCastExpr(HasConstructExprWithValueTypeType))))); Finder->addMatcher( traverse(TK_AsIs, cxxMemberCallExpr(CallPushBack, has(SoughtParam), unless(isInTemplateInstantiation())) - .bind("call")), + .bind("push_back_call")), + this); + + Finder->addMatcher( + traverse(TK_AsIs, + cxxMemberCallExpr( + CallEmplacy, HasConstructExprWithValueTypeTypeAsLastArgument, + hasSameNumArgsAsDeclNumParams(), + unless(isInTemplateInstantiation())) + .bind("emplacy_call")), + this); + + Finder->addMatcher( + traverse( + TK_AsIs, + cxxMemberCallExpr( + CallEmplacy, + on(hasType(cxxRecordDecl(has(typedefNameDecl( + hasName("value_type"), + hasType(type( + hasUnqualifiedDesugaredType(recordType(hasDeclaration( + cxxRecordDecl(hasAnyName(SmallVector( + TupleTypes.begin(), TupleTypes.end()))))))))))))), + has(MakeTuple), hasSameNumArgsAsDeclNumParams(), + unless(isInTemplateInstantiation())) + .bind("emplacy_call")), this); } void UseEmplaceCheck::check(const MatchFinder::MatchResult &Result) { - const auto *Call = Result.Nodes.getNodeAs("call"); + const auto *PushBackCall = + Result.Nodes.getNodeAs("push_back_call"); + const auto *EmplacyCall = + Result.Nodes.getNodeAs("emplacy_call"); const auto *CtorCall = Result.Nodes.getNodeAs("ctor"); const auto *MakeCall = Result.Nodes.getNodeAs("make"); + + assert((PushBackCall || EmplacyCall) && "No call matched"); assert((CtorCall || MakeCall) && "No push_back parameter matched"); + const CXXMemberCallExpr *Call = PushBackCall ? PushBackCall : EmplacyCall; + if (IgnoreImplicitConstructors && CtorCall && CtorCall->getNumArgs() >= 1 && CtorCall->getArg(0)->getSourceRange() == CtorCall->getSourceRange()) return; @@ -125,13 +254,21 @@ void UseEmplaceCheck::check(const MatchFinder::MatchResult &Result) { const auto FunctionNameSourceRange = CharSourceRange::getCharRange( Call->getExprLoc(), Call->getArg(0)->getExprLoc()); - auto Diag = diag(Call->getExprLoc(), "use emplace_back instead of push_back"); + auto Diag = + PushBackCall + ? diag(Call->getExprLoc(), "use emplace_back instead of push_back") + : diag(CtorCall ? CtorCall->getBeginLoc() : MakeCall->getBeginLoc(), + "unnecessary temporary object created while calling " + + Call->getMethodDecl()->getName().str()); if (FunctionNameSourceRange.getBegin().isMacroID()) return; - const auto *EmplacePrefix = MakeCall ? "emplace_back" : "emplace_back("; - Diag << FixItHint::CreateReplacement(FunctionNameSourceRange, EmplacePrefix); + if (PushBackCall) { + const char *EmplacePrefix = MakeCall ? "emplace_back" : "emplace_back("; + Diag << FixItHint::CreateReplacement(FunctionNameSourceRange, + EmplacePrefix); + } const SourceRange CallParensRange = MakeCall ? SourceRange(MakeCall->getCallee()->getEndLoc(), @@ -143,7 +280,7 @@ void UseEmplaceCheck::check(const MatchFinder::MatchResult &Result) { return; const SourceLocation ExprBegin = - MakeCall ? MakeCall->getExprLoc() : CtorCall->getExprLoc(); + CtorCall ? CtorCall->getExprLoc() : MakeCall->getExprLoc(); // Range for constructor name and opening brace. const auto ParamCallSourceRange = @@ -151,7 +288,14 @@ void UseEmplaceCheck::check(const MatchFinder::MatchResult &Result) { Diag << FixItHint::CreateRemoval(ParamCallSourceRange) << FixItHint::CreateRemoval(CharSourceRange::getTokenRange( - CallParensRange.getEnd(), CallParensRange.getEnd())); + CallParensRange.getEnd(), CallParensRange.getEnd())); + + if (MakeCall && EmplacyCall) { + // Remove extra left parenthesis + Diag << FixItHint::CreateRemoval( + CharSourceRange::getCharRange(MakeCall->getCallee()->getEndLoc(), + MakeCall->getArg(0)->getBeginLoc())); + } } void UseEmplaceCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { @@ -164,6 +308,8 @@ void UseEmplaceCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { utils::options::serializeStringList(TupleTypes)); Options.store(Opts, "TupleMakeFunctions", utils::options::serializeStringList(TupleMakeFunctions)); + Options.store(Opts, "EmplacyFunctions", + utils::options::serializeStringList(EmplacyFunctions)); } } // namespace modernize diff --git a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.h b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.h index 096f4e0164cc1..45a1d5dba43f5 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.h +++ b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.h @@ -40,6 +40,7 @@ class UseEmplaceCheck : public ClangTidyCheck { const std::vector SmartPointers; const std::vector TupleTypes; const std::vector TupleMakeFunctions; + const std::vector EmplacyFunctions; }; } // namespace modernize diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index 0c6e73b3446e0..c102b74114d2a 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -253,28 +253,25 @@ IdentifierNamingCheck::FileStyle IdentifierNamingCheck::getFileStyleFromOptions( Styles.resize(SK_Count); SmallString<64> StyleString; for (unsigned I = 0; I < SK_Count; ++I) { - StyleString = StyleNames[I]; - size_t StyleSize = StyleString.size(); + size_t StyleSize = StyleNames[I].size(); + StyleString.assign({StyleNames[I], "HungarianPrefix"}); - StyleString.append("HungarianPrefix"); auto HPTOpt = Options.get(StyleString); - if (!HungarianNotation.checkOptionValid(I, StyleString) && - HPTOpt.hasValue()) + if (HPTOpt.hasValue() && !HungarianNotation.checkOptionValid(I)) configurationDiag("invalid identifier naming option '%0'") << StyleString; - StyleString.resize(StyleSize); - StyleString.append("IgnoredRegexp"); + memcpy(&StyleString[StyleSize], "IgnoredRegexp", 13); + StyleString.truncate(StyleSize + 13); StringRef IgnoredRegexpStr = Options.get(StyleString, ""); - StyleString.resize(StyleSize); - StyleString.append("Prefix"); + memcpy(&StyleString[StyleSize], "Prefix", 6); + StyleString.truncate(StyleSize + 6); std::string Prefix(Options.get(StyleString, "")); // Fast replacement of [Pre]fix -> [Suf]fix. memcpy(&StyleString[StyleSize], "Suf", 3); std::string Postfix(Options.get(StyleString, "")); memcpy(&StyleString[StyleSize], "Case", 4); - StyleString.pop_back(); - StyleString.pop_back(); + StyleString.pop_back_n(2); auto CaseOptional = Options.get(StyleString); @@ -311,9 +308,8 @@ std::string IdentifierNamingCheck::HungarianNotation::getDeclTypeName( if (!EOL) EOL = Begin + strlen(Begin); - const std::vector PosList = { - strchr(Begin, '='), strchr(Begin, ';'), strchr(Begin, ','), - strchr(Begin, ')'), EOL}; + const char *PosList[] = {strchr(Begin, '='), strchr(Begin, ';'), + strchr(Begin, ','), strchr(Begin, ')'), EOL}; for (const auto &Pos : PosList) { if (Pos > Begin) EOL = std::min(EOL, Pos); @@ -408,7 +404,7 @@ IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name, IdentifierNamingCheck::~IdentifierNamingCheck() = default; bool IdentifierNamingCheck::HungarianNotation::checkOptionValid( - int StyleKindIndex, StringRef StyleString) const { + int StyleKindIndex) const { if ((StyleKindIndex >= SK_EnumConstant) && (StyleKindIndex <= SK_ConstantParameter)) return true; @@ -442,16 +438,21 @@ void IdentifierNamingCheck::HungarianNotation::loadFileConfig( StringRef Section = "HungarianNotation."; - SmallString<128> Buffer; + SmallString<128> Buffer = {Section, "General."}; + size_t DefSize = Buffer.size(); for (const auto &Opt : HNOpts) { - Buffer.assign({Section, "General.", Opt}); + Buffer.truncate(DefSize); + Buffer.append(Opt); StringRef Val = Options.get(Buffer, ""); if (!Val.empty()) HNOption.General[Opt] = Val.str(); } + Buffer = {Section, "DerivedType."}; + DefSize = Buffer.size(); for (const auto &Type : HNDerivedTypes) { - Buffer.assign({Section, "DerivedType.", Type}); + Buffer.truncate(DefSize); + Buffer.append(Type); StringRef Val = Options.get(Buffer, ""); if (!Val.empty()) HNOption.DerivedType[Type] = Val.str(); @@ -463,15 +464,21 @@ void IdentifierNamingCheck::HungarianNotation::loadFileConfig( {"WideCharPrinter", "wchar_t*"}, {"WideCharArray", "wchar_t[]"}}; + Buffer = {Section, "CString."}; + DefSize = Buffer.size(); for (const auto &CStr : HNCStrings) { - Buffer.assign({Section, "CString.", CStr.first}); + Buffer.truncate(DefSize); + Buffer.append(CStr.first); StringRef Val = Options.get(Buffer, ""); if (!Val.empty()) HNOption.CString[CStr.first] = Val.str(); } + Buffer = {Section, "PrimitiveType."}; + DefSize = Buffer.size(); for (const auto &PrimType : HungarainNotationPrimitiveTypes) { - Buffer.assign({Section, "PrimitiveType.", PrimType}); + Buffer.truncate(DefSize); + Buffer.append(PrimType); StringRef Val = Options.get(Buffer, ""); if (!Val.empty()) { std::string Type = PrimType.str(); @@ -480,8 +487,11 @@ void IdentifierNamingCheck::HungarianNotation::loadFileConfig( } } + Buffer = {Section, "UserDefinedType."}; + DefSize = Buffer.size(); for (const auto &Type : HungarainNotationUserDefinedTypes) { - Buffer.assign({Section, "UserDefinedType.", Type}); + Buffer.truncate(DefSize); + Buffer.append(Type); StringRef Val = Options.get(Buffer, ""); if (!Val.empty()) HNOption.UserDefinedType[Type] = Val.str(); @@ -796,24 +806,23 @@ void IdentifierNamingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { for (size_t I = 0; I < SK_Count; ++I) { if (!Styles[I]) continue; - StyleString = StyleNames[I]; - size_t StyleSize = StyleString.size(); + size_t StyleSize = StyleNames[I].size(); + StyleString.assign({StyleNames[I], "HungarianPrefix"}); - Options.store(Opts, (StyleString + "HungarianPrefix").str(), - Styles[I]->HPType); + Options.store(Opts, StyleString, Styles[I]->HPType); - StyleString.append("IgnoredRegexp"); + memcpy(&StyleString[StyleSize], "IgnoredRegexp", 13); + StyleString.truncate(StyleSize + 13); Options.store(Opts, StyleString, Styles[I]->IgnoredRegexpStr); - StyleString.resize(StyleSize); - StyleString.append("Prefix"); + memcpy(&StyleString[StyleSize], "Prefix", 6); + StyleString.truncate(StyleSize + 6); Options.store(Opts, StyleString, Styles[I]->Prefix); // Fast replacement of [Pre]fix -> [Suf]fix. memcpy(&StyleString[StyleSize], "Suf", 3); Options.store(Opts, StyleString, Styles[I]->Suffix); if (Styles[I]->Case) { memcpy(&StyleString[StyleSize], "Case", 4); - StyleString.pop_back(); - StyleString.pop_back(); + StyleString.pop_back_n(2); Options.store(Opts, StyleString, *Styles[I]->Case); } } diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h index dcad7f8834273..2739d18a0f74b 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h @@ -89,7 +89,7 @@ class IdentifierNamingCheck final : public RenamerClangTidyCheck { struct HungarianNotation { public: - bool checkOptionValid(int StyleKindIndex, StringRef StyleString) const; + bool checkOptionValid(int StyleKindIndex) const; bool isOptionEnabled(StringRef OptionKey, const llvm::StringMap &StrMap) const; void loadDefaultConfig( diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index 70d98d0e0bb40..ca838618badd9 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -53,8 +53,10 @@ getTemplateSpecializationArgLocs(const NamedDecl &ND) { llvm::dyn_cast(&ND)) { if (auto *Args = Var->getTemplateArgsAsWritten()) return Args->arguments(); - } else if (auto *Var = llvm::dyn_cast(&ND)) - return Var->getTemplateArgsInfo().arguments(); + } else if (auto *Var = llvm::dyn_cast(&ND)) { + if (auto *Args = Var->getTemplateArgsInfo()) + return Args->arguments(); + } // We return None for ClassTemplateSpecializationDecls because it does not // contain TemplateArgumentLoc information. return llvm::None; diff --git a/clang-tools-extra/clangd/Config.h b/clang-tools-extra/clangd/Config.h index ec7247121d5cd..312ca3b7af90a 100644 --- a/clang-tools-extra/clangd/Config.h +++ b/clang-tools-extra/clangd/Config.h @@ -129,7 +129,7 @@ struct Config { /// Configures hover feature. struct { /// Whether hover show a.k.a type. - bool ShowAKA = false; + bool ShowAKA = true; } Hover; struct { diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp b/clang-tools-extra/clangd/ConfigCompile.cpp index 0cdbc5526e6e5..2de8816f9f084 100644 --- a/clang-tools-extra/clangd/ConfigCompile.cpp +++ b/clang-tools-extra/clangd/ConfigCompile.cpp @@ -197,6 +197,7 @@ struct FragmentCompiler { compile(std::move(F.Completion)); compile(std::move(F.Hover)); compile(std::move(F.InlayHints)); + compile(std::move(F.Style)); } void compile(Fragment::IfBlock &&F) { diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index fcf3af7561845..26eb2574195d3 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -578,7 +578,7 @@ HoverInfo getHoverContents(const NamedDecl *D, const PrintingPolicy &PP, const SymbolIndex *Index, const syntax::TokenBuffer &TB) { HoverInfo HI; - const ASTContext &Ctx = D->getASTContext(); + auto &Ctx = D->getASTContext(); HI.AccessSpecifier = getAccessSpelling(D->getAccess()).str(); HI.NamespaceScope = getNamespaceScope(D); @@ -614,19 +614,17 @@ HoverInfo getHoverContents(const NamedDecl *D, const PrintingPolicy &PP, if (const FunctionDecl *FD = getUnderlyingFunction(D)) fillFunctionTypeAndParams(HI, D, FD, PP); else if (const auto *VD = dyn_cast(D)) - HI.Type = printType(VD->getType(), VD->getASTContext(), PP); + HI.Type = printType(VD->getType(), Ctx, PP); else if (const auto *TTP = dyn_cast(D)) HI.Type = TTP->wasDeclaredWithTypename() ? "typename" : "class"; else if (const auto *TTP = dyn_cast(D)) HI.Type = printType(TTP, PP); else if (const auto *VT = dyn_cast(D)) - HI.Type = - printType(VT->getTemplatedDecl()->getType(), VT->getASTContext(), PP); + HI.Type = printType(VT->getTemplatedDecl()->getType(), Ctx, PP); else if (const auto *TN = dyn_cast(D)) - HI.Type = printType(TN->getUnderlyingType(), TN->getASTContext(), PP); + HI.Type = printType(TN->getUnderlyingType().getDesugaredType(Ctx), Ctx, PP); else if (const auto *TAT = dyn_cast(D)) - HI.Type = printType(TAT->getTemplatedDecl()->getUnderlyingType(), - TAT->getASTContext(), PP); + HI.Type = printType(TAT->getTemplatedDecl()->getUnderlyingType(), Ctx, PP); // Fill in value with evaluated initializer if possible. if (const auto *Var = dyn_cast(D)) { diff --git a/clang-tools-extra/clangd/index/CanonicalIncludes.cpp b/clang-tools-extra/clangd/index/CanonicalIncludes.cpp index 3d40219616eca..145d98d57ca83 100644 --- a/clang-tools-extra/clangd/index/CanonicalIncludes.cpp +++ b/clang-tools-extra/clangd/index/CanonicalIncludes.cpp @@ -18,6 +18,655 @@ namespace clang { namespace clangd { namespace { const char IWYUPragma[] = "// IWYU pragma: private, include "; + +const std::pair IncludeMappings[] = { + {"include/__stddef_max_align_t.h", ""}, + {"include/__wmmintrin_aes.h", ""}, + {"include/__wmmintrin_pclmul.h", ""}, + {"include/adxintrin.h", ""}, + {"include/ammintrin.h", ""}, + {"include/avx2intrin.h", ""}, + {"include/avx512bwintrin.h", ""}, + {"include/avx512cdintrin.h", ""}, + {"include/avx512dqintrin.h", ""}, + {"include/avx512erintrin.h", ""}, + {"include/avx512fintrin.h", ""}, + {"include/avx512ifmaintrin.h", ""}, + {"include/avx512ifmavlintrin.h", ""}, + {"include/avx512pfintrin.h", ""}, + {"include/avx512vbmiintrin.h", ""}, + {"include/avx512vbmivlintrin.h", ""}, + {"include/avx512vlbwintrin.h", ""}, + {"include/avx512vlcdintrin.h", ""}, + {"include/avx512vldqintrin.h", ""}, + {"include/avx512vlintrin.h", ""}, + {"include/avxintrin.h", ""}, + {"include/bmi2intrin.h", ""}, + {"include/bmiintrin.h", ""}, + {"include/emmintrin.h", ""}, + {"include/f16cintrin.h", ""}, + {"include/float.h", ""}, + {"include/fma4intrin.h", ""}, + {"include/fmaintrin.h", ""}, + {"include/fxsrintrin.h", ""}, + {"include/ia32intrin.h", ""}, + {"include/immintrin.h", ""}, + {"include/inttypes.h", ""}, + {"include/limits.h", ""}, + {"include/lzcntintrin.h", ""}, + {"include/mm3dnow.h", ""}, + {"include/mm_malloc.h", ""}, + {"include/mmintrin.h", ""}, + {"include/mwaitxintrin.h", ""}, + {"include/pkuintrin.h", ""}, + {"include/pmmintrin.h", ""}, + {"include/popcntintrin.h", ""}, + {"include/prfchwintrin.h", ""}, + {"include/rdseedintrin.h", ""}, + {"include/rtmintrin.h", ""}, + {"include/shaintrin.h", ""}, + {"include/smmintrin.h", ""}, + {"include/stdalign.h", ""}, + {"include/stdarg.h", ""}, + {"include/stdbool.h", ""}, + {"include/stddef.h", ""}, + {"include/stdint.h", ""}, + {"include/tbmintrin.h", ""}, + {"include/tmmintrin.h", ""}, + {"include/wmmintrin.h", ""}, + {"include/x86intrin.h", ""}, + {"include/xmmintrin.h", ""}, + {"include/xopintrin.h", ""}, + {"include/xsavecintrin.h", ""}, + {"include/xsaveintrin.h", ""}, + {"include/xsaveoptintrin.h", ""}, + {"include/xsavesintrin.h", ""}, + {"include/xtestintrin.h", ""}, + {"include/_G_config.h", ""}, + {"include/assert.h", ""}, + {"algorithm", ""}, + {"valarray", ""}, + {"array", ""}, + {"atomic", ""}, + {"backward/auto_ptr.h", ""}, + {"backward/binders.h", ""}, + {"bits/algorithmfwd.h", ""}, + {"bits/alloc_traits.h", ""}, + {"bits/allocated_ptr.h", ""}, + {"bits/allocator.h", ""}, + {"bits/atomic_base.h", ""}, + {"bits/atomic_lockfree_defines.h", ""}, + {"bits/atomic_futex.h", ""}, + {"bits/basic_ios.h", ""}, + {"bits/basic_ios.tcc", ""}, + {"bits/basic_string.h", ""}, + {"bits/basic_string.tcc", ""}, + {"bits/char_traits.h", ""}, + {"bits/codecvt.h", ""}, + {"bits/concept_check.h", ""}, + {"bits/cpp_type_traits.h", ""}, + {"bits/cxxabi_forced.h", ""}, + {"bits/deque.tcc", ""}, + {"bits/exception.h", ""}, + {"bits/exception_defines.h", ""}, + {"bits/exception_ptr.h", ""}, + {"bits/forward_list.h", ""}, + {"bits/forward_list.tcc", ""}, + {"bits/fstream.tcc", ""}, + {"bits/functexcept.h", ""}, + {"bits/functional_hash.h", ""}, + {"bits/gslice.h", ""}, + {"bits/gslice_array.h", ""}, + {"bits/hash_bytes.h", ""}, + {"bits/hashtable.h", ""}, + {"bits/hashtable_policy.h", ""}, + {"bits/indirect_array.h", ""}, + {"bits/invoke.h", ""}, + {"bits/ios_base.h", ""}, + {"bits/istream.tcc", ""}, + {"bits/list.tcc", ""}, + {"bits/locale_classes.h", ""}, + {"bits/locale_classes.tcc", ""}, + {"bits/locale_conv.h", ""}, + {"bits/locale_facets.h", ""}, + {"bits/locale_facets.tcc", ""}, + {"bits/locale_facets_nonio.h", ""}, + {"bits/locale_facets_nonio.tcc", ""}, + {"bits/localefwd.h", ""}, + {"bits/mask_array.h", ""}, + {"bits/memoryfwd.h", ""}, + {"bits/move.h", ""}, + {"bits/nested_exception.h", ""}, + {"bits/ostream.tcc", ""}, + {"bits/ostream_insert.h", ""}, + {"bits/parse_numbers.h", ""}, + {"bits/postypes.h", ""}, + {"bits/predefined_ops.h", ""}, + {"bits/ptr_traits.h", ""}, + {"bits/quoted_string.h", ""}, + {"bits/random.h", ""}, + {"bits/random.tcc", ""}, + {"bits/range_access.h", ""}, + {"bits/refwrap.h", ""}, + {"bits/regex.h", ""}, + {"bits/regex_automaton.h", ""}, + {"bits/regex_compiler.h", ""}, + {"bits/regex_constants.h", ""}, + {"bits/regex_cursor.h", ""}, + {"bits/regex_error.h", ""}, + {"bits/regex_executor.h", ""}, + {"bits/regex_grep_matcher.h", ""}, + {"bits/regex_grep_matcher.tcc", ""}, + {"bits/regex_nfa.h", ""}, + {"bits/regex_scanner.h", ""}, + {"bits/shared_ptr.h", ""}, + {"bits/shared_ptr_base.h", ""}, + {"bits/shared_ptr_atomic.h", ""}, + {"bits/slice_array.h", ""}, + {"bits/sstream.tcc", ""}, + {"bits/std_abs.h", ""}, + {"bits/std_function.h", ""}, + {"bits/std_mutex.h", ""}, + {"bits/stl_algo.h", ""}, + {"bits/stl_algobase.h", ""}, + {"bits/stl_bvector.h", ""}, + {"bits/stl_construct.h", ""}, + {"bits/stl_deque.h", ""}, + {"bits/stl_function.h", ""}, + {"bits/stl_heap.h", ""}, + {"bits/stl_iterator.h", ""}, + {"bits/stl_iterator_base_funcs.h", ""}, + {"bits/stl_iterator_base_types.h", ""}, + {"bits/stl_list.h", ""}, + {"bits/stl_map.h", ""}, + {"bits/stl_multimap.h", ""}, + {"bits/stl_multiset.h", ""}, + {"bits/stl_numeric.h", ""}, + {"bits/stl_pair.h", ""}, + {"bits/stl_queue.h", ""}, + {"bits/stl_raw_storage_iter.h", ""}, + {"bits/stl_relops.h", ""}, + {"bits/stl_set.h", ""}, + {"bits/stl_stack.h", ""}, + {"bits/stl_tempbuf.h", ""}, + {"bits/stl_tree.h", ""}, + {"bits/stl_uninitialized.h", ""}, + {"bits/stl_vector.h", ""}, + {"bits/stream_iterator.h", ""}, + {"bits/streambuf.tcc", ""}, + {"bits/streambuf_iterator.h", ""}, + {"bits/stringfwd.h", ""}, + {"bits/uniform_int_dist.h", ""}, + {"bits/unique_ptr.h", ""}, + {"bits/unordered_map.h", ""}, + {"bits/unordered_set.h", ""}, + {"bits/uses_allocator.h", ""}, + {"bits/valarray_after.h", ""}, + {"bits/valarray_array.h", ""}, + {"bits/valarray_array.tcc", ""}, + {"bits/valarray_before.h", ""}, + {"bits/vector.tcc", ""}, + {"bitset", ""}, + {"ccomplex", ""}, + {"cctype", ""}, + {"cerrno", ""}, + {"cfenv", ""}, + {"cfloat", ""}, + {"chrono", ""}, + {"cinttypes", ""}, + {"climits", ""}, + {"clocale", ""}, + {"cmath", ""}, + {"complex", ""}, + {"complex.h", ""}, + {"condition_variable", ""}, + {"csetjmp", ""}, + {"csignal", ""}, + {"cstdalign", ""}, + {"cstdarg", ""}, + {"cstdbool", ""}, + {"cstdint", ""}, + {"cstdio", ""}, + {"cstdlib", ""}, + {"cstring", ""}, + {"ctgmath", ""}, + {"ctime", ""}, + {"cwchar", ""}, + {"cwctype", ""}, + {"cxxabi.h", ""}, + {"debug/debug.h", ""}, + {"debug/map.h", ""}, + {"debug/multimap.h", ""}, + {"debug/multiset.h", ""}, + {"debug/set.h", ""}, + {"deque", ""}, + {"exception", ""}, + {"ext/alloc_traits.h", ""}, + {"ext/atomicity.h", ""}, + {"ext/concurrence.h", ""}, + {"ext/new_allocator.h", ""}, + {"ext/numeric_traits.h", ""}, + {"ext/string_conversions.h", ""}, + {"ext/type_traits.h", ""}, + {"fenv.h", ""}, + {"forward_list", ""}, + {"fstream", ""}, + {"functional", ""}, + {"future", ""}, + {"initializer_list", ""}, + {"iomanip", ""}, + {"ios", ""}, + {"iosfwd", ""}, + {"iostream", ""}, + {"istream", ""}, + {"iterator", ""}, + {"limits", ""}, + {"list", ""}, + {"locale", ""}, + {"map", ""}, + {"memory", ""}, + {"shared_mutex", ""}, + {"mutex", ""}, + {"new", ""}, + {"numeric", ""}, + {"ostream", ""}, + {"queue", ""}, + {"random", ""}, + {"ratio", ""}, + {"regex", ""}, + {"scoped_allocator", ""}, + {"set", ""}, + {"sstream", ""}, + {"stack", ""}, + {"stdexcept", ""}, + {"streambuf", ""}, + {"string", ""}, + {"system_error", ""}, + {"tgmath.h", ""}, + {"thread", ""}, + {"tuple", ""}, + {"type_traits", ""}, + {"typeindex", ""}, + {"typeinfo", ""}, + {"unordered_map", ""}, + {"unordered_set", ""}, + {"utility", ""}, + {"vector", ""}, + {"include/complex.h", ""}, + {"include/ctype.h", ""}, + {"include/errno.h", ""}, + {"include/fenv.h", ""}, + {"include/libio.h", ""}, + {"include/locale.h", ""}, + {"include/math.h", ""}, + {"include/setjmp.h", ""}, + {"include/signal.h", ""}, + {"include/stdio.h", ""}, + {"include/stdlib.h", ""}, + {"include/string.h", ""}, + {"include/time.h", ""}, + {"include/wchar.h", ""}, + {"include/wctype.h", ""}, + {"bits/cmathcalls.h", ""}, + {"bits/errno.h", ""}, + {"bits/fenv.h", ""}, + {"bits/huge_val.h", ""}, + {"bits/huge_valf.h", ""}, + {"bits/huge_vall.h", ""}, + {"bits/inf.h", ""}, + {"bits/local_lim.h", ""}, + {"bits/locale.h", ""}, + {"bits/mathcalls.h", ""}, + {"bits/mathdef.h", ""}, + {"bits/nan.h", ""}, + {"bits/posix1_lim.h", ""}, + {"bits/posix2_lim.h", ""}, + {"bits/setjmp.h", ""}, + {"bits/sigaction.h", ""}, + {"bits/sigcontext.h", ""}, + {"bits/siginfo.h", ""}, + {"bits/signum.h", ""}, + {"bits/sigset.h", ""}, + {"bits/sigstack.h", ""}, + {"bits/stdint-intn.h", ""}, + {"bits/stdint-uintn.h", ""}, + {"bits/stdio_lim.h", ""}, + {"bits/sys_errlist.h", ""}, + {"bits/time.h", ""}, + {"bits/timex.h", ""}, + {"bits/typesizes.h", ""}, + {"bits/wchar.h", ""}, + {"bits/wordsize.h", ""}, + {"bits/xopen_lim.h", ""}, + {"include/xlocale.h", ""}, + {"bits/atomic_word.h", ""}, + {"bits/basic_file.h", ""}, + {"bits/c\\+\\+allocator.h", ""}, + {"bits/c\\+\\+config.h", ""}, + {"bits/c\\+\\+io.h", ""}, + {"bits/c\\+\\+locale.h", ""}, + {"bits/cpu_defines.h", ""}, + {"bits/ctype_base.h", ""}, + {"bits/cxxabi_tweaks.h", ""}, + {"bits/error_constants.h", ""}, + {"bits/gthr-default.h", ""}, + {"bits/gthr.h", ""}, + {"bits/opt_random.h", ""}, + {"bits/os_defines.h", ""}, + // GNU C headers + {"include/aio.h", ""}, + {"include/aliases.h", ""}, + {"include/alloca.h", ""}, + {"include/ar.h", ""}, + {"include/argp.h", ""}, + {"include/argz.h", ""}, + {"include/arpa/nameser.h", ""}, + {"include/arpa/nameser_compat.h", ""}, + {"include/byteswap.h", ""}, + {"include/cpio.h", ""}, + {"include/crypt.h", ""}, + {"include/dirent.h", ""}, + {"include/dlfcn.h", ""}, + {"include/elf.h", ""}, + {"include/endian.h", ""}, + {"include/envz.h", ""}, + {"include/err.h", ""}, + {"include/error.h", ""}, + {"include/execinfo.h", ""}, + {"include/fcntl.h", ""}, + {"include/features.h", ""}, + {"include/fmtmsg.h", ""}, + {"include/fnmatch.h", ""}, + {"include/fstab.h", ""}, + {"include/fts.h", ""}, + {"include/ftw.h", ""}, + {"include/gconv.h", ""}, + {"include/getopt.h", ""}, + {"include/glob.h", ""}, + {"include/grp.h", ""}, + {"include/gshadow.h", ""}, + {"include/iconv.h", ""}, + {"include/ifaddrs.h", ""}, + {"include/kdb.h", ""}, + {"include/langinfo.h", ""}, + {"include/libgen.h", ""}, + {"include/libintl.h", ""}, + {"include/link.h", ""}, + {"include/malloc.h", ""}, + {"include/mcheck.h", ""}, + {"include/memory.h", ""}, + {"include/mntent.h", ""}, + {"include/monetary.h", ""}, + {"include/mqueue.h", ""}, + {"include/netdb.h", ""}, + {"include/netinet/in.h", ""}, + {"include/nl_types.h", ""}, + {"include/nss.h", ""}, + {"include/obstack.h", ""}, + {"include/panel.h", ""}, + {"include/paths.h", ""}, + {"include/printf.h", ""}, + {"include/profile.h", ""}, + {"include/pthread.h", ""}, + {"include/pty.h", ""}, + {"include/pwd.h", ""}, + {"include/re_comp.h", ""}, + {"include/regex.h", ""}, + {"include/regexp.h", ""}, + {"include/resolv.h", ""}, + {"include/rpc/netdb.h", ""}, + {"include/sched.h", ""}, + {"include/search.h", ""}, + {"include/semaphore.h", ""}, + {"include/sgtty.h", ""}, + {"include/shadow.h", ""}, + {"include/spawn.h", ""}, + {"include/stab.h", ""}, + {"include/stdc-predef.h", ""}, + {"include/stdio_ext.h", ""}, + {"include/strings.h", ""}, + {"include/stropts.h", ""}, + {"include/sudo_plugin.h", ""}, + {"include/sysexits.h", ""}, + {"include/tar.h", ""}, + {"include/tcpd.h", ""}, + {"include/term.h", ""}, + {"include/term_entry.h", ""}, + {"include/termcap.h", ""}, + {"include/termios.h", ""}, + {"include/thread_db.h", ""}, + {"include/tic.h", ""}, + {"include/ttyent.h", ""}, + {"include/uchar.h", ""}, + {"include/ucontext.h", ""}, + {"include/ulimit.h", ""}, + {"include/unctrl.h", ""}, + {"include/unistd.h", ""}, + {"include/utime.h", ""}, + {"include/utmp.h", ""}, + {"include/utmpx.h", ""}, + {"include/values.h", ""}, + {"include/wordexp.h", ""}, + {"fpu_control.h", ""}, + {"ieee754.h", ""}, + {"gnu/lib-names.h", ""}, + {"gnu/libc-version.h", ""}, + {"gnu/option-groups.h", ""}, + {"gnu/stubs-32.h", ""}, + {"gnu/stubs-64.h", ""}, + {"gnu/stubs-x32.h", ""}, + {"include/rpc/auth_des.h", ""}, + {"include/rpc/rpc_msg.h", ""}, + {"include/rpc/pmap_clnt.h", ""}, + {"include/rpc/rpc.h", ""}, + {"include/rpc/types.h", ""}, + {"include/rpc/auth_unix.h", ""}, + {"include/rpc/key_prot.h", ""}, + {"include/rpc/pmap_prot.h", ""}, + {"include/rpc/auth.h", ""}, + {"include/rpc/svc_auth.h", ""}, + {"include/rpc/xdr.h", ""}, + {"include/rpc/pmap_rmt.h", ""}, + {"include/rpc/des_crypt.h", ""}, + {"include/rpc/svc.h", ""}, + {"include/rpc/rpc_des.h", ""}, + {"include/rpc/clnt.h", ""}, + {"include/scsi/scsi.h", ""}, + {"include/scsi/sg.h", ""}, + {"include/scsi/scsi_ioctl.h", ""}, + {"include/netrose/rose.h", ""}, + {"include/nfs/nfs.h", ""}, + {"include/netatalk/at.h", ""}, + {"include/netinet/ether.h", ""}, + {"include/netinet/icmp6.h", ""}, + {"include/netinet/if_ether.h", ""}, + {"include/netinet/if_fddi.h", ""}, + {"include/netinet/if_tr.h", ""}, + {"include/netinet/igmp.h", ""}, + {"include/netinet/in_systm.h", ""}, + {"include/netinet/ip.h", ""}, + {"include/netinet/ip6.h", ""}, + {"include/netinet/ip_icmp.h", ""}, + {"include/netinet/tcp.h", ""}, + {"include/netinet/udp.h", ""}, + {"include/netrom/netrom.h", ""}, + {"include/protocols/routed.h", ""}, + {"include/protocols/rwhod.h", ""}, + {"include/protocols/talkd.h", ""}, + {"include/protocols/timed.h", ""}, + {"include/rpcsvc/klm_prot.x", ""}, + {"include/rpcsvc/rstat.h", ""}, + {"include/rpcsvc/spray.x", ""}, + {"include/rpcsvc/nlm_prot.x", ""}, + {"include/rpcsvc/nis_callback.x", ""}, + {"include/rpcsvc/yp.h", ""}, + {"include/rpcsvc/yp.x", ""}, + {"include/rpcsvc/nfs_prot.h", ""}, + {"include/rpcsvc/rex.h", ""}, + {"include/rpcsvc/yppasswd.h", ""}, + {"include/rpcsvc/rex.x", ""}, + {"include/rpcsvc/nis_tags.h", ""}, + {"include/rpcsvc/nis_callback.h", ""}, + {"include/rpcsvc/nfs_prot.x", ""}, + {"include/rpcsvc/bootparam_prot.x", ""}, + {"include/rpcsvc/rusers.x", ""}, + {"include/rpcsvc/rquota.x", ""}, + {"include/rpcsvc/nis.h", ""}, + {"include/rpcsvc/nislib.h", ""}, + {"include/rpcsvc/ypupd.h", ""}, + {"include/rpcsvc/bootparam.h", ""}, + {"include/rpcsvc/spray.h", ""}, + {"include/rpcsvc/key_prot.h", ""}, + {"include/rpcsvc/klm_prot.h", ""}, + {"include/rpcsvc/sm_inter.h", ""}, + {"include/rpcsvc/nlm_prot.h", ""}, + {"include/rpcsvc/yp_prot.h", ""}, + {"include/rpcsvc/ypclnt.h", ""}, + {"include/rpcsvc/rstat.x", ""}, + {"include/rpcsvc/rusers.h", ""}, + {"include/rpcsvc/key_prot.x", ""}, + {"include/rpcsvc/sm_inter.x", ""}, + {"include/rpcsvc/rquota.h", ""}, + {"include/rpcsvc/nis.x", ""}, + {"include/rpcsvc/bootparam_prot.h", ""}, + {"include/rpcsvc/mount.h", ""}, + {"include/rpcsvc/mount.x", ""}, + {"include/rpcsvc/nis_object.x", ""}, + {"include/rpcsvc/yppasswd.x", ""}, + {"sys/acct.h", ""}, + {"sys/auxv.h", ""}, + {"sys/cdefs.h", ""}, + {"sys/debugreg.h", ""}, + {"sys/dir.h", ""}, + {"sys/elf.h", ""}, + {"sys/epoll.h", ""}, + {"sys/eventfd.h", ""}, + {"sys/fanotify.h", ""}, + {"sys/file.h", ""}, + {"sys/fsuid.h", ""}, + {"sys/gmon.h", ""}, + {"sys/gmon_out.h", ""}, + {"sys/inotify.h", ""}, + {"sys/io.h", ""}, + {"sys/ioctl.h", ""}, + {"sys/ipc.h", ""}, + {"sys/kd.h", ""}, + {"sys/kdaemon.h", ""}, + {"sys/klog.h", ""}, + {"sys/mman.h", ""}, + {"sys/mount.h", ""}, + {"sys/msg.h", ""}, + {"sys/mtio.h", ""}, + {"sys/param.h", ""}, + {"sys/pci.h", ""}, + {"sys/perm.h", ""}, + {"sys/personality.h", ""}, + {"sys/poll.h", ""}, + {"sys/prctl.h", ""}, + {"sys/procfs.h", ""}, + {"sys/profil.h", ""}, + {"sys/ptrace.h", ""}, + {"sys/queue.h", ""}, + {"sys/quota.h", ""}, + {"sys/raw.h", ""}, + {"sys/reboot.h", ""}, + {"sys/reg.h", ""}, + {"sys/resource.h", ""}, + {"sys/select.h", ""}, + {"sys/sem.h", ""}, + {"sys/sendfile.h", ""}, + {"sys/shm.h", ""}, + {"sys/signalfd.h", ""}, + {"sys/socket.h", ""}, + {"sys/stat.h", ""}, + {"sys/statfs.h", ""}, + {"sys/statvfs.h", ""}, + {"sys/swap.h", ""}, + {"sys/syscall.h", ""}, + {"sys/sysctl.h", ""}, + {"sys/sysinfo.h", ""}, + {"sys/syslog.h", ""}, + {"sys/sysmacros.h", ""}, + {"sys/termios.h", ""}, + {"sys/time.h", ""}, + {"sys/timeb.h", ""}, + {"sys/timerfd.h", ""}, + {"sys/times.h", ""}, + {"sys/timex.h", ""}, + {"sys/ttychars.h", ""}, + {"sys/ttydefaults.h", ""}, + {"sys/types.h", ""}, + {"sys/ucontext.h", ""}, + {"sys/uio.h", ""}, + {"sys/un.h", ""}, + {"sys/user.h", ""}, + {"sys/ustat.h", ""}, + {"sys/utsname.h", ""}, + {"sys/vlimit.h", ""}, + {"sys/vm86.h", ""}, + {"sys/vtimes.h", ""}, + {"sys/wait.h", ""}, + {"sys/xattr.h", ""}, + {"bits/epoll.h", ""}, + {"bits/eventfd.h", ""}, + {"bits/inotify.h", ""}, + {"bits/ipc.h", ""}, + {"bits/ipctypes.h", ""}, + {"bits/mman-linux.h", ""}, + {"bits/mman.h", ""}, + {"bits/msq.h", ""}, + {"bits/resource.h", ""}, + {"bits/sem.h", ""}, + {"bits/shm.h", ""}, + {"bits/signalfd.h", ""}, + {"bits/statfs.h", ""}, + {"bits/statvfs.h", ""}, + {"bits/timerfd.h", ""}, + {"bits/utsname.h", ""}, + {"bits/auxv.h", ""}, + {"bits/byteswap-16.h", ""}, + {"bits/byteswap.h", ""}, + {"bits/confname.h", ""}, + {"bits/dirent.h", ""}, + {"bits/dlfcn.h", ""}, + {"bits/elfclass.h", ""}, + {"bits/endian.h", ""}, + {"bits/environments.h", ""}, + {"bits/fcntl-linux.h", ""}, + {"bits/fcntl.h", ""}, + {"bits/in.h", ""}, + {"bits/ioctl-types.h", ""}, + {"bits/ioctls.h", ""}, + {"bits/link.h", ""}, + {"bits/mqueue.h", ""}, + {"bits/netdb.h", ""}, + {"bits/param.h", ""}, + {"bits/poll.h", ""}, + {"bits/posix_opt.h", ""}, + {"bits/pthreadtypes.h", ""}, + {"bits/sched.h", ""}, + {"bits/select.h", ""}, + {"bits/semaphore.h", ""}, + {"bits/sigthread.h", ""}, + {"bits/sockaddr.h", ""}, + {"bits/socket.h", ""}, + {"bits/socket_type.h", ""}, + {"bits/stab.def", ""}, + {"bits/stat.h", ""}, + {"bits/stropts.h", ""}, + {"bits/syscall.h", ""}, + {"bits/syslog-path.h", ""}, + {"bits/termios.h", ""}, + {"bits/types.h", ""}, + {"bits/uio.h", ""}, + {"bits/ustat.h", ""}, + {"bits/utmp.h", ""}, + {"bits/utmpx.h", ""}, + {"bits/waitflags.h", ""}, + {"bits/waitstatus.h", ""}, + {"bits/xtitypes.h", ""}, +}; + } // namespace void CanonicalIncludes::addMapping(FileEntryRef Header, @@ -109,661 +758,18 @@ void CanonicalIncludes::addSystemHeadersMapping(const LangOptions &Language) { // FIXME: remove the std header mapping once we support ambiguous symbols, now // it serves as a fallback to disambiguate: // - symbols with multiple headers (e.g. std::move) - static const auto *SystemHeaderMap = new llvm::StringMap({ - {"include/__stddef_max_align_t.h", ""}, - {"include/__wmmintrin_aes.h", ""}, - {"include/__wmmintrin_pclmul.h", ""}, - {"include/adxintrin.h", ""}, - {"include/ammintrin.h", ""}, - {"include/avx2intrin.h", ""}, - {"include/avx512bwintrin.h", ""}, - {"include/avx512cdintrin.h", ""}, - {"include/avx512dqintrin.h", ""}, - {"include/avx512erintrin.h", ""}, - {"include/avx512fintrin.h", ""}, - {"include/avx512ifmaintrin.h", ""}, - {"include/avx512ifmavlintrin.h", ""}, - {"include/avx512pfintrin.h", ""}, - {"include/avx512vbmiintrin.h", ""}, - {"include/avx512vbmivlintrin.h", ""}, - {"include/avx512vlbwintrin.h", ""}, - {"include/avx512vlcdintrin.h", ""}, - {"include/avx512vldqintrin.h", ""}, - {"include/avx512vlintrin.h", ""}, - {"include/avxintrin.h", ""}, - {"include/bmi2intrin.h", ""}, - {"include/bmiintrin.h", ""}, - {"include/emmintrin.h", ""}, - {"include/f16cintrin.h", ""}, - {"include/float.h", ""}, - {"include/fma4intrin.h", ""}, - {"include/fmaintrin.h", ""}, - {"include/fxsrintrin.h", ""}, - {"include/ia32intrin.h", ""}, - {"include/immintrin.h", ""}, - {"include/inttypes.h", ""}, - {"include/limits.h", ""}, - {"include/lzcntintrin.h", ""}, - {"include/mm3dnow.h", ""}, - {"include/mm_malloc.h", ""}, - {"include/mmintrin.h", ""}, - {"include/mwaitxintrin.h", ""}, - {"include/pkuintrin.h", ""}, - {"include/pmmintrin.h", ""}, - {"include/popcntintrin.h", ""}, - {"include/prfchwintrin.h", ""}, - {"include/rdseedintrin.h", ""}, - {"include/rtmintrin.h", ""}, - {"include/shaintrin.h", ""}, - {"include/smmintrin.h", ""}, - {"include/stdalign.h", ""}, - {"include/stdarg.h", ""}, - {"include/stdbool.h", ""}, - {"include/stddef.h", ""}, - {"include/stdint.h", ""}, - {"include/tbmintrin.h", ""}, - {"include/tmmintrin.h", ""}, - {"include/wmmintrin.h", ""}, - {"include/x86intrin.h", ""}, - {"include/xmmintrin.h", ""}, - {"include/xopintrin.h", ""}, - {"include/xsavecintrin.h", ""}, - {"include/xsaveintrin.h", ""}, - {"include/xsaveoptintrin.h", ""}, - {"include/xsavesintrin.h", ""}, - {"include/xtestintrin.h", ""}, - {"include/_G_config.h", ""}, - {"include/assert.h", ""}, - {"algorithm", ""}, - {"valarray", ""}, - {"array", ""}, - {"atomic", ""}, - {"backward/auto_ptr.h", ""}, - {"backward/binders.h", ""}, - {"bits/algorithmfwd.h", ""}, - {"bits/alloc_traits.h", ""}, - {"bits/allocated_ptr.h", ""}, - {"bits/allocator.h", ""}, - {"bits/atomic_base.h", ""}, - {"bits/atomic_lockfree_defines.h", ""}, - {"bits/atomic_futex.h", ""}, - {"bits/basic_ios.h", ""}, - {"bits/basic_ios.tcc", ""}, - {"bits/basic_string.h", ""}, - {"bits/basic_string.tcc", ""}, - {"bits/char_traits.h", ""}, - {"bits/codecvt.h", ""}, - {"bits/concept_check.h", ""}, - {"bits/cpp_type_traits.h", ""}, - {"bits/cxxabi_forced.h", ""}, - {"bits/deque.tcc", ""}, - {"bits/exception.h", ""}, - {"bits/exception_defines.h", ""}, - {"bits/exception_ptr.h", ""}, - {"bits/forward_list.h", ""}, - {"bits/forward_list.tcc", ""}, - {"bits/fstream.tcc", ""}, - {"bits/functexcept.h", ""}, - {"bits/functional_hash.h", ""}, - {"bits/gslice.h", ""}, - {"bits/gslice_array.h", ""}, - {"bits/hash_bytes.h", ""}, - {"bits/hashtable.h", ""}, - {"bits/hashtable_policy.h", ""}, - {"bits/indirect_array.h", ""}, - {"bits/invoke.h", ""}, - {"bits/ios_base.h", ""}, - {"bits/istream.tcc", ""}, - {"bits/list.tcc", ""}, - {"bits/locale_classes.h", ""}, - {"bits/locale_classes.tcc", ""}, - {"bits/locale_conv.h", ""}, - {"bits/locale_facets.h", ""}, - {"bits/locale_facets.tcc", ""}, - {"bits/locale_facets_nonio.h", ""}, - {"bits/locale_facets_nonio.tcc", ""}, - {"bits/localefwd.h", ""}, - {"bits/mask_array.h", ""}, - {"bits/memoryfwd.h", ""}, - {"bits/move.h", ""}, - {"bits/nested_exception.h", ""}, - {"bits/ostream.tcc", ""}, - {"bits/ostream_insert.h", ""}, - {"bits/parse_numbers.h", ""}, - {"bits/postypes.h", ""}, - {"bits/predefined_ops.h", ""}, - {"bits/ptr_traits.h", ""}, - {"bits/quoted_string.h", ""}, - {"bits/random.h", ""}, - {"bits/random.tcc", ""}, - {"bits/range_access.h", ""}, - {"bits/refwrap.h", ""}, - {"bits/regex.h", ""}, - {"bits/regex_automaton.h", ""}, - {"bits/regex_compiler.h", ""}, - {"bits/regex_constants.h", ""}, - {"bits/regex_cursor.h", ""}, - {"bits/regex_error.h", ""}, - {"bits/regex_executor.h", ""}, - {"bits/regex_grep_matcher.h", ""}, - {"bits/regex_grep_matcher.tcc", ""}, - {"bits/regex_nfa.h", ""}, - {"bits/regex_scanner.h", ""}, - {"bits/shared_ptr.h", ""}, - {"bits/shared_ptr_base.h", ""}, - {"bits/shared_ptr_atomic.h", ""}, - {"bits/slice_array.h", ""}, - {"bits/sstream.tcc", ""}, - {"bits/std_abs.h", ""}, - {"bits/std_function.h", ""}, - {"bits/std_mutex.h", ""}, - {"bits/stl_algo.h", ""}, - {"bits/stl_algobase.h", ""}, - {"bits/stl_bvector.h", ""}, - {"bits/stl_construct.h", ""}, - {"bits/stl_deque.h", ""}, - {"bits/stl_function.h", ""}, - {"bits/stl_heap.h", ""}, - {"bits/stl_iterator.h", ""}, - {"bits/stl_iterator_base_funcs.h", ""}, - {"bits/stl_iterator_base_types.h", ""}, - {"bits/stl_list.h", ""}, - {"bits/stl_map.h", ""}, - {"bits/stl_multimap.h", ""}, - {"bits/stl_multiset.h", ""}, - {"bits/stl_numeric.h", ""}, - {"bits/stl_pair.h", ""}, - {"bits/stl_queue.h", ""}, - {"bits/stl_raw_storage_iter.h", ""}, - {"bits/stl_relops.h", ""}, - {"bits/stl_set.h", ""}, - {"bits/stl_stack.h", ""}, - {"bits/stl_tempbuf.h", ""}, - {"bits/stl_tree.h", ""}, - {"bits/stl_uninitialized.h", ""}, - {"bits/stl_vector.h", ""}, - {"bits/stream_iterator.h", ""}, - {"bits/streambuf.tcc", ""}, - {"bits/streambuf_iterator.h", ""}, - {"bits/stringfwd.h", ""}, - {"bits/uniform_int_dist.h", ""}, - {"bits/unique_ptr.h", ""}, - {"bits/unordered_map.h", ""}, - {"bits/unordered_set.h", ""}, - {"bits/uses_allocator.h", ""}, - {"bits/valarray_after.h", ""}, - {"bits/valarray_array.h", ""}, - {"bits/valarray_array.tcc", ""}, - {"bits/valarray_before.h", ""}, - {"bits/vector.tcc", ""}, - {"bitset", ""}, - {"ccomplex", ""}, - {"cctype", ""}, - {"cerrno", ""}, - {"cfenv", ""}, - {"cfloat", ""}, - {"chrono", ""}, - {"cinttypes", ""}, - {"climits", ""}, - {"clocale", ""}, - {"cmath", ""}, - {"complex", ""}, - {"complex.h", ""}, - {"condition_variable", ""}, - {"csetjmp", ""}, - {"csignal", ""}, - {"cstdalign", ""}, - {"cstdarg", ""}, - {"cstdbool", ""}, - {"cstdint", ""}, - {"cstdio", ""}, - {"cstdlib", ""}, - {"cstring", ""}, - {"ctgmath", ""}, - {"ctime", ""}, - {"cwchar", ""}, - {"cwctype", ""}, - {"cxxabi.h", ""}, - {"debug/debug.h", ""}, - {"debug/map.h", ""}, - {"debug/multimap.h", ""}, - {"debug/multiset.h", ""}, - {"debug/set.h", ""}, - {"deque", ""}, - {"exception", ""}, - {"ext/alloc_traits.h", ""}, - {"ext/atomicity.h", ""}, - {"ext/concurrence.h", ""}, - {"ext/new_allocator.h", ""}, - {"ext/numeric_traits.h", ""}, - {"ext/string_conversions.h", ""}, - {"ext/type_traits.h", ""}, - {"fenv.h", ""}, - {"forward_list", ""}, - {"fstream", ""}, - {"functional", ""}, - {"future", ""}, - {"initializer_list", ""}, - {"iomanip", ""}, - {"ios", ""}, - {"iosfwd", ""}, - {"iostream", ""}, - {"istream", ""}, - {"iterator", ""}, - {"limits", ""}, - {"list", ""}, - {"locale", ""}, - {"map", ""}, - {"memory", ""}, - {"shared_mutex", ""}, - {"mutex", ""}, - {"new", ""}, - {"numeric", ""}, - {"ostream", ""}, - {"queue", ""}, - {"random", ""}, - {"ratio", ""}, - {"regex", ""}, - {"scoped_allocator", ""}, - {"set", ""}, - {"sstream", ""}, - {"stack", ""}, - {"stdexcept", ""}, - {"streambuf", ""}, - {"string", ""}, - {"system_error", ""}, - {"tgmath.h", ""}, - {"thread", ""}, - {"tuple", ""}, - {"type_traits", ""}, - {"typeindex", ""}, - {"typeinfo", ""}, - {"unordered_map", ""}, - {"unordered_set", ""}, - {"utility", ""}, - {"valarray", ""}, - {"vector", ""}, - {"include/complex.h", ""}, - {"include/ctype.h", ""}, - {"include/errno.h", ""}, - {"include/fenv.h", ""}, - {"include/inttypes.h", ""}, - {"include/libio.h", ""}, - {"include/limits.h", ""}, - {"include/locale.h", ""}, - {"include/math.h", ""}, - {"include/setjmp.h", ""}, - {"include/signal.h", ""}, - {"include/stdint.h", ""}, - {"include/stdio.h", ""}, - {"include/stdlib.h", ""}, - {"include/string.h", ""}, - {"include/time.h", ""}, - {"include/wchar.h", ""}, - {"include/wctype.h", ""}, - {"bits/cmathcalls.h", ""}, - {"bits/errno.h", ""}, - {"bits/fenv.h", ""}, - {"bits/huge_val.h", ""}, - {"bits/huge_valf.h", ""}, - {"bits/huge_vall.h", ""}, - {"bits/inf.h", ""}, - {"bits/local_lim.h", ""}, - {"bits/locale.h", ""}, - {"bits/mathcalls.h", ""}, - {"bits/mathdef.h", ""}, - {"bits/nan.h", ""}, - {"bits/posix1_lim.h", ""}, - {"bits/posix2_lim.h", ""}, - {"bits/setjmp.h", ""}, - {"bits/sigaction.h", ""}, - {"bits/sigcontext.h", ""}, - {"bits/siginfo.h", ""}, - {"bits/signum.h", ""}, - {"bits/sigset.h", ""}, - {"bits/sigstack.h", ""}, - {"bits/stdint-intn.h", ""}, - {"bits/stdint-uintn.h", ""}, - {"bits/stdio_lim.h", ""}, - {"bits/sys_errlist.h", ""}, - {"bits/time.h", ""}, - {"bits/timex.h", ""}, - {"bits/typesizes.h", ""}, - {"bits/wchar.h", ""}, - {"bits/wordsize.h", ""}, - {"bits/xopen_lim.h", ""}, - {"include/xlocale.h", ""}, - {"bits/atomic_word.h", ""}, - {"bits/basic_file.h", ""}, - {"bits/c\\+\\+allocator.h", ""}, - {"bits/c\\+\\+config.h", ""}, - {"bits/c\\+\\+io.h", ""}, - {"bits/c\\+\\+locale.h", ""}, - {"bits/cpu_defines.h", ""}, - {"bits/ctype_base.h", ""}, - {"bits/cxxabi_tweaks.h", ""}, - {"bits/error_constants.h", ""}, - {"bits/gthr-default.h", ""}, - {"bits/gthr.h", ""}, - {"bits/opt_random.h", ""}, - {"bits/os_defines.h", ""}, - // GNU C headers - {"include/aio.h", ""}, - {"include/aliases.h", ""}, - {"include/alloca.h", ""}, - {"include/ar.h", ""}, - {"include/argp.h", ""}, - {"include/argz.h", ""}, - {"include/arpa/nameser.h", ""}, - {"include/arpa/nameser_compat.h", ""}, - {"include/byteswap.h", ""}, - {"include/cpio.h", ""}, - {"include/crypt.h", ""}, - {"include/dirent.h", ""}, - {"include/dlfcn.h", ""}, - {"include/elf.h", ""}, - {"include/endian.h", ""}, - {"include/envz.h", ""}, - {"include/err.h", ""}, - {"include/error.h", ""}, - {"include/execinfo.h", ""}, - {"include/fcntl.h", ""}, - {"include/features.h", ""}, - {"include/fenv.h", ""}, - {"include/fmtmsg.h", ""}, - {"include/fnmatch.h", ""}, - {"include/fstab.h", ""}, - {"include/fts.h", ""}, - {"include/ftw.h", ""}, - {"include/gconv.h", ""}, - {"include/getopt.h", ""}, - {"include/glob.h", ""}, - {"include/grp.h", ""}, - {"include/gshadow.h", ""}, - {"include/iconv.h", ""}, - {"include/ifaddrs.h", ""}, - {"include/kdb.h", ""}, - {"include/langinfo.h", ""}, - {"include/libgen.h", ""}, - {"include/libintl.h", ""}, - {"include/link.h", ""}, - {"include/malloc.h", ""}, - {"include/mcheck.h", ""}, - {"include/memory.h", ""}, - {"include/mntent.h", ""}, - {"include/monetary.h", ""}, - {"include/mqueue.h", ""}, - {"include/netdb.h", ""}, - {"include/netinet/in.h", ""}, - {"include/nl_types.h", ""}, - {"include/nss.h", ""}, - {"include/obstack.h", ""}, - {"include/panel.h", ""}, - {"include/paths.h", ""}, - {"include/printf.h", ""}, - {"include/profile.h", ""}, - {"include/pthread.h", ""}, - {"include/pty.h", ""}, - {"include/pwd.h", ""}, - {"include/re_comp.h", ""}, - {"include/regex.h", ""}, - {"include/regexp.h", ""}, - {"include/resolv.h", ""}, - {"include/rpc/netdb.h", ""}, - {"include/sched.h", ""}, - {"include/search.h", ""}, - {"include/semaphore.h", ""}, - {"include/sgtty.h", ""}, - {"include/shadow.h", ""}, - {"include/spawn.h", ""}, - {"include/stab.h", ""}, - {"include/stdc-predef.h", ""}, - {"include/stdio_ext.h", ""}, - {"include/strings.h", ""}, - {"include/stropts.h", ""}, - {"include/sudo_plugin.h", ""}, - {"include/sysexits.h", ""}, - {"include/tar.h", ""}, - {"include/tcpd.h", ""}, - {"include/term.h", ""}, - {"include/term_entry.h", ""}, - {"include/termcap.h", ""}, - {"include/termios.h", ""}, - {"include/thread_db.h", ""}, - {"include/tic.h", ""}, - {"include/ttyent.h", ""}, - {"include/uchar.h", ""}, - {"include/ucontext.h", ""}, - {"include/ulimit.h", ""}, - {"include/unctrl.h", ""}, - {"include/unistd.h", ""}, - {"include/utime.h", ""}, - {"include/utmp.h", ""}, - {"include/utmpx.h", ""}, - {"include/values.h", ""}, - {"include/wordexp.h", ""}, - {"fpu_control.h", ""}, - {"ieee754.h", ""}, - {"include/xlocale.h", ""}, - {"gnu/lib-names.h", ""}, - {"gnu/libc-version.h", ""}, - {"gnu/option-groups.h", ""}, - {"gnu/stubs-32.h", ""}, - {"gnu/stubs-64.h", ""}, - {"gnu/stubs-x32.h", ""}, - {"include/rpc/auth_des.h", ""}, - {"include/rpc/rpc_msg.h", ""}, - {"include/rpc/pmap_clnt.h", ""}, - {"include/rpc/rpc.h", ""}, - {"include/rpc/types.h", ""}, - {"include/rpc/auth_unix.h", ""}, - {"include/rpc/key_prot.h", ""}, - {"include/rpc/pmap_prot.h", ""}, - {"include/rpc/auth.h", ""}, - {"include/rpc/svc_auth.h", ""}, - {"include/rpc/xdr.h", ""}, - {"include/rpc/pmap_rmt.h", ""}, - {"include/rpc/des_crypt.h", ""}, - {"include/rpc/svc.h", ""}, - {"include/rpc/rpc_des.h", ""}, - {"include/rpc/clnt.h", ""}, - {"include/scsi/scsi.h", ""}, - {"include/scsi/sg.h", ""}, - {"include/scsi/scsi_ioctl.h", ""}, - {"include/netrose/rose.h", ""}, - {"include/nfs/nfs.h", ""}, - {"include/netatalk/at.h", ""}, - {"include/netinet/ether.h", ""}, - {"include/netinet/icmp6.h", ""}, - {"include/netinet/if_ether.h", ""}, - {"include/netinet/if_fddi.h", ""}, - {"include/netinet/if_tr.h", ""}, - {"include/netinet/igmp.h", ""}, - {"include/netinet/in.h", ""}, - {"include/netinet/in_systm.h", ""}, - {"include/netinet/ip.h", ""}, - {"include/netinet/ip6.h", ""}, - {"include/netinet/ip_icmp.h", ""}, - {"include/netinet/tcp.h", ""}, - {"include/netinet/udp.h", ""}, - {"include/netrom/netrom.h", ""}, - {"include/protocols/routed.h", ""}, - {"include/protocols/rwhod.h", ""}, - {"include/protocols/talkd.h", ""}, - {"include/protocols/timed.h", ""}, - {"include/rpcsvc/klm_prot.x", ""}, - {"include/rpcsvc/rstat.h", ""}, - {"include/rpcsvc/spray.x", ""}, - {"include/rpcsvc/nlm_prot.x", ""}, - {"include/rpcsvc/nis_callback.x", ""}, - {"include/rpcsvc/yp.h", ""}, - {"include/rpcsvc/yp.x", ""}, - {"include/rpcsvc/nfs_prot.h", ""}, - {"include/rpcsvc/rex.h", ""}, - {"include/rpcsvc/yppasswd.h", ""}, - {"include/rpcsvc/rex.x", ""}, - {"include/rpcsvc/nis_tags.h", ""}, - {"include/rpcsvc/nis_callback.h", ""}, - {"include/rpcsvc/nfs_prot.x", ""}, - {"include/rpcsvc/bootparam_prot.x", ""}, - {"include/rpcsvc/rusers.x", ""}, - {"include/rpcsvc/rquota.x", ""}, - {"include/rpcsvc/nis.h", ""}, - {"include/rpcsvc/nislib.h", ""}, - {"include/rpcsvc/ypupd.h", ""}, - {"include/rpcsvc/bootparam.h", ""}, - {"include/rpcsvc/spray.h", ""}, - {"include/rpcsvc/key_prot.h", ""}, - {"include/rpcsvc/klm_prot.h", ""}, - {"include/rpcsvc/sm_inter.h", ""}, - {"include/rpcsvc/nlm_prot.h", ""}, - {"include/rpcsvc/yp_prot.h", ""}, - {"include/rpcsvc/ypclnt.h", ""}, - {"include/rpcsvc/rstat.x", ""}, - {"include/rpcsvc/rusers.h", ""}, - {"include/rpcsvc/key_prot.x", ""}, - {"include/rpcsvc/sm_inter.x", ""}, - {"include/rpcsvc/rquota.h", ""}, - {"include/rpcsvc/nis.x", ""}, - {"include/rpcsvc/bootparam_prot.h", ""}, - {"include/rpcsvc/mount.h", ""}, - {"include/rpcsvc/mount.x", ""}, - {"include/rpcsvc/nis_object.x", ""}, - {"include/rpcsvc/yppasswd.x", ""}, - {"sys/acct.h", ""}, - {"sys/auxv.h", ""}, - {"sys/cdefs.h", ""}, - {"sys/debugreg.h", ""}, - {"sys/dir.h", ""}, - {"sys/elf.h", ""}, - {"sys/epoll.h", ""}, - {"sys/eventfd.h", ""}, - {"sys/fanotify.h", ""}, - {"sys/file.h", ""}, - {"sys/fsuid.h", ""}, - {"sys/gmon.h", ""}, - {"sys/gmon_out.h", ""}, - {"sys/inotify.h", ""}, - {"sys/io.h", ""}, - {"sys/ioctl.h", ""}, - {"sys/ipc.h", ""}, - {"sys/kd.h", ""}, - {"sys/kdaemon.h", ""}, - {"sys/klog.h", ""}, - {"sys/mman.h", ""}, - {"sys/mount.h", ""}, - {"sys/msg.h", ""}, - {"sys/mtio.h", ""}, - {"sys/param.h", ""}, - {"sys/pci.h", ""}, - {"sys/perm.h", ""}, - {"sys/personality.h", ""}, - {"sys/poll.h", ""}, - {"sys/prctl.h", ""}, - {"sys/procfs.h", ""}, - {"sys/profil.h", ""}, - {"sys/ptrace.h", ""}, - {"sys/queue.h", ""}, - {"sys/quota.h", ""}, - {"sys/raw.h", ""}, - {"sys/reboot.h", ""}, - {"sys/reg.h", ""}, - {"sys/resource.h", ""}, - {"sys/select.h", ""}, - {"sys/sem.h", ""}, - {"sys/sendfile.h", ""}, - {"sys/shm.h", ""}, - {"sys/signalfd.h", ""}, - {"sys/socket.h", ""}, - {"sys/stat.h", ""}, - {"sys/statfs.h", ""}, - {"sys/statvfs.h", ""}, - {"sys/swap.h", ""}, - {"sys/syscall.h", ""}, - {"sys/sysctl.h", ""}, - {"sys/sysinfo.h", ""}, - {"sys/syslog.h", ""}, - {"sys/sysmacros.h", ""}, - {"sys/termios.h", ""}, - {"sys/time.h", ""}, - {"sys/timeb.h", ""}, - {"sys/timerfd.h", ""}, - {"sys/times.h", ""}, - {"sys/timex.h", ""}, - {"sys/ttychars.h", ""}, - {"sys/ttydefaults.h", ""}, - {"sys/types.h", ""}, - {"sys/ucontext.h", ""}, - {"sys/uio.h", ""}, - {"sys/un.h", ""}, - {"sys/user.h", ""}, - {"sys/ustat.h", ""}, - {"sys/utsname.h", ""}, - {"sys/vlimit.h", ""}, - {"sys/vm86.h", ""}, - {"sys/vtimes.h", ""}, - {"sys/wait.h", ""}, - {"sys/xattr.h", ""}, - {"bits/epoll.h", ""}, - {"bits/eventfd.h", ""}, - {"bits/inotify.h", ""}, - {"bits/ipc.h", ""}, - {"bits/ipctypes.h", ""}, - {"bits/mman-linux.h", ""}, - {"bits/mman.h", ""}, - {"bits/msq.h", ""}, - {"bits/resource.h", ""}, - {"bits/sem.h", ""}, - {"bits/shm.h", ""}, - {"bits/signalfd.h", ""}, - {"bits/statfs.h", ""}, - {"bits/statvfs.h", ""}, - {"bits/timerfd.h", ""}, - {"bits/utsname.h", ""}, - {"bits/auxv.h", ""}, - {"bits/byteswap-16.h", ""}, - {"bits/byteswap.h", ""}, - {"bits/confname.h", ""}, - {"bits/dirent.h", ""}, - {"bits/dlfcn.h", ""}, - {"bits/elfclass.h", ""}, - {"bits/endian.h", ""}, - {"bits/environments.h", ""}, - {"bits/fcntl-linux.h", ""}, - {"bits/fcntl.h", ""}, - {"bits/in.h", ""}, - {"bits/ioctl-types.h", ""}, - {"bits/ioctls.h", ""}, - {"bits/link.h", ""}, - {"bits/mqueue.h", ""}, - {"bits/netdb.h", ""}, - {"bits/param.h", ""}, - {"bits/poll.h", ""}, - {"bits/posix_opt.h", ""}, - {"bits/pthreadtypes.h", ""}, - {"bits/sched.h", ""}, - {"bits/select.h", ""}, - {"bits/semaphore.h", ""}, - {"bits/sigthread.h", ""}, - {"bits/sockaddr.h", ""}, - {"bits/socket.h", ""}, - {"bits/socket_type.h", ""}, - {"bits/stab.def", ""}, - {"bits/stat.h", ""}, - {"bits/stropts.h", ""}, - {"bits/syscall.h", ""}, - {"bits/syslog-path.h", ""}, - {"bits/termios.h", ""}, - {"bits/types.h", ""}, - {"bits/typesizes.h", ""}, - {"bits/uio.h", ""}, - {"bits/ustat.h", ""}, - {"bits/utmp.h", ""}, - {"bits/utmpx.h", ""}, - {"bits/waitflags.h", ""}, - {"bits/waitstatus.h", ""}, - {"bits/xtitypes.h", ""}, - }); + static const auto *SystemHeaderMap = [] { + const size_t Size = sizeof(IncludeMappings) / sizeof(IncludeMappings[0]); + auto *HeaderMap = new llvm::StringMap(Size); + for (size_t I = 0; I < Size; I++) { + auto Result = HeaderMap->insert(IncludeMappings[I]); + (void)Result; + + assert(Result.second && "Duplicate in include mappings"); + } + return HeaderMap; + }(); + // Check MaxSuffixComponents constant is correct. assert(llvm::all_of(SystemHeaderMap->keys(), [](llvm::StringRef Path) { return std::distance( diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 316fcb6293b12..18b02af48095f 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -413,6 +413,23 @@ TEST(CompletionTest, Accessible) { )cpp"); EXPECT_THAT(External.Completions, AllOf(has("pub"), Not(has("prot")), Not(has("priv")))); + + auto Results = completions(R"cpp( + struct Foo { + public: void pub(); + protected: void prot(); + private: void priv(); + }; + struct Bar : public Foo { + private: using Foo::pub; + }; + void test() { + Bar B; + B.^ + } + )cpp"); + EXPECT_THAT(Results.Completions, + AllOf(Not(has("priv")), Not(has("prot")), Not(has("pub")))); } TEST(CompletionTest, Qualifiers) { diff --git a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp index 8761f371c1ad9..b3286e58efef1 100644 --- a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp @@ -536,6 +536,14 @@ TEST_F(ConfigCompileTests, AllScopes) { EXPECT_TRUE(compileAndApply()); EXPECT_TRUE(Conf.Completion.AllScopes); } + +TEST_F(ConfigCompileTests, Style) { + Frag = {}; + Frag.Style.FullyQualifiedNamespaces.push_back(std::string("foo")); + Frag.Style.FullyQualifiedNamespaces.push_back(std::string("bar")); + EXPECT_TRUE(compileAndApply()); + EXPECT_THAT(Conf.Style.FullyQualifiedNamespaces, ElementsAre("foo", "bar")); +} } // namespace } // namespace config } // namespace clangd diff --git a/clang-tools-extra/clangd/unittests/ConfigProviderTests.cpp b/clang-tools-extra/clangd/unittests/ConfigProviderTests.cpp index 22f69143dadfa..36a9c383e058e 100644 --- a/clang-tools-extra/clangd/unittests/ConfigProviderTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigProviderTests.cpp @@ -178,44 +178,6 @@ TEST(ProviderTest, FromAncestorRelativeYAMLFiles) { EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("bar", "baz")); } -// FIXME: delete this test, it's covered by FileCacheTests. -TEST(ProviderTest, Staleness) { - MockFS FS; - - auto StartTime = std::chrono::steady_clock::now(); - Params StaleOK; - StaleOK.FreshTime = StartTime; - Params MustBeFresh; - MustBeFresh.FreshTime = StartTime + std::chrono::hours(1); - CapturedDiags Diags; - auto P = Provider::fromYAMLFile(testPath("foo.yaml"), /*Directory=*/"", FS); - - // Initial query always reads, regardless of policy. - FS.Files["foo.yaml"] = AddFooWithErr; - auto Cfg = P->getConfig(StaleOK, Diags.callback()); - EXPECT_THAT(Diags.Diagnostics, - ElementsAre(diagMessage("Unknown CompileFlags key 'Unknown'"))); - EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("foo")); - Diags.clear(); - - // Stale value reused by policy. - FS.Files["foo.yaml"] = AddBarBaz; - Cfg = P->getConfig(StaleOK, Diags.callback()); - EXPECT_THAT(Diags.Diagnostics, IsEmpty()) << "Cached, not re-parsed"; - EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("foo")); - - // Cache revalidated by policy. - Cfg = P->getConfig(MustBeFresh, Diags.callback()); - EXPECT_THAT(Diags.Diagnostics, IsEmpty()) << "New config, no errors"; - EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("bar", "baz")); - - // Cache revalidated by (default) policy. - FS.Files.erase("foo.yaml"); - Cfg = P->getConfig(Params(), Diags.callback()); - EXPECT_THAT(Diags.Diagnostics, IsEmpty()); - EXPECT_THAT(getAddedArgs(Cfg), IsEmpty()); -} - TEST(ProviderTest, SourceInfo) { MockFS FS; diff --git a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp index 143bcf99fc547..ddf6f4f5fb1f6 100644 --- a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp @@ -261,6 +261,19 @@ TEST(ParseYAML, IncludesIgnoreHeader) { EXPECT_THAT(Results[0].Diagnostics.Includes.IgnoreHeader, ElementsAre(val("foo"), val("bar"))); } + +TEST(ParseYAML, Style) { + CapturedDiags Diags; + Annotations YAML(R"yaml( +Style: + FullyQualifiedNamespaces: [foo, bar])yaml"); + auto Results = + Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback()); + ASSERT_THAT(Diags.Diagnostics, IsEmpty()); + ASSERT_EQ(Results.size(), 1u); + EXPECT_THAT(Results[0].Style.FullyQualifiedNamespaces, + ElementsAre(val("foo"), val("bar"))); +} } // namespace } // namespace config } // namespace clangd diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index 25ce19b2c580b..0f149b7242966 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -3206,6 +3206,30 @@ TEST(Hover, HideBigInitializers) { ASSERT_TRUE(H); EXPECT_EQ(H->Definition, "int arr[]"); } + +TEST(Hover, Typedefs) { + Annotations T(R"cpp( + template + struct cond { using type = T; }; + template + struct cond { using type = F; }; + + template + using type = typename cond::type; + + void foo() { + using f^oo = type; + } + )cpp"); + + TestTU TU = TestTU::withCode(T.code()); + auto AST = TU.build(); + auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); + + ASSERT_TRUE(H && H->Type); + EXPECT_EQ(H->Type->Type, "int"); + EXPECT_EQ(H->Definition, "using foo = type"); +} } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp index 2f4e8e57a81f1..f60c62500c7de 100644 --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -807,6 +807,19 @@ sizeof...($TemplateParameter[[Elements]]); $Function_deprecated[[Foo]]($Parameter[[x]]); $Function_deprecated[[Foo]]($Parameter[[x]]); } + )cpp", + // Explicit template specialization + R"cpp( + struct $Class_decl[[Base]]{}; + template + struct $Class_decl[[S]] : public $Class[[Base]] {}; + template <> + struct $Class_decl[[S]] : public $Class[[Base]] {}; + + template + $TemplateParameter[[T]] $Variable_decl[[x]] = {}; + template <> + int $Variable_decl[[x]] = (int)sizeof($Class[[Base]]); )cpp"}; for (const auto &TestCase : TestCases) // Mask off scope modifiers to keep the tests manageable. diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 5196c53291d19..916bb1dbd99f1 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -156,6 +156,9 @@ Changes in existing checks ` when `sizeof(...)` is compared against a `__int128_t`. +- Made :doc:`cert-oop57-cpp ` more sensitive + by checking for an arbitrary expression in the second argument of ``memset``. + - Improved :doc:`cppcoreguidelines-prefer-member-initializer ` check. @@ -204,7 +207,16 @@ Changes in existing checks - Fixed a crash in :doc:`performance-unnecessary-value-param ` when the specialization - template has an unnecessary value paramter. Removed the fix for a template. + template has an unnecessary value parameter. Removed the fix for a template. + +- Fixed bugs in :doc:`bugprone-use-after-move + `: + + - Treat a move in a lambda capture as happening in the function that defines + the lambda, not within the body of the lambda (as we were previously doing + erroneously). + + - Don't emit an erroneous warning on self-moves. Removed checks ^^^^^^^^^^^^^^ @@ -227,7 +239,7 @@ The improvements are... Improvements to pp-trace ------------------------ -The improvements are... +- Added `HashLoc` information to `InclusionDirective` callback output. Clang-tidy Visual Studio plugin ------------------------------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone-unchecked-optional-access.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone-unchecked-optional-access.rst index 9c53c8a6d175f..3ed6372840a89 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone-unchecked-optional-access.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone-unchecked-optional-access.rst @@ -4,8 +4,8 @@ bugprone-unchecked-optional-access ================================== *Note*: This check uses a flow-sensitive static analysis to produce its - results. Therefore, it may be more resource intensive (RAM, CPU) than the - average clang-tidy check. +results. Therefore, it may be more resource intensive (RAM, CPU) than the +average clang-tidy check. This check identifies unsafe accesses to values contained in ``std::optional``, ``absl::optional``, or ``base::Optional`` @@ -42,7 +42,7 @@ existence check: .. code-block:: c++ - void f(absl::optional opt) { + void f(std::optional opt) { use(*opt); // unsafe: it is unclear whether `opt` has a value. } @@ -54,7 +54,7 @@ branches of the code. For example: .. code-block:: c++ - void f(absl::optional opt) { + void f(std::optional opt) { if (opt.has_value()) { } else { use(opt.value()); // unsafe: it is clear that `opt` does *not* have a value. @@ -99,11 +99,11 @@ optional has a value. For example: .. code-block:: c++ - void g(absl::optional opt) { + void g(std::optional opt) { use(*opt); // unsafe: it is unclear whether `opt` has a value. } - void f(absl::optional opt) { + void f(std::optional opt) { if (opt.has_value()) { g(opt); } @@ -121,7 +121,7 @@ example: .. code-block:: c++ - void f(absl::optional opt) { + void f(std::optional opt) { if (opt.has_value()) { use(*opt); } @@ -137,9 +137,9 @@ have a value. For example: .. code-block:: c++ - void f(absl::optional opt1) { + void f(std::optional opt1) { if (opt1.has_value()) { - absl::optional opt2 = opt1; + std::optional opt2 = opt1; use(*opt2); } } @@ -154,7 +154,7 @@ a value. For example: .. code-block:: c++ - void f(absl::optional opt) { + void f(std::optional opt) { DCHECK(opt.has_value()); use(*opt); } @@ -168,7 +168,7 @@ paths that lead to an access. For example: .. code-block:: c++ - void f(absl::optional opt) { + void f(std::optional opt) { bool safe = false; if (opt.has_value() && SomeOtherCondition()) { safe = true; @@ -223,7 +223,7 @@ check the optional again in the local scope of the callee. For example: use(val); } - void f(absl::optional opt) { + void f(std::optional opt) { if (opt.has_value()) { g(*opt); } @@ -234,7 +234,7 @@ and .. code-block:: c++ struct S { - absl::optional opt; + std::optional opt; int x; }; @@ -260,7 +260,7 @@ The check is aware of aliases of optional types that are created via .. code-block:: c++ - using OptionalInt = absl::optional; + using OptionalInt = std::optional; void f(OptionalInt opt) { use(opt.value()); // unsafe: it is unclear whether `opt` has a value. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-emplace.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-emplace.rst index 8533c89589977..f08bfb4449c32 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-emplace.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-emplace.rst @@ -15,17 +15,29 @@ because replacing ``insert`` with ``emplace`` may result in By default only ``std::vector``, ``std::deque``, ``std::list`` are considered. This list can be modified using the :option:`ContainersWithPushBack` option. +This check also reports when an ``emplace``-like method is improperly used, +for example using ``emplace_back`` while also calling a constructor. This +creates a temporary that requires at best a move and at worst a copy. Almost all +``emplace``-like functions in the STL are covered by this, with ``try_emplace`` +on ``std::map`` and ``std::unordered_map`` being the exception as it behaves +slightly differently than all the others. More containers can be added with the +:option:`EmplacyFunctions` option, so long as the container defines a +``value_type`` type, and the ``emplace``-like functions construct a +``value_type`` object. + Before: .. code-block:: c++ std::vector v; v.push_back(MyClass(21, 37)); + v.emplace_back(MyClass(21, 37)); std::vector> w; w.push_back(std::pair(21, 37)); w.push_back(std::make_pair(21L, 37L)); + w.emplace_back(std::make_pair(21L, 37L)); After: @@ -33,10 +45,12 @@ After: std::vector v; v.emplace_back(21, 37); + v.emplace_back(21, 37); std::vector> w; w.emplace_back(21, 37); w.emplace_back(21L, 37L); + w.emplace_back(21L, 37L); By default, the check is able to remove unnecessary ``std::make_pair`` and ``std::make_tuple`` calls from ``push_back`` calls on containers of @@ -128,6 +142,13 @@ Options function calls will be removed from ``push_back`` calls and turned into ``emplace_back``. +.. option:: EmplacyFunctions + + Semicolon-separated list of containers without their template parameters + and some ``emplace``-like method of the container. Example: + ``vector::emplace_back``. Those methods will be checked for improper use and + the check will report when a temporary is unnecessarily created. + Example ^^^^^^^ @@ -135,6 +156,7 @@ Example std::vector> x; x.push_back(MakeMyTuple(1, false, 'x')); + x.emplace_back(MakeMyTuple(1, false, 'x')); transforms to: @@ -142,6 +164,8 @@ transforms to: std::vector> x; x.emplace_back(1, false, 'x'); + x.emplace_back(1, false, 'x'); -when :option:`TupleTypes` is set to ``MyTuple`` and :option:`TupleMakeFunctions` -is set to ``MakeMyTuple``. +when :option:`TupleTypes` is set to ``MyTuple``, :option:`TupleMakeFunctions` +is set to ``MakeMyTuple``, and :option:`EmplacyFunctions` is set to +``vector::emplace_back``. diff --git a/clang-tools-extra/docs/pp-trace.rst b/clang-tools-extra/docs/pp-trace.rst index 84a5ae6ed6c60..7339d8084c34e 100644 --- a/clang-tools-extra/docs/pp-trace.rst +++ b/clang-tools-extra/docs/pp-trace.rst @@ -223,6 +223,7 @@ Imported ((module name)|(null)) const Modu Example::: - Callback: InclusionDirective + HashLoc: "D:/Clang/llvmnewmod/clang-tools-extra/test/pp-trace/pp-trace-include.cpp:4:1" IncludeTok: include FileName: "Input/Level1B.h" IsAngled: false diff --git a/clang-tools-extra/include-cleaner/unittests/CMakeLists.txt b/clang-tools-extra/include-cleaner/unittests/CMakeLists.txt index 0cbbefcdd611e..8786f6d38e35f 100644 --- a/clang-tools-extra/include-cleaner/unittests/CMakeLists.txt +++ b/clang-tools-extra/include-cleaner/unittests/CMakeLists.txt @@ -23,5 +23,6 @@ target_link_libraries(ClangIncludeCleanerTests PRIVATE clangIncludeCleaner clangTesting + LLVMTestingSupport ) diff --git a/clang-tools-extra/modularize/Modularize.cpp b/clang-tools-extra/modularize/Modularize.cpp index 7f73749f5b540..4b95711813d9e 100644 --- a/clang-tools-extra/modularize/Modularize.cpp +++ b/clang-tools-extra/modularize/Modularize.cpp @@ -310,13 +310,12 @@ cl::desc("Only warn if #include directives are inside extern or namespace" // Option for include paths for coverage check. static cl::list -IncludePaths("I", cl::desc("Include path for coverage check."), -cl::ZeroOrMore, cl::value_desc("path")); + IncludePaths("I", cl::desc("Include path for coverage check."), + cl::value_desc("path")); // Option for disabling the coverage check. -static cl::opt -NoCoverageCheck("no-coverage-check", cl::init(false), -cl::desc("Don't do the coverage check.")); +static cl::opt NoCoverageCheck("no-coverage-check", + cl::desc("Don't do the coverage check.")); // Option for just doing the coverage check. static cl::opt diff --git a/clang-tools-extra/pp-trace/PPCallbacksTracker.cpp b/clang-tools-extra/pp-trace/PPCallbacksTracker.cpp index 63a07914f2071..c1434558698db 100644 --- a/clang-tools-extra/pp-trace/PPCallbacksTracker.cpp +++ b/clang-tools-extra/pp-trace/PPCallbacksTracker.cpp @@ -137,6 +137,7 @@ void PPCallbacksTracker::InclusionDirective( llvm::StringRef SearchPath, llvm::StringRef RelativePath, const Module *Imported, SrcMgr::CharacteristicKind FileType) { beginCallback("InclusionDirective"); + appendArgument("HashLoc", HashLoc); appendArgument("IncludeTok", IncludeTok); appendFilePathArgument("FileName", FileName); appendArgument("IsAngled", IsAngled); diff --git a/clang-tools-extra/pseudo/benchmarks/Benchmark.cpp b/clang-tools-extra/pseudo/benchmarks/Benchmark.cpp index b10ff3a175bd2..6002bada2aa21 100644 --- a/clang-tools-extra/pseudo/benchmarks/Benchmark.cpp +++ b/clang-tools-extra/pseudo/benchmarks/Benchmark.cpp @@ -24,9 +24,9 @@ #include "clang-pseudo/DirectiveTree.h" #include "clang-pseudo/Forest.h" #include "clang-pseudo/GLR.h" -#include "clang-pseudo/Grammar.h" -#include "clang-pseudo/LRTable.h" #include "clang-pseudo/Token.h" +#include "clang-pseudo/grammar/Grammar.h" +#include "clang-pseudo/grammar/LRTable.h" #include "clang/Basic/LangOptions.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" diff --git a/clang-tools-extra/pseudo/fuzzer/Fuzzer.cpp b/clang-tools-extra/pseudo/fuzzer/Fuzzer.cpp index 7b59eec30dbdf..58367837813ff 100644 --- a/clang-tools-extra/pseudo/fuzzer/Fuzzer.cpp +++ b/clang-tools-extra/pseudo/fuzzer/Fuzzer.cpp @@ -9,9 +9,9 @@ #include "clang-pseudo/DirectiveTree.h" #include "clang-pseudo/Forest.h" #include "clang-pseudo/GLR.h" -#include "clang-pseudo/Grammar.h" -#include "clang-pseudo/LRTable.h" #include "clang-pseudo/Token.h" +#include "clang-pseudo/grammar/Grammar.h" +#include "clang-pseudo/grammar/LRTable.h" #include "clang/Basic/LangOptions.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/MemoryBuffer.h" diff --git a/clang-tools-extra/pseudo/gen/CMakeLists.txt b/clang-tools-extra/pseudo/gen/CMakeLists.txt index a104e05b53da9..3dd615a558751 100644 --- a/clang-tools-extra/pseudo/gen/CMakeLists.txt +++ b/clang-tools-extra/pseudo/gen/CMakeLists.txt @@ -1,10 +1,11 @@ set(LLVM_LINK_COMPONENTS Support) +list(REMOVE_ITEM LLVM_COMMON_DEPENDS clang-tablegen-targets) -add_clang_executable(pseudo-gen +add_clang_executable(clang-pseudo-gen Main.cpp ) -target_link_libraries(pseudo-gen +target_link_libraries(clang-pseudo-gen PRIVATE clangPseudoGrammar ) diff --git a/clang-tools-extra/pseudo/gen/Main.cpp b/clang-tools-extra/pseudo/gen/Main.cpp index 47ba7f2e71b54..38cb7f48e2b66 100644 --- a/clang-tools-extra/pseudo/gen/Main.cpp +++ b/clang-tools-extra/pseudo/gen/Main.cpp @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -#include "clang-pseudo/Grammar.h" +#include "clang-pseudo/grammar/Grammar.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" diff --git a/clang-tools-extra/pseudo/include/CMakeLists.txt b/clang-tools-extra/pseudo/include/CMakeLists.txt index e4265b18c2b2e..92259594bce1f 100644 --- a/clang-tools-extra/pseudo/include/CMakeLists.txt +++ b/clang-tools-extra/pseudo/include/CMakeLists.txt @@ -1,14 +1,18 @@ # The cxx.bnf grammar file set(cxx_bnf ${CMAKE_CURRENT_SOURCE_DIR}/../lib/cxx.bnf) -# Using CMAKE_CROSSCOMPILING and not LLVM_USE_HOST_TOOLS because the latter is -# also set for LLVM_OPTIMIZED_TABLEGEN, which we don't care about here. -if(CMAKE_CROSSCOMPILING) - build_native_tool(pseudo-gen pseudo_gen) +set(CLANG_PSEUDO_GEN "clang-pseudo-gen" CACHE + STRING "Host clang-pseudo-gen executable. Saves building if cross-compiling.") + +if(NOT CLANG_PSEUDO_GEN STREQUAL "clang-pseudo-gen") + set(pseudo_gen ${CLANG_PSEUDO_GEN}) + set(pseudo_gen_target ${CLANG_PSEUDO_GEN}) +elseif(LLVM_USE_HOST_TOOLS) + build_native_tool(clang-pseudo-gen pseudo_gen) set(pseudo_gen_target "${pseudo_gen}") else() - set(pseudo_gen $) - set(pseudo_gen_target pseudo-gen) + set(pseudo_gen $) + set(pseudo_gen_target clang-pseudo-gen) endif() # Generate inc files. @@ -19,7 +23,7 @@ add_custom_command(OUTPUT ${cxx_symbols_inc} --emit-symbol-list -o ${cxx_symbols_inc} COMMENT "Generating nonterminal symbol file for cxx grammar..." - DEPENDS ${pseudo_gen_target} + DEPENDS ${pseudo_gen_target} ${cxx_bnf} VERBATIM) set(cxx_bnf_inc ${CMAKE_CURRENT_BINARY_DIR}/CXXBNF.inc) @@ -29,7 +33,7 @@ add_custom_command(OUTPUT ${cxx_bnf_inc} --emit-grammar-content -o ${cxx_bnf_inc} COMMENT "Generating bnf string file for cxx grammar..." - DEPENDS ${pseudo_gen_target} + DEPENDS ${pseudo_gen_target} ${cxx_bnf} VERBATIM) # add_custom_command does not create a new target, we need to deine a target diff --git a/clang-tools-extra/pseudo/include/clang-pseudo/Forest.h b/clang-tools-extra/pseudo/include/clang-pseudo/Forest.h index c699c4c217dff..29bcac98a64f8 100644 --- a/clang-tools-extra/pseudo/include/clang-pseudo/Forest.h +++ b/clang-tools-extra/pseudo/include/clang-pseudo/Forest.h @@ -20,8 +20,8 @@ #ifndef CLANG_PSEUDO_FOREST_H #define CLANG_PSEUDO_FOREST_H -#include "clang-pseudo/Grammar.h" #include "clang-pseudo/Token.h" +#include "clang-pseudo/grammar/Grammar.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Allocator.h" diff --git a/clang-tools-extra/pseudo/include/clang-pseudo/GLR.h b/clang-tools-extra/pseudo/include/clang-pseudo/GLR.h index 70d6e46e5aed3..8783872fa3556 100644 --- a/clang-tools-extra/pseudo/include/clang-pseudo/GLR.h +++ b/clang-tools-extra/pseudo/include/clang-pseudo/GLR.h @@ -30,8 +30,8 @@ #define CLANG_PSEUDO_GLR_H #include "clang-pseudo/Forest.h" -#include "clang-pseudo/Grammar.h" -#include "clang-pseudo/LRTable.h" +#include "clang-pseudo/grammar/Grammar.h" +#include "clang-pseudo/grammar/LRTable.h" #include "llvm/Support/Allocator.h" #include @@ -68,6 +68,8 @@ struct GSS { struct alignas(struct Node *) Node { // LR state describing how parsing should continue from this head. LRTable::StateID State; + // Used internally to track reachability during garbage collection. + bool GCParity; // Number of the parents of this node. // The parents hold previous parsed symbols, and may resume control after // this node is reduced. @@ -77,10 +79,6 @@ struct GSS { // (In the literature, the node is attached to the *edge* to the parent). const ForestNode *Payload = nullptr; - // FIXME: Most nodes live a fairly short time, and are simply discarded. - // Is it worth refcounting them (we have empty padding) and returning to a - // freelist, to keep the working set small? - llvm::ArrayRef parents() const { return llvm::makeArrayRef(reinterpret_cast(this + 1), ParentCount); @@ -90,23 +88,26 @@ struct GSS { // Allocates a new node in the graph. const Node *addNode(LRTable::StateID State, const ForestNode *Symbol, - llvm::ArrayRef Parents) { - ++NodeCount; - Node *Result = new (Arena.Allocate( - sizeof(Node) + Parents.size() * sizeof(Node *), alignof(Node))) - Node({State, static_cast(Parents.size())}); - Result->Payload = Symbol; - if (!Parents.empty()) - llvm::copy(Parents, reinterpret_cast(Result + 1)); - return Result; - } + llvm::ArrayRef Parents); + // Frees all nodes not reachable as ancestors of Roots, and returns the count. + // Calling this periodically prevents steady memory growth of the GSS. + unsigned gc(std::vector &&Roots); size_t bytes() const { return Arena.getTotalMemory() + sizeof(*this); } - size_t nodeCount() const { return NodeCount; } + size_t nodesCreated() const { return NodesCreated; } private: + // Nodes are recycled using freelists. + // They are variable size, so use one free-list per distinct #parents. + std::vector> FreeList; + Node *allocate(unsigned Parents); + void destroy(Node *N); + // The list of nodes created and not destroyed - our candidates for gc(). + std::vector Alive; + bool GCParity = false; // All nodes should match this, except during GC. + llvm::BumpPtrAllocator Arena; - unsigned NodeCount = 0; + unsigned NodesCreated = 0; }; llvm::raw_ostream &operator<<(llvm::raw_ostream &, const GSS::Node &); diff --git a/clang-tools-extra/pseudo/include/clang-pseudo/cxx/CXX.h b/clang-tools-extra/pseudo/include/clang-pseudo/cxx/CXX.h index edeeb636d83ed..4acad01588124 100644 --- a/clang-tools-extra/pseudo/include/clang-pseudo/cxx/CXX.h +++ b/clang-tools-extra/pseudo/include/clang-pseudo/cxx/CXX.h @@ -23,7 +23,7 @@ #ifndef CLANG_PSEUDO_CXX_CXX_H #define CLANG_PSEUDO_CXX_CXX_H -#include "clang-pseudo/Grammar.h" +#include "clang-pseudo/grammar/Grammar.h" namespace clang { namespace pseudo { diff --git a/clang-tools-extra/pseudo/include/clang-pseudo/Grammar.h b/clang-tools-extra/pseudo/include/clang-pseudo/grammar/Grammar.h similarity index 81% rename from clang-tools-extra/pseudo/include/clang-pseudo/Grammar.h rename to clang-tools-extra/pseudo/include/clang-pseudo/grammar/Grammar.h index df757c61a1ede..8137734bd74fb 100644 --- a/clang-tools-extra/pseudo/include/clang-pseudo/Grammar.h +++ b/clang-tools-extra/pseudo/include/clang-pseudo/grammar/Grammar.h @@ -19,6 +19,22 @@ // production rules. A rule is of BNF form (AAA := BBB CCC). A symbol is either // nonterminal or terminal, identified by a SymbolID. // +// Annotations are supported in a syntax form of [key=value]. They specify +// attributes which are associated with either a grammar symbol (on the +// right-hand side of the symbol) or a grammar rule (at the end of the rule +// body). +// Attributes provide a way to inject custom code into the GLR parser. Each +// unique attribute value creates an extension point (identified by ExtensionID +// ), and an extension point corresponds to a piece of native code. For +// example, C++ grammar has a rule: +// +// contextual-override := IDENTIFIER [guard=Override] +// +// GLR parser only conducts the reduction of the rule if the IDENTIFIER +// content is `override`. This Override guard is implemented in CXX.cpp by +// binding the ExtensionID for the `Override` value to a specific C++ function +// that performs the check. +// // Notions about the BNF grammar: // - "_" is the start symbol of the augmented grammar; // - single-line comment is supported, starting with a # @@ -33,8 +49,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_PSEUDO_GRAMMAR_H -#define CLANG_PSEUDO_GRAMMAR_H +#ifndef CLANG_PSEUDO_GRAMMAR_GRAMMAR_H +#define CLANG_PSEUDO_GRAMMAR_GRAMMAR_H #include "clang/Basic/TokenKinds.h" #include "llvm/ADT/ArrayRef.h" @@ -69,6 +85,11 @@ inline SymbolID tokenSymbol(tok::TokenKind TK) { return TokenFlag | static_cast(TK); } +// An extension is a piece of native code specific to a grammar that modifies +// the behavior of annotated rules. One ExtensionID is assigned for each unique +// attribute value (all attributes share a namespace). +using ExtensionID = uint16_t; + // A RuleID uniquely identifies a production rule in a grammar. // It is an index into a table of rules. using RuleID = uint16_t; @@ -96,11 +117,17 @@ struct Rule { uint8_t Size : SizeBits; // Size of the Sequence SymbolID Sequence[MaxElements]; + // A guard extension controls whether a reduction of a rule will be conducted + // by the GLR parser. + // 0 is sentinel unset extension ID, indicating there is no guard extension + // being set for this rule. + ExtensionID Guard = 0; + llvm::ArrayRef seq() const { return llvm::ArrayRef(Sequence, Size); } friend bool operator==(const Rule &L, const Rule &R) { - return L.Target == R.Target && L.seq() == R.seq(); + return L.Target == R.Target && L.seq() == R.seq() && L.Guard == R.Guard; } }; @@ -186,9 +213,12 @@ struct GrammarTable { // A table of nonterminals, sorted by name. // SymbolID is the index of the table. std::vector Nonterminals; + // A table of attribute values, sorted by name. + // ExtensionID is the index of the table. + std::vector AttributeValues; }; } // namespace pseudo } // namespace clang -#endif // CLANG_PSEUDO_GRAMMAR_H +#endif // CLANG_PSEUDO_GRAMMAR_GRAMMAR_H diff --git a/clang-tools-extra/pseudo/include/clang-pseudo/LRGraph.h b/clang-tools-extra/pseudo/include/clang-pseudo/grammar/LRGraph.h similarity index 97% rename from clang-tools-extra/pseudo/include/clang-pseudo/LRGraph.h rename to clang-tools-extra/pseudo/include/clang-pseudo/grammar/LRGraph.h index 889c5e5decf50..1b53653274310 100644 --- a/clang-tools-extra/pseudo/include/clang-pseudo/LRGraph.h +++ b/clang-tools-extra/pseudo/include/clang-pseudo/grammar/LRGraph.h @@ -28,10 +28,10 @@ // in making decisions. //===----------------------------------------------------------------------===// -#ifndef CLANG_PSEUDO_LRGRAPH_H -#define CLANG_PSEUDO_LRGRAPH_H +#ifndef CLANG_PSEUDO_GRAMMAR_LRGRAPH_H +#define CLANG_PSEUDO_GRAMMAR_LRGRAPH_H -#include "clang-pseudo/Grammar.h" +#include "clang-pseudo/grammar/Grammar.h" #include "llvm/ADT/Hashing.h" #include @@ -178,4 +178,4 @@ template <> struct DenseMapInfo { }; } // namespace llvm -#endif // CLANG_PSEUDO_LRGRAPH_H +#endif // CLANG_PSEUDO_GRAMMAR_LRGRAPH_H diff --git a/clang-tools-extra/pseudo/include/clang-pseudo/LRTable.h b/clang-tools-extra/pseudo/include/clang-pseudo/grammar/LRTable.h similarity index 84% rename from clang-tools-extra/pseudo/include/clang-pseudo/LRTable.h rename to clang-tools-extra/pseudo/include/clang-pseudo/grammar/LRTable.h index 735ef3b781ad4..08e4868b88f70 100644 --- a/clang-tools-extra/pseudo/include/clang-pseudo/LRTable.h +++ b/clang-tools-extra/pseudo/include/clang-pseudo/grammar/LRTable.h @@ -19,8 +19,7 @@ // Typically, based on the category of the grammar symbol, the LRTable is // broken into two logically separate tables: // - ACTION table with terminals as columns -- e.g. ACTION[S, a] specifies -// next action (shift/reduce/accept/error) on state S under a lookahead -// terminal a +// next action (shift/reduce) on state S under a lookahead terminal a // - GOTO table with nonterminals as columns -- e.g. GOTO[S, X] specifies // the state which we transist to from the state S with the nonterminal X // @@ -34,10 +33,10 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_PSEUDO_LRTABLE_H -#define CLANG_PSEUDO_LRTABLE_H +#ifndef CLANG_PSEUDO_GRAMMAR_LRTABLE_H +#define CLANG_PSEUDO_GRAMMAR_LRTABLE_H -#include "clang-pseudo/Grammar.h" +#include "clang-pseudo/grammar/Grammar.h" #include "llvm/ADT/ArrayRef.h" #include #include @@ -76,8 +75,12 @@ class LRTable { Shift, // Reduce by a rule: pop the state stack. Reduce, - // Signals that we have parsed the input successfully. - Accept, + + // NOTE: there are no typical accept actions in the LRtable, accept + // actions are handled specifically in the parser -- if the parser + // reaches to a target state (which is goto(StartState, StartSymbol)) at + // the EOF token after a reduce, this indicates the input has been parsed + // as the StartSymbol successfully. // Nonterminal actions, corresponding to entry of GOTO table. @@ -86,7 +89,6 @@ class LRTable { GoTo, }; - static Action accept(RuleID RID) { return Action(Accept, RID); } static Action goTo(StateID S) { return Action(GoTo, S); } static Action shift(StateID S) { return Action(Shift, S); } static Action reduce(RuleID RID) { return Action(Reduce, RID); } @@ -145,9 +147,8 @@ class LRTable { size_t bytes() const { return sizeof(*this) + Actions.capacity() * sizeof(Action) + - States.capacity() * sizeof(StateID) + - NontermOffset.capacity() * sizeof(uint32_t) + - TerminalOffset.capacity() * sizeof(uint32_t); + Symbols.capacity() * sizeof(SymbolID) + + StateOffset.capacity() * sizeof(uint32_t); } std::string dumpStatistics() const; @@ -170,17 +171,15 @@ class LRTable { // Conceptually the LR table is a multimap from (State, SymbolID) => Action. // Our physical representation is quite different for compactness. - // Index is nonterminal SymbolID, value is the offset into States/Actions - // where the entries for this nonterminal begin. - // Give a nonterminal id, the corresponding half-open range of StateIdx is - // [NontermIdx[id], NontermIdx[id+1]). - std::vector NontermOffset; - // Similar to NontermOffset, but for terminals, index is tok::TokenKind. - std::vector TerminalOffset; - // Parallel to Actions, the value is State (rows of the matrix). - // Grouped by the SymbolID, and only subranges are sorted. - std::vector States; - // A flat list of available actions, sorted by (SymbolID, State). + // Index is StateID, value is the offset into Symbols/Actions + // where the entries for this state begin. + // Give a state id, the corresponding half-open range of Symbols/Actions is + // [StateOffset[id], StateOffset[id+1]). + std::vector StateOffset; + // Parallel to Actions, the value is SymbolID (columns of the matrix). + // Grouped by the StateID, and only subranges are sorted. + std::vector Symbols; + // A flat list of available actions, sorted by (State, SymbolID). std::vector Actions; // A sorted table, storing the start state for each target parsing symbol. std::vector> StartStates; @@ -190,4 +189,4 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &, const LRTable::Action &); } // namespace pseudo } // namespace clang -#endif // CLANG_PSEUDO_LRTABLE_H +#endif // CLANG_PSEUDO_GRAMMAR_LRTABLE_H diff --git a/clang-tools-extra/pseudo/lib/GLR.cpp b/clang-tools-extra/pseudo/lib/GLR.cpp index 10fa0d0568c02..39da7f15c5c9a 100644 --- a/clang-tools-extra/pseudo/lib/GLR.cpp +++ b/clang-tools-extra/pseudo/lib/GLR.cpp @@ -7,11 +7,12 @@ //===----------------------------------------------------------------------===// #include "clang-pseudo/GLR.h" -#include "clang-pseudo/Grammar.h" -#include "clang-pseudo/LRTable.h" +#include "clang-pseudo/grammar/Grammar.h" +#include "clang-pseudo/grammar/LRTable.h" #include "clang/Basic/TokenKinds.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -38,13 +39,14 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const GSS::Node &N) { const ForestNode &glrParse(const TokenStream &Tokens, const ParseParams &Params, SymbolID StartSymbol) { + assert(isNonterminal(StartSymbol) && "Start symbol must be a nonterminal"); llvm::ArrayRef Terminals = Params.Forest.createTerminals(Tokens); auto &G = Params.G; (void)G; auto &GSS = Params.GSStack; - // Lists of active shift, reduce, accept actions. - std::vector PendingShift, PendingReduce, PendingAccept; + // Lists of active shift, reduce actions. + std::vector PendingShift, PendingReduce; auto AddSteps = [&](const GSS::Node *Head, SymbolID NextTok) { for (const auto &Action : Params.Table.getActions(Head->State, NextTok)) { switch (Action.kind()) { @@ -54,17 +56,27 @@ const ForestNode &glrParse(const TokenStream &Tokens, const ParseParams &Params, case LRTable::Action::Reduce: PendingReduce.push_back({Head, Action}); break; - case LRTable::Action::Accept: - PendingAccept.push_back({Head, Action}); - break; default: llvm_unreachable("unexpected action kind!"); } } }; + StateID StartState = Params.Table.getStartState(StartSymbol); std::vector NewHeads = { - GSS.addNode(/*State=*/Params.Table.getStartState(StartSymbol), + GSS.addNode(/*State=*/StartState, /*ForestNode=*/nullptr, {})}; + auto MaybeGC = [&, Roots(std::vector{}), I(0u)]() mutable { + assert(PendingShift.empty() && PendingReduce.empty() && + "Running GC at the wrong time!"); + + if (++I != 20) // Run periodically to balance CPU and memory usage. + return; + I = 0; + + // We need to copy the list: Roots is consumed by the GC. + Roots = NewHeads; + GSS.gc(std::move(Roots)); + }; for (const ForestNode &Terminal : Terminals) { LLVM_DEBUG(llvm::dbgs() << llvm::formatv("Next token {0} (id={1})\n", G.symbolName(Terminal.symbol()), @@ -80,28 +92,36 @@ const ForestNode &glrParse(const TokenStream &Tokens, const ParseParams &Params, glrShift(PendingShift, Terminal, Params, [&](const GSS::Node *NewHead) { NewHeads.push_back(NewHead); }); + MaybeGC(); } LLVM_DEBUG(llvm::dbgs() << llvm::formatv("Next is eof\n")); for (const auto *Heads : NewHeads) AddSteps(Heads, tokenSymbol(tok::eof)); - glrReduce(PendingReduce, Params, - [&](const GSS::Node * NewHead) { - // A reduce will enable more steps. - AddSteps(NewHead, tokenSymbol(tok::eof)); - }); - - if (!PendingAccept.empty()) { - LLVM_DEBUG({ - llvm::dbgs() << llvm::formatv("Accept: {0} accepted result:\n", - PendingAccept.size()); - for (const auto &Accept : PendingAccept) - llvm::dbgs() << " - " << G.symbolName(Accept.Head->Payload->symbol()) - << "\n"; - }); - assert(PendingAccept.size() == 1); - return *PendingAccept.front().Head->Payload; + + StateID AcceptState = Params.Table.getGoToState(StartState, StartSymbol); + // Collect new heads created from the final reduce. + std::vector Heads; + glrReduce(PendingReduce, Params, [&](const GSS::Node *NewHead) { + Heads.push_back(NewHead); + // A reduce will enable more steps. + AddSteps(NewHead, tokenSymbol(tok::eof)); + }); + + const ForestNode *Result = nullptr; + for (const auto *Head : Heads) { + if (Head->State == AcceptState) { + assert(Head->Payload->symbol() == StartSymbol); + assert(Result == nullptr && "multiple results!"); + Result = Head->Payload; + } } + if (Result) + return *Result; // We failed to parse the input, returning an opaque forest node for recovery. + // + // FIXME: We will need to invoke our generic error-recovery handlers when we + // reach EOF without reaching accept state, and involving the eof + // token in the above main for-loopmay be the best way to reuse the code). return Params.Forest.createOpaque(StartSymbol, /*Token::Index=*/0); } @@ -259,18 +279,16 @@ void glrReduce(std::vector &PendingReduce, const ParseParams &Params, } }; - // The base nodes are the heads after popping the GSS nodes we are reducing. - // We don't care which rule yielded each base. If Family.Symbol is S, the - // base includes an item X := ... • S ... and since the grammar is - // context-free, *all* parses of S are valid here. - // FIXME: reuse the queues across calls instead of reallocating. - KeyedQueue Bases; - // A sequence is the ForestNode payloads of the GSS nodes we are reducing. // These are the RHS of the rule, the RuleID is stored in the Family. // They specify a sequence ForestNode we may build (but we dedup first). using Sequence = llvm::SmallVector; - KeyedQueue Sequences; + struct PushSpec { + // A base node is the head after popping the GSS nodes we are reducing. + const GSS::Node* Base = nullptr; + Sequence Seq; + }; + KeyedQueue Sequences; Sequence TempSequence; // Pop walks up the parent chain(s) for a reduction from Head by to Rule. @@ -283,9 +301,8 @@ void glrReduce(std::vector &PendingReduce, const ParseParams &Params, auto DFS = [&](const GSS::Node *N, unsigned I, auto &DFS) { if (I == Rule.Size) { F.Start = TempSequence.front()->startTokenIndex(); - Bases.emplace(F, N); LLVM_DEBUG(llvm::dbgs() << " --> base at S" << N->State << "\n"); - Sequences.emplace(F, TempSequence); + Sequences.emplace(F, PushSpec{N, TempSequence}); return; } TempSequence[Rule.Size - 1 - I] = N->Payload; @@ -311,20 +328,26 @@ void glrReduce(std::vector &PendingReduce, const ParseParams &Params, // - process one family at a time, forming a forest node // - produces new GSS heads which may enable more pops PopPending(); - while (!Bases.empty()) { - // We should always have bases and sequences for the same families. - Family F = Bases.top().first; - assert(!Sequences.empty()); - assert(Sequences.top().first == F); + while (!Sequences.empty()) { + Family F = Sequences.top().first; LLVM_DEBUG(llvm::dbgs() << " Push " << Params.G.symbolName(F.Symbol) << " from token " << F.Start << "\n"); - // Grab the sequences for this family. + // Grab the sequences and bases for this family. + // We don't care which rule yielded each base. If Family.Symbol is S, the + // base includes an item X := ... • S ... and since the grammar is + // context-free, *all* parses of S are valid here. FamilySequences.clear(); + FamilyBases.clear(); do { FamilySequences.emplace_back(Sequences.top().first.Rule, - Sequences.top().second); + Sequences.top().second.Seq); + FamilyBases.emplace_back( + Params.Table.getGoToState(Sequences.top().second.Base->State, + F.Symbol), + Sequences.top().second.Base); + Sequences.pop(); } while (!Sequences.empty() && Sequences.top().first == F); // Build a forest node for each unique sequence. @@ -341,15 +364,7 @@ void glrReduce(std::vector &PendingReduce, const ParseParams &Params, : &Params.Forest.createAmbiguous(F.Symbol, SequenceNodes); LLVM_DEBUG(llvm::dbgs() << " --> " << Parsed->dump(Params.G) << "\n"); - // Grab the bases for this family. - // As well as deduplicating them, we'll group by the goto state. - FamilyBases.clear(); - do { - FamilyBases.emplace_back( - Params.Table.getGoToState(Bases.top().second->State, F.Symbol), - Bases.top().second); - Bases.pop(); - } while (!Bases.empty() && Bases.top().first == F); + // Bases for this family, deduplicate them, and group by the goTo State. sortAndUnique(FamilyBases); // Create a GSS node for each unique goto state. llvm::ArrayRef BasesLeft = FamilyBases; @@ -373,5 +388,72 @@ void glrReduce(std::vector &PendingReduce, const ParseParams &Params, assert(Sequences.empty()); } +const GSS::Node *GSS::addNode(LRTable::StateID State, const ForestNode *Symbol, + llvm::ArrayRef Parents) { + Node *Result = new (allocate(Parents.size())) + Node({State, GCParity, static_cast(Parents.size())}); + Alive.push_back(Result); + ++NodesCreated; + Result->Payload = Symbol; + if (!Parents.empty()) + llvm::copy(Parents, reinterpret_cast(Result + 1)); + return Result; +} + +GSS::Node *GSS::allocate(unsigned Parents) { + if (FreeList.size() <= Parents) + FreeList.resize(Parents + 1); + auto &SizedList = FreeList[Parents]; + if (!SizedList.empty()) { + auto *Result = SizedList.back(); + SizedList.pop_back(); + return Result; + } + return static_cast( + Arena.Allocate(sizeof(Node) + Parents * sizeof(Node *), alignof(Node))); +} + +void GSS::destroy(Node *N) { + unsigned ParentCount = N->ParentCount; + N->~Node(); + assert(FreeList.size() > ParentCount && "established on construction!"); + FreeList[ParentCount].push_back(N); +} + +unsigned GSS::gc(std::vector &&Queue) { +#ifndef NDEBUG + auto ParityMatches = [&](const Node *N) { return N->GCParity == GCParity; }; + assert("Before GC" && llvm::all_of(Alive, ParityMatches)); + auto Deferred = llvm::make_scope_exit( + [&] { assert("After GC" && llvm::all_of(Alive, ParityMatches)); }); + assert(llvm::all_of( + Queue, [&](const Node *R) { return llvm::is_contained(Alive, R); })); +#endif + unsigned InitialCount = Alive.size(); + + // Mark + GCParity = !GCParity; + while (!Queue.empty()) { + Node *N = const_cast(Queue.back()); // Safe: we created these nodes. + Queue.pop_back(); + if (N->GCParity != GCParity) { // Not seen yet + N->GCParity = GCParity; // Mark as seen + for (const Node *P : N->parents()) // And walk parents + Queue.push_back(P); + } + } + // Sweep + llvm::erase_if(Alive, [&](Node *N) { + if (N->GCParity == GCParity) // Walk reached this node. + return false; + destroy(N); + return true; + }); + + LLVM_DEBUG(llvm::dbgs() << "GC pruned " << (InitialCount - Alive.size()) + << "/" << InitialCount << " GSS nodes\n"); + return InitialCount - Alive.size(); +} + } // namespace pseudo } // namespace clang diff --git a/clang-tools-extra/pseudo/lib/cxx.bnf b/clang-tools-extra/pseudo/lib/cxx.bnf index 3a4048f657570..ec05af94c0269 100644 --- a/clang-tools-extra/pseudo/lib/cxx.bnf +++ b/clang-tools-extra/pseudo/lib/cxx.bnf @@ -409,7 +409,7 @@ noptr-declarator := declarator-id noptr-declarator := noptr-declarator parameters-and-qualifiers noptr-declarator := noptr-declarator [ constant-expression_opt ] noptr-declarator := ( ptr-declarator ) -parameters-and-qualifiers := ( parameter-declaration-list_opt ) cv-qualifier-seq_opt ref-qualifier_opt noexcept-specifier_opt +parameters-and-qualifiers := ( parameter-declaration-clause_opt ) cv-qualifier-seq_opt ref-qualifier_opt noexcept-specifier_opt trailing-return-type := -> type-id ptr-operator := * cv-qualifier-seq_opt ptr-operator := & @@ -429,7 +429,7 @@ abstract-declarator := abstract-pack-declarator ptr-abstract-declarator := noptr-abstract-declarator ptr-abstract-declarator := ptr-operator ptr-abstract-declarator_opt noptr-abstract-declarator := noptr-abstract-declarator_opt parameters-and-qualifiers -noptr-abstract-declarator := noptr-abstract-declarator_opt [ constant-expression ] +noptr-abstract-declarator := noptr-abstract-declarator_opt [ constant-expression_opt ] noptr-abstract-declarator := ( ptr-abstract-declarator ) abstract-pack-declarator := noptr-abstract-pack-declarator abstract-pack-declarator := ptr-operator abstract-pack-declarator @@ -537,7 +537,7 @@ class-key := CLASS class-key := STRUCT class-key := UNION member-specification := member-declaration member-specification_opt -member-specification := access-specifier : member-declaration member-specification_opt +member-specification := access-specifier : member-specification_opt member-declaration := decl-specifier-seq_opt member-declarator-list_opt ; member-declaration := function-definition member-declaration := using-declaration @@ -645,7 +645,7 @@ constraint-logical-and-expression := primary-expression constraint-logical-and-expression := constraint-logical-and-expression && primary-expression template-parameter := type-parameter template-parameter := parameter-declaration -type-parameter := type-parameter-key ..._opt IDENTIFIER +type-parameter := type-parameter-key ..._opt IDENTIFIER_opt type-parameter := type-parameter-key IDENTIFIER_opt = type-id type-parameter := type-constraint ..._opt IDENTIFIER_opt type-parameter := type-constraint IDENTIFIER_opt = type-id @@ -750,3 +750,8 @@ export-keyword := IDENTIFIER #! split it into two tokens to make the GLR parser aware of the nested-template #! case. greatergreater := > > + +#! C++ predefined identifier, __func__ [dcl.fct.def.general] p8 +#! FIXME: add other (MSVC, GNU extension) predefined identifiers. +primary-expression := predefined-expression +predefined-expression := __FUNC__ diff --git a/clang-tools-extra/pseudo/lib/cxx/CMakeLists.txt b/clang-tools-extra/pseudo/lib/cxx/CMakeLists.txt index 9e10f2ba5388e..775b3b8c95384 100644 --- a/clang-tools-extra/pseudo/lib/cxx/CMakeLists.txt +++ b/clang-tools-extra/pseudo/lib/cxx/CMakeLists.txt @@ -1,3 +1,7 @@ +set(LLVM_LINK_COMPONENTS + Support + ) + add_clang_library(clangPseudoCXX CXX.cpp diff --git a/clang-tools-extra/pseudo/lib/cxx/CXX.cpp b/clang-tools-extra/pseudo/lib/cxx/CXX.cpp index 3d594b722f1ca..bcf350ce87fc5 100644 --- a/clang-tools-extra/pseudo/lib/cxx/CXX.cpp +++ b/clang-tools-extra/pseudo/lib/cxx/CXX.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "clang-pseudo/cxx/CXX.h" -#include "clang-pseudo/LRTable.h" +#include "clang-pseudo/grammar/LRTable.h" namespace clang { namespace pseudo { diff --git a/clang-tools-extra/pseudo/lib/grammar/CMakeLists.txt b/clang-tools-extra/pseudo/lib/grammar/CMakeLists.txt index d50cb7df2a2cc..f7ada93eeb60b 100644 --- a/clang-tools-extra/pseudo/lib/grammar/CMakeLists.txt +++ b/clang-tools-extra/pseudo/lib/grammar/CMakeLists.txt @@ -1,18 +1,15 @@ set(LLVM_LINK_COMPONENTS Support) -# This library intents to keep as minimal dependencies as possible, it is a base -# library of the cxx generator, to avoid creating long dep paths in the build -# graph. +# This library is used by the clang-pseudo-gen tool which runs at build time. +# Dependencies should be minimal to avoid long dep paths in the build graph. +# It does use clangBasic headers (tok::TokenKind), but linking is not needed. +# We have no transitive dependencies on tablegen files. +list(REMOVE_ITEM LLVM_COMMON_DEPENDS clang-tablegen-targets) add_clang_library(clangPseudoGrammar Grammar.cpp GrammarBNF.cpp LRGraph.cpp LRTable.cpp LRTableBuild.cpp - - # FIXME: can we get rid of the clangBasic dependency? We need it for the - # clang::tok::getTokenName and clang::tok::getPunctuatorSpelling functions, we - # could consider remimplement these functions. - LINK_LIBS - clangBasic ) + diff --git a/clang-tools-extra/pseudo/lib/grammar/Grammar.cpp b/clang-tools-extra/pseudo/lib/grammar/Grammar.cpp index e048f8753d9d9..8e3bcb7afb376 100644 --- a/clang-tools-extra/pseudo/lib/grammar/Grammar.cpp +++ b/clang-tools-extra/pseudo/lib/grammar/Grammar.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "clang-pseudo/Grammar.h" +#include "clang-pseudo/grammar/Grammar.h" #include "clang/Basic/TokenKinds.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" @@ -61,6 +61,8 @@ std::string Grammar::dumpRule(RuleID RID) const { OS << symbolName(R.Target) << " :="; for (SymbolID SID : R.seq()) OS << " " << symbolName(SID); + if (R.Guard) + OS << " [guard=" << T->AttributeValues[R.Guard] << "]"; return Result; } @@ -167,19 +169,16 @@ std::vector> followSets(const Grammar &G) { } static llvm::ArrayRef getTerminalNames() { - static const std::vector *TerminalNames = []() { - static std::vector TerminalNames; - TerminalNames.reserve(NumTerminals); - for (unsigned I = 0; I < NumTerminals; ++I) { - tok::TokenKind K = static_cast(I); - if (const auto *Punc = tok::getPunctuatorSpelling(K)) - TerminalNames.push_back(Punc); - else - TerminalNames.push_back(llvm::StringRef(tok::getTokenName(K)).upper()); - } - return &TerminalNames; + static const auto &TerminalNames = []() { + auto TerminalNames = new std::string[NumTerminals]; +#define PUNCTUATOR(Tok, Spelling) TerminalNames[tok::Tok] = Spelling; +#define KEYWORD(Keyword, Condition) \ + TerminalNames[tok::kw_##Keyword] = llvm::StringRef(#Keyword).upper(); +#define TOK(Tok) TerminalNames[tok::Tok] = llvm::StringRef(#Tok).upper(); +#include "clang/Basic/TokenKinds.def" + return llvm::makeArrayRef(TerminalNames, NumTerminals); }(); - return *TerminalNames; + return TerminalNames; } GrammarTable::GrammarTable() : Terminals(getTerminalNames()) {} diff --git a/clang-tools-extra/pseudo/lib/grammar/GrammarBNF.cpp b/clang-tools-extra/pseudo/lib/grammar/GrammarBNF.cpp index f581adb3932ef..bf5d06f26ae7d 100644 --- a/clang-tools-extra/pseudo/lib/grammar/GrammarBNF.cpp +++ b/clang-tools-extra/pseudo/lib/grammar/GrammarBNF.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "clang-pseudo/Grammar.h" +#include "clang-pseudo/grammar/Grammar.h" #include "clang/Basic/TokenKinds.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" @@ -47,6 +47,9 @@ class GrammarBuilder { // Assemble the name->ID and ID->nonterminal name maps. llvm::DenseSet UniqueNonterminals; llvm::DenseMap SymbolIds; + + llvm::DenseSet UniqueAttributeValues; + for (uint16_t I = 0; I < NumTerminals; ++I) SymbolIds.try_emplace(T->Terminals[I], tokenSymbol(tok::TokenKind(I))); auto Consider = [&](llvm::StringRef Name) { @@ -55,8 +58,11 @@ class GrammarBuilder { }; for (const auto &Spec : Specs) { Consider(Spec.Target); - for (const RuleSpec::Element &Elt : Spec.Sequence) + for (const RuleSpec::Element &Elt : Spec.Sequence) { Consider(Elt.Symbol); + for (const auto& KV : Elt.Attributes) + UniqueAttributeValues.insert(KV.second); + } } llvm::for_each(UniqueNonterminals, [&T](llvm::StringRef Name) { T->Nonterminals.emplace_back(); @@ -68,6 +74,15 @@ class GrammarBuilder { const GrammarTable::Nonterminal &R) { return L.Name < R.Name; }); + // Add an empty string for the corresponding sentinel unset attribute. + T->AttributeValues.push_back(""); + llvm::for_each(UniqueAttributeValues, [&T](llvm::StringRef Name) { + T->AttributeValues.emplace_back(); + T->AttributeValues.back() = Name.str(); + }); + llvm::sort(T->AttributeValues); + assert(T->AttributeValues.front() == ""); + // Build name -> ID maps for nonterminals. for (SymbolID SID = 0; SID < T->Nonterminals.size(); ++SID) SymbolIds.try_emplace(T->Nonterminals[SID].Name, SID); @@ -86,7 +101,9 @@ class GrammarBuilder { for (const RuleSpec::Element &Elt : Spec.Sequence) Symbols.push_back(Lookup(Elt.Symbol)); T->Rules.push_back(Rule(Lookup(Spec.Target), Symbols)); + applyAttributes(Spec, *T, T->Rules.back()); } + assert(T->Rules.size() < (1 << RuleBits) && "Too many rules to fit in RuleID bits!"); const auto &SymbolOrder = getTopologicalOrder(T.get()); @@ -164,6 +181,9 @@ class GrammarBuilder { llvm::StringRef Target; struct Element { llvm::StringRef Symbol; // Name of the symbol + // Attributes that are associated to the sequence symbol or rule. + std::vector> + Attributes; }; std::vector Sequence; @@ -204,11 +224,46 @@ class GrammarBuilder { Chunk = Chunk.trim(); if (Chunk.empty()) continue; // skip empty + if (Chunk.startswith("[") && Chunk.endswith("]")) { + if (Out.Sequence.empty()) + continue; - Out.Sequence.push_back({Chunk}); + parseAttributes(Chunk, Out.Sequence.back().Attributes); + continue; + } + + Out.Sequence.push_back({Chunk, /*Attributes=*/{}}); } return true; - }; + } + + bool parseAttributes( + llvm::StringRef Content, + std::vector> &Out) { + assert(Content.startswith("[") && Content.endswith("]")); + auto KV = Content.drop_front().drop_back().split('='); + Out.push_back({KV.first, KV.second.trim()}); + + return true; + } + // Apply the parsed extensions (stored in RuleSpec) to the grammar Rule. + void applyAttributes(const RuleSpec& Spec, const GrammarTable& T, Rule& R) { + auto LookupExtensionID = [&T](llvm::StringRef Name) { + const auto It = llvm::partition_point( + T.AttributeValues, [&](llvm::StringRef X) { return X < Name; }); + assert(It != T.AttributeValues.end() && *It == Name && + "Didn't find the attribute in AttrValues!"); + return It - T.AttributeValues.begin(); + }; + for (const auto &KV : Spec.Sequence.back().Attributes) { + if (KV.first == "guard") { + R.Guard = LookupExtensionID(KV.second); + continue; + } + Diagnostics.push_back( + llvm::formatv("Unknown attribute '{0}'", KV.first).str()); + } + } // Inlines all _opt symbols. // For example, a rule E := id +_opt id, after elimination, we have two diff --git a/clang-tools-extra/pseudo/lib/grammar/LRGraph.cpp b/clang-tools-extra/pseudo/lib/grammar/LRGraph.cpp index a186549a25e9d..5312a675cdb89 100644 --- a/clang-tools-extra/pseudo/lib/grammar/LRGraph.cpp +++ b/clang-tools-extra/pseudo/lib/grammar/LRGraph.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "clang-pseudo/LRGraph.h" -#include "clang-pseudo/Grammar.h" +#include "clang-pseudo/grammar/LRGraph.h" +#include "clang-pseudo/grammar/Grammar.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/STLExtras.h" diff --git a/clang-tools-extra/pseudo/lib/grammar/LRTable.cpp b/clang-tools-extra/pseudo/lib/grammar/LRTable.cpp index 745ad44bafa6c..016949df5e640 100644 --- a/clang-tools-extra/pseudo/lib/grammar/LRTable.cpp +++ b/clang-tools-extra/pseudo/lib/grammar/LRTable.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "clang-pseudo/LRTable.h" -#include "clang-pseudo/Grammar.h" +#include "clang-pseudo/grammar/LRTable.h" +#include "clang-pseudo/grammar/Grammar.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" @@ -25,8 +25,6 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LRTable::Action &A) { return OS << llvm::formatv("reduce by rule {0}", A.getReduceRule()); case LRTable::Action::GoTo: return OS << llvm::formatv("go to state {0}", A.getGoToState()); - case LRTable::Action::Accept: - return OS << "acc"; case LRTable::Action::Sentinel: llvm_unreachable("unexpected Sentinel action kind!"); } @@ -34,27 +32,21 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LRTable::Action &A) { } std::string LRTable::dumpStatistics() const { - StateID NumOfStates = 0; - for (StateID It : States) - NumOfStates = std::max(It, NumOfStates); return llvm::formatv(R"( Statistics of the LR parsing table: number of states: {0} number of actions: {1} size of the table (bytes): {2} )", - NumOfStates, Actions.size(), bytes()) + StateOffset.size() - 1, Actions.size(), bytes()) .str(); } std::string LRTable::dumpForTests(const Grammar &G) const { std::string Result; llvm::raw_string_ostream OS(Result); - StateID MaxState = 0; - for (StateID It : States) - MaxState = std::max(MaxState, It); OS << "LRTable:\n"; - for (StateID S = 0; S <= MaxState; ++S) { + for (StateID S = 0; S < StateOffset.size() - 1; ++S) { OS << llvm::formatv("State {0}\n", S); for (uint16_t Terminal = 0; Terminal < NumTerminals; ++Terminal) { SymbolID TokID = tokenSymbol(static_cast(Terminal)); @@ -66,8 +58,6 @@ std::string LRTable::dumpForTests(const Grammar &G) const { OS.indent(4) << llvm::formatv("'{0}': reduce by rule {1} '{2}'\n", G.symbolName(TokID), A.getReduceRule(), G.dumpRule(A.getReduceRule())); - else if (A.kind() == LRTable::Action::Accept) - OS.indent(4) << llvm::formatv("'{0}': accept\n", G.symbolName(TokID)); } } for (SymbolID NontermID = 0; NontermID < G.table().Nonterminals.size(); @@ -97,26 +87,22 @@ LRTable::StateID LRTable::getGoToState(StateID State, } llvm::ArrayRef LRTable::find(StateID Src, SymbolID ID) const { - size_t Idx = isToken(ID) ? static_cast(symbolToToken(ID)) : ID; - assert(isToken(ID) ? Idx + 1 < TerminalOffset.size() - : Idx + 1 < NontermOffset.size()); - std::pair TargetStateRange = - isToken(ID) ? std::make_pair(TerminalOffset[Idx], TerminalOffset[Idx + 1]) - : std::make_pair(NontermOffset[Idx], NontermOffset[Idx + 1]); - auto TargetedStates = - llvm::makeArrayRef(States.data() + TargetStateRange.first, - States.data() + TargetStateRange.second); + assert(Src + 1u < StateOffset.size()); + std::pair Range = + std::make_pair(StateOffset[Src], StateOffset[Src + 1]); + auto SymbolRange = llvm::makeArrayRef(Symbols.data() + Range.first, + Symbols.data() + Range.second); - assert(llvm::is_sorted(TargetedStates) && - "subrange of the StateIdx should be sorted!"); - const LRTable::StateID *Start = llvm::partition_point( - TargetedStates, [&Src](LRTable::StateID S) { return S < Src; }); - if (Start == TargetedStates.end()) + assert(llvm::is_sorted(SymbolRange) && + "subrange of the Symbols should be sorted!"); + const LRTable::StateID *Start = + llvm::partition_point(SymbolRange, [&ID](SymbolID S) { return S < ID; }); + if (Start == SymbolRange.end()) return {}; const LRTable::StateID *End = Start; - while (End != TargetedStates.end() && *End == Src) + while (End != SymbolRange.end() && *End == ID) ++End; - return llvm::makeArrayRef(&Actions[Start - States.data()], + return llvm::makeArrayRef(&Actions[Start - Symbols.data()], /*length=*/End - Start); } diff --git a/clang-tools-extra/pseudo/lib/grammar/LRTableBuild.cpp b/clang-tools-extra/pseudo/lib/grammar/LRTableBuild.cpp index 827eb986ab226..69251142ca134 100644 --- a/clang-tools-extra/pseudo/lib/grammar/LRTableBuild.cpp +++ b/clang-tools-extra/pseudo/lib/grammar/LRTableBuild.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// -#include "clang-pseudo/Grammar.h" -#include "clang-pseudo/LRGraph.h" -#include "clang-pseudo/LRTable.h" +#include "clang-pseudo/grammar/Grammar.h" +#include "clang-pseudo/grammar/LRGraph.h" +#include "clang-pseudo/grammar/LRTable.h" #include "clang/Basic/TokenKinds.h" #include @@ -44,7 +44,7 @@ class LRTable::Builder { : StartStates(StartStates) {} bool insert(Entry E) { return Entries.insert(std::move(E)).second; } - LRTable build(const GrammarTable >) && { + LRTable build(const GrammarTable >, unsigned NumStates) && { // E.g. given the following parsing table with 3 states and 3 terminals: // // a b c @@ -55,44 +55,34 @@ class LRTable::Builder { // +-------+----+-------+-+ // // The final LRTable: - // - TerminalOffset: [a] = 0, [b] = 1, [c] = 4, [d] = 4 (d is a sentinel) - // - States: [ 1, 0, 0, 2] - // Actions: [ acc, s0, r0, r1] - // ~~~ corresponding range for terminal a - // ~~~~~~~~~~ corresponding range for terminal b - // First step, we sort all entries by (Symbol, State, Action). + // - StateOffset: [s0] = 0, [s1] = 2, [s2] = 3, [sentinel] = 4 + // - Symbols: [ b, b, a, b] + // Actions: [ s0, r0, acc, r1] + // ~~~~~~ range for state 0 + // ~~~~ range for state 1 + // ~~ range for state 2 + // First step, we sort all entries by (State, Symbol, Action). std::vector Sorted(Entries.begin(), Entries.end()); llvm::sort(Sorted, [](const Entry &L, const Entry &R) { - return std::forward_as_tuple(L.Symbol, L.State, L.Act.opaque()) < - std::forward_as_tuple(R.Symbol, R.State, R.Act.opaque()); + return std::forward_as_tuple(L.State, L.Symbol, L.Act.opaque()) < + std::forward_as_tuple(R.State, R.Symbol, R.Act.opaque()); }); LRTable Table; Table.Actions.reserve(Sorted.size()); - Table.States.reserve(Sorted.size()); + Table.Symbols.reserve(Sorted.size()); // We are good to finalize the States and Actions. for (const auto &E : Sorted) { Table.Actions.push_back(E.Act); - Table.States.push_back(E.State); + Table.Symbols.push_back(E.Symbol); } // Initialize the terminal and nonterminal offset, all ranges are empty by // default. - Table.TerminalOffset = std::vector(GT.Terminals.size() + 1, 0); - Table.NontermOffset = std::vector(GT.Nonterminals.size() + 1, 0); + Table.StateOffset = std::vector(NumStates + 1, 0); size_t SortedIndex = 0; - for (SymbolID NonterminalID = 0; NonterminalID < Table.NontermOffset.size(); - ++NonterminalID) { - Table.NontermOffset[NonterminalID] = SortedIndex; - while (SortedIndex < Sorted.size() && - Sorted[SortedIndex].Symbol == NonterminalID) - ++SortedIndex; - } - for (size_t Terminal = 0; Terminal < Table.TerminalOffset.size(); - ++Terminal) { - Table.TerminalOffset[Terminal] = SortedIndex; - while (SortedIndex < Sorted.size() && - Sorted[SortedIndex].Symbol == - tokenSymbol(static_cast(Terminal))) + for (StateID State = 0; State < Table.StateOffset.size(); ++State) { + Table.StateOffset[State] = SortedIndex; + while (SortedIndex < Sorted.size() && Sorted[SortedIndex].State == State) ++SortedIndex; } Table.StartStates = std::move(StartStates); @@ -106,10 +96,13 @@ class LRTable::Builder { LRTable LRTable::buildForTests(const GrammarTable >, llvm::ArrayRef Entries) { + StateID MaxState = 0; + for (const auto &Entry : Entries) + MaxState = std::max(MaxState, Entry.State); Builder Build({}); for (const Entry &E : Entries) Build.insert(E); - return std::move(Build).build(GT); + return std::move(Build).build(GT, /*NumStates=*/MaxState + 1); } LRTable LRTable::buildSLR(const Grammar &G) { @@ -124,11 +117,11 @@ LRTable LRTable::buildSLR(const Grammar &G) { auto FollowSets = followSets(G); for (StateID SID = 0; SID < Graph.states().size(); ++SID) { for (const Item &I : Graph.states()[SID].Items) { - // If we've just parsed the start symbol, we can accept the input. - if (G.lookupRule(I.rule()).Target == G.underscore() && !I.hasNext()) { - Build.insert({SID, tokenSymbol(tok::eof), Action::accept(I.rule())}); + // If we've just parsed the start symbol, this means we successfully parse + // the input. We don't add the reduce action of `_ := start_symbol` in the + // LRTable (the GLR parser handles it specifically). + if (G.lookupRule(I.rule()).Target == G.underscore() && !I.hasNext()) continue; - } if (!I.hasNext()) { // If we've reached the end of a rule A := ..., then we can reduce if // the next token is in the follow set of A. @@ -139,7 +132,7 @@ LRTable LRTable::buildSLR(const Grammar &G) { } } } - return std::move(Build).build(G.table()); + return std::move(Build).build(G.table(), Graph.states().size()); } } // namespace pseudo diff --git a/clang-tools-extra/pseudo/test/.clang-format b/clang-tools-extra/pseudo/test/.clang-format new file mode 100644 index 0000000000000..e3845288a2aec --- /dev/null +++ b/clang-tools-extra/pseudo/test/.clang-format @@ -0,0 +1 @@ +DisableFormat: true diff --git a/clang-tools-extra/pseudo/test/cxx/empty-member-spec.cpp b/clang-tools-extra/pseudo/test/cxx/empty-member-spec.cpp new file mode 100644 index 0000000000000..6d7a6823d0bf0 --- /dev/null +++ b/clang-tools-extra/pseudo/test/cxx/empty-member-spec.cpp @@ -0,0 +1,13 @@ +// RUN: clang-pseudo -grammar=%cxx-bnf-file -source=%s --print-forest | FileCheck %s +class Foo { +public: +}; +// CHECK: decl-specifier-seq~class-specifier := class-head { member-specification } +// CHECK-NEXT: ├─class-head := class-key class-head-name +// CHECK-NEXT: │ ├─class-key~CLASS := tok[0] +// CHECK-NEXT: │ └─class-head-name~IDENTIFIER := tok[1] +// CHECK-NEXT: ├─{ := tok[2] +// CHECK-NEXT: ├─member-specification := access-specifier : +// CHECK-NEXT: │ ├─access-specifier~PUBLIC := tok[3] +// CHECK-NEXT: │ └─: := tok[4] +// CHECK-NEXT: └─} := tok[5] diff --git a/clang-tools-extra/pseudo/test/cxx/keyword.cpp b/clang-tools-extra/pseudo/test/cxx/keyword.cpp new file mode 100644 index 0000000000000..b58c250c763f0 --- /dev/null +++ b/clang-tools-extra/pseudo/test/cxx/keyword.cpp @@ -0,0 +1,12 @@ +// RUN: clang-pseudo -grammar=%cxx-bnf-file -source=%s --print-forest | FileCheck %s +bool operator<(); +// CHECK: translation-unit~simple-declaration := decl-specifier-seq init-declarator-list ; +// CHECK-NEXT: ├─decl-specifier-seq~BOOL +// CHECK-NEXT: ├─init-declarator-list~noptr-declarator := noptr-declarator parameters-and-qualifiers +// CHECK-NEXT: │ ├─noptr-declarator~operator-function-id := OPERATOR operator-name +// CHECK-NEXT: │ │ ├─OPERATOR +// CHECK-NEXT: │ │ └─operator-name~< +// CHECK-NEXT: │ └─parameters-and-qualifiers := ( ) +// CHECK-NEXT: │ ├─( +// CHECK-NEXT: │ └─) +// CHECK-NEXT: └─; diff --git a/clang-tools-extra/pseudo/test/cxx/parameter-decl-clause.cpp b/clang-tools-extra/pseudo/test/cxx/parameter-decl-clause.cpp new file mode 100644 index 0000000000000..7de65687e1d15 --- /dev/null +++ b/clang-tools-extra/pseudo/test/cxx/parameter-decl-clause.cpp @@ -0,0 +1,14 @@ +// RUN: clang-pseudo -grammar=%cxx-bnf-file -source=%s --print-forest | FileCheck %s +void foo2(int, ...); +// CHECK: translation-unit~simple-declaration := decl-specifier-seq init-declarator-list ; +// CHECK-NEXT: ├─decl-specifier-seq~VOID := +// CHECK-NEXT: ├─init-declarator-list~noptr-declarator := noptr-declarator parameters-and-qualifiers +// CHECK-NEXT: │ ├─noptr-declarator~IDENTIFIER := +// CHECK-NEXT: │ └─parameters-and-qualifiers := ( parameter-declaration-clause ) +// CHECK-NEXT: │ ├─( := +// CHECK-NEXT: │ ├─parameter-declaration-clause := parameter-declaration-list , ... +// CHECK-NEXT: │ │ ├─parameter-declaration-list~INT := +// CHECK-NEXT: │ │ ├─, := +// CHECK-NEXT: │ │ └─... := +// CHECK-NEXT: │ └─) := +// CHECK-NEXT: └─; := diff --git a/clang-tools-extra/pseudo/test/cxx/predefined-identifier.cpp b/clang-tools-extra/pseudo/test/cxx/predefined-identifier.cpp new file mode 100644 index 0000000000000..1a05672835a74 --- /dev/null +++ b/clang-tools-extra/pseudo/test/cxx/predefined-identifier.cpp @@ -0,0 +1,5 @@ +// RUN: clang-pseudo -grammar=%cxx-bnf-file -source=%s --print-forest | FileCheck %s +void s() { + __func__; + // CHECK: expression~__FUNC__ := tok[5] +} diff --git a/clang-tools-extra/pseudo/test/cxx/template-empty-type-parameter.cpp b/clang-tools-extra/pseudo/test/cxx/template-empty-type-parameter.cpp new file mode 100644 index 0000000000000..e8f48c64d79f3 --- /dev/null +++ b/clang-tools-extra/pseudo/test/cxx/template-empty-type-parameter.cpp @@ -0,0 +1,3 @@ +// RUN: clang-pseudo -grammar=%cxx-bnf-file -source=%s --print-forest | FileCheck %s +template struct MatchParents; +// CHECK: template-parameter-list~TYPENAME := tok[2] diff --git a/clang-tools-extra/pseudo/test/cxx/unsized-array.cpp b/clang-tools-extra/pseudo/test/cxx/unsized-array.cpp new file mode 100644 index 0000000000000..52179e0e2dd41 --- /dev/null +++ b/clang-tools-extra/pseudo/test/cxx/unsized-array.cpp @@ -0,0 +1,7 @@ +// RUN: clang-pseudo -grammar=%cxx-bnf-file -source=%s --print-forest | FileCheck %s +void s(int[]); +// CHECK: parameter-declaration-clause~parameter-declaration := decl-specifier-seq abstract-declarator +// CHECK-NEXT: ├─decl-specifier-seq~INT := tok[3] +// CHECK-NEXT: └─abstract-declarator~noptr-abstract-declarator := [ ] +// CHECK-NEXT: ├─[ := tok[4] +// CHECK-NEXT: └─] := tok[5] diff --git a/clang-tools-extra/pseudo/test/glr.cpp b/clang-tools-extra/pseudo/test/glr.cpp index 8f58f6f894e59..8817462d7d83e 100644 --- a/clang-tools-extra/pseudo/test/glr.cpp +++ b/clang-tools-extra/pseudo/test/glr.cpp @@ -21,15 +21,3 @@ void foo() { // CHECK-NEXT: │ └─ptr-declarator~IDENTIFIER := tok[7] // CHECK-NEXT: └─; := tok[8] } - -bool operator<(); -// CHECK: declaration~simple-declaration := decl-specifier-seq init-declarator-list ; -// CHECK-NEXT: ├─decl-specifier-seq~BOOL -// CHECK-NEXT: ├─init-declarator-list~noptr-declarator := noptr-declarator parameters-and-qualifiers -// CHECK-NEXT: │ ├─noptr-declarator~operator-function-id := OPERATOR operator-name -// CHECK-NEXT: │ │ ├─OPERATOR -// CHECK-NEXT: │ │ └─operator-name~< -// CHECK-NEXT: │ └─parameters-and-qualifiers := ( ) -// CHECK-NEXT: │ ├─( -// CHECK-NEXT: │ └─) -// CHECK-NEXT: └─; diff --git a/clang-tools-extra/pseudo/test/lr-build-basic.test b/clang-tools-extra/pseudo/test/lr-build-basic.test index 5c017fa0e4dae..36a86ecd9f1f8 100644 --- a/clang-tools-extra/pseudo/test/lr-build-basic.test +++ b/clang-tools-extra/pseudo/test/lr-build-basic.test @@ -22,7 +22,6 @@ id := IDENTIFIER # TABLE-NEXT: 'expr': go to state 1 # TABLE-NEXT: 'id': go to state 2 # TABLE-NEXT: State 1 -# TABLE-NEXT: 'EOF': accept # TABLE-NEXT: State 2 # TABLE-NEXT: 'EOF': reduce by rule 1 'expr := id' # TABLE-NEXT: State 3 diff --git a/clang-tools-extra/pseudo/test/lr-build-conflicts.test b/clang-tools-extra/pseudo/test/lr-build-conflicts.test index aefa905413bd5..916589572ae48 100644 --- a/clang-tools-extra/pseudo/test/lr-build-conflicts.test +++ b/clang-tools-extra/pseudo/test/lr-build-conflicts.test @@ -33,7 +33,6 @@ expr := IDENTIFIER # TABLE-NEXT: 'IDENTIFIER': shift state 2 # TABLE-NEXT: 'expr': go to state 1 # TABLE-NEXT: State 1 -# TABLE-NEXT: 'EOF': accept # TABLE-NEXT: '-': shift state 3 # TABLE-NEXT: State 2 # TABLE-NEXT: 'EOF': reduce by rule 1 'expr := IDENTIFIER' diff --git a/clang-tools-extra/pseudo/tool/ClangPseudo.cpp b/clang-tools-extra/pseudo/tool/ClangPseudo.cpp index 1d3ab19b3c09d..a9c972abb77e8 100644 --- a/clang-tools-extra/pseudo/tool/ClangPseudo.cpp +++ b/clang-tools-extra/pseudo/tool/ClangPseudo.cpp @@ -9,10 +9,10 @@ #include "clang-pseudo/Bracket.h" #include "clang-pseudo/DirectiveTree.h" #include "clang-pseudo/GLR.h" -#include "clang-pseudo/Grammar.h" -#include "clang-pseudo/LRGraph.h" -#include "clang-pseudo/LRTable.h" #include "clang-pseudo/Token.h" +#include "clang-pseudo/grammar/Grammar.h" +#include "clang-pseudo/grammar/LRGraph.h" +#include "clang-pseudo/grammar/LRTable.h" #include "clang/Basic/LangOptions.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" @@ -111,6 +111,8 @@ int main(int argc, char *argv[]) { auto LRTable = clang::pseudo::LRTable::buildSLR(*G); if (PrintTable) llvm::outs() << LRTable.dumpForTests(*G); + if (PrintStatistics) + llvm::outs() << LRTable.dumpStatistics(); if (ParseableStream) { clang::pseudo::ForestArena Arena; @@ -132,7 +134,7 @@ int main(int argc, char *argv[]) { llvm::outs() << "Forest bytes: " << Arena.bytes() << " nodes: " << Arena.nodeCount() << "\n"; llvm::outs() << "GSS bytes: " << GSS.bytes() - << " nodes: " << GSS.nodeCount() << "\n"; + << " nodes: " << GSS.nodesCreated() << "\n"; } } } diff --git a/clang-tools-extra/pseudo/unittests/CMakeLists.txt b/clang-tools-extra/pseudo/unittests/CMakeLists.txt index 2185e4e4c146b..70796195d9bed 100644 --- a/clang-tools-extra/pseudo/unittests/CMakeLists.txt +++ b/clang-tools-extra/pseudo/unittests/CMakeLists.txt @@ -1,6 +1,5 @@ set(LLVM_LINK_COMPONENTS Support - TestingSupport ) add_custom_target(ClangPseudoUnitTests) @@ -24,4 +23,5 @@ target_link_libraries(ClangPseudoTests PRIVATE clangPseudo clangPseudoGrammar + LLVMTestingSupport ) diff --git a/clang-tools-extra/pseudo/unittests/GLRTest.cpp b/clang-tools-extra/pseudo/unittests/GLRTest.cpp index f885094111a6c..d9555a8d56dd9 100644 --- a/clang-tools-extra/pseudo/unittests/GLRTest.cpp +++ b/clang-tools-extra/pseudo/unittests/GLRTest.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "clang-pseudo/GLR.h" -#include "clang-pseudo/Grammar.h" +#include "clang-pseudo/grammar/Grammar.h" #include "clang-pseudo/Token.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/TokenKinds.h" @@ -393,6 +393,51 @@ TEST_F(GLRTest, GLRReduceOrder) { "[ 0, end) └─IDENTIFIER := tok[0]\n"); } +TEST_F(GLRTest, NoExplicitAccept) { + build(R"bnf( + _ := test + + test := IDENTIFIER test + test := IDENTIFIER + )bnf"); + clang::LangOptions LOptions; + // Given the following input, and the grammar above, we perform two reductions + // of the nonterminal `test` when the next token is `eof`, verify that the + // parser stops at the right state. + const TokenStream &Tokens = cook(lex("id id", LOptions), LOptions); + auto LRTable = LRTable::buildSLR(*G); + + const ForestNode &Parsed = + glrParse(Tokens, {*G, LRTable, Arena, GSStack}, id("test")); + EXPECT_EQ(Parsed.dumpRecursive(*G), + "[ 0, end) test := IDENTIFIER test\n" + "[ 0, 1) ├─IDENTIFIER := tok[0]\n" + "[ 1, end) └─test := IDENTIFIER\n" + "[ 1, end) └─IDENTIFIER := tok[1]\n"); +} + +TEST(GSSTest, GC) { + // ┌-A-┬-AB + // ├-B-┘ + // Root-+-C + // ├-D + // └-E + GSS GSStack; + auto *Root = GSStack.addNode(0, nullptr, {}); + auto *A = GSStack.addNode(0, nullptr, {Root}); + auto *B = GSStack.addNode(0, nullptr, {Root}); + auto *C = GSStack.addNode(0, nullptr, {Root}); + auto *D = GSStack.addNode(0, nullptr, {Root}); + auto *AB = GSStack.addNode(0, nullptr, {A, B}); + + EXPECT_EQ(1u, GSStack.gc({AB, C})) << "D is destroyed"; + EXPECT_EQ(0u, GSStack.gc({AB, C})) << "D is already gone"; + auto *E = GSStack.addNode(0, nullptr, {Root}); + EXPECT_EQ(D, E) << "Storage of GCed node D is reused for E"; + EXPECT_EQ(3u, GSStack.gc({A, E})) << "Destroys B, AB, C"; + EXPECT_EQ(1u, GSStack.gc({E})) << "Destroys A"; +} + } // namespace } // namespace pseudo } // namespace clang diff --git a/clang-tools-extra/pseudo/unittests/GrammarTest.cpp b/clang-tools-extra/pseudo/unittests/GrammarTest.cpp index 0f71c47019058..284d91e9bba15 100644 --- a/clang-tools-extra/pseudo/unittests/GrammarTest.cpp +++ b/clang-tools-extra/pseudo/unittests/GrammarTest.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "clang-pseudo/Grammar.h" +#include "clang-pseudo/grammar/Grammar.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include @@ -99,6 +99,22 @@ TEST_F(GrammarTest, RuleIDSorted) { EXPECT_LT(ruleFor("x"), ruleFor("_")); } +TEST_F(GrammarTest, Annotation) { + build(R"bnf( + _ := x + + x := y [guard=value] + y := IDENTIFIER [guard=final] + + )bnf"); + ASSERT_TRUE(Diags.empty()); + EXPECT_EQ(G->lookupRule(ruleFor("_")).Guard, 0); + EXPECT_GT(G->lookupRule(ruleFor("x")).Guard, 0); + EXPECT_GT(G->lookupRule(ruleFor("y")).Guard, 0); + EXPECT_NE(G->lookupRule(ruleFor("x")).Guard, + G->lookupRule(ruleFor("y")).Guard); +} + TEST_F(GrammarTest, Diagnostics) { build(R"cpp( _ := ,_opt @@ -110,6 +126,8 @@ TEST_F(GrammarTest, Diagnostics) { # cycle a := b b := a + + _ := IDENTIFIER [unknown=value] )cpp"); EXPECT_EQ(G->underscore(), id("_")); @@ -120,7 +138,8 @@ TEST_F(GrammarTest, Diagnostics) { "Failed to parse 'invalid': no separator :=", "Token-like name IDENFIFIE is used as a nonterminal", "No rules for nonterminal: IDENFIFIE", - "The grammar contains a cycle involving symbol a")); + "The grammar contains a cycle involving symbol a", + "Unknown attribute 'unknown'")); } TEST_F(GrammarTest, FirstAndFollowSets) { diff --git a/clang-tools-extra/pseudo/unittests/LRTableTest.cpp b/clang-tools-extra/pseudo/unittests/LRTableTest.cpp index 9823159e5517a..f4ba9be49db1f 100644 --- a/clang-tools-extra/pseudo/unittests/LRTableTest.cpp +++ b/clang-tools-extra/pseudo/unittests/LRTableTest.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "clang-pseudo/LRTable.h" -#include "clang-pseudo/Grammar.h" +#include "clang-pseudo/grammar/LRTable.h" +#include "clang-pseudo/grammar/Grammar.h" #include "clang/Basic/TokenKinds.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -33,7 +33,7 @@ TEST(LRTable, Builder) { std::vector Entries = { {/* State */ 0, tokenSymbol(tok::semi), Action::shift(0)}, {/* State */ 0, tokenSymbol(tok::semi), Action::reduce(0)}, - {/* State */ 1, tokenSymbol(tok::eof), Action::accept(2)}, + {/* State */ 1, tokenSymbol(tok::eof), Action::reduce(2)}, {/* State */ 2, tokenSymbol(tok::semi), Action::reduce(1)}}; GrammarTable GT; LRTable T = LRTable::buildForTests(GT, Entries); @@ -41,7 +41,7 @@ TEST(LRTable, Builder) { EXPECT_THAT(T.find(0, tokenSymbol(tok::semi)), UnorderedElementsAre(Action::shift(0), Action::reduce(0))); EXPECT_THAT(T.find(1, tokenSymbol(tok::eof)), - UnorderedElementsAre(Action::accept(2))); + UnorderedElementsAre(Action::reduce(2))); EXPECT_THAT(T.find(1, tokenSymbol(tok::semi)), IsEmpty()); EXPECT_THAT(T.find(2, tokenSymbol(tok::semi)), UnorderedElementsAre(Action::reduce(1))); diff --git a/clang-tools-extra/test/clang-tidy/check_clang_tidy.py b/clang-tools-extra/test/clang-tidy/check_clang_tidy.py index e6a4a8e505492..4ce6cd4e65de8 100755 --- a/clang-tools-extra/test/clang-tidy/check_clang_tidy.py +++ b/clang-tools-extra/test/clang-tidy/check_clang_tidy.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # #===- check_clang_tidy.py - ClangTidy Test Helper ------------*- python -*--===# # diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone-use-after-move.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone-use-after-move.cpp index e26db0f6793e0..281f2083857ad 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone-use-after-move.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-use-after-move.cpp @@ -152,6 +152,13 @@ void simple() { // CHECK-NOTES: [[@LINE-3]]:15: note: move occurred here } +// Don't flag a move-to-self. +void selfMove() { + A a; + a = std::move(a); + a.foo(); +} + // A warning should only be emitted for one use-after-move. void onlyFlagOneUseAfterMove() { A a; @@ -416,6 +423,13 @@ void lambdas() { auto lambda = [&]() { a.foo(); }; std::move(a); } + { + A a; + auto lambda = [a = std::move(a)] { a.foo(); }; + a.foo(); + // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved + // CHECK-NOTES: [[@LINE-3]]:24: note: move occurred here + } } // Use-after-moves are detected in uninstantiated templates if the moved type diff --git a/clang-tools-extra/test/clang-tidy/checkers/cert-oop57-cpp.cpp b/clang-tools-extra/test/clang-tidy/checkers/cert-oop57-cpp.cpp index a5a38734ce6ae..880c5c3a1c9fe 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cert-oop57-cpp.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cert-oop57-cpp.cpp @@ -88,3 +88,17 @@ void baz(const NonTrivial &Other) { mymemcmp(&Data, &Other, sizeof(Data)); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: consider using comparison operators instead of calling 'mymemcmp' } + +void nonNullSetValue() { + NonTrivial Data; + // Check non-null-valued second argument. + std::memset(&Data, 1, sizeof(Data)); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'memset' on a non-trivially default constructible class is undefined +} + +void nonLiteralSetValue(char C) { + NonTrivial Data; + // Check non-literal second argument. + std::memset(&Data, C, sizeof(Data)); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'memset' on a non-trivially default constructible class is undefined +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize-macro-to-enum.c b/clang-tools-extra/test/clang-tidy/checkers/modernize-macro-to-enum.c new file mode 100644 index 0000000000000..c15e04510460e --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize-macro-to-enum.c @@ -0,0 +1,16 @@ +// RUN: %check_clang_tidy %s modernize-macro-to-enum %t + +// C requires enum values to fit into an int. +#define TOO_BIG1 1L +#define TOO_BIG2 1UL +#define TOO_BIG3 1LL +#define TOO_BIG4 1ULL + +// C forbids comma operator in initializing expressions. +#define BAD_OP 1, 2 + +#define SIZE_OK1 1 +#define SIZE_OK2 1U +// CHECK-MESSAGES: :[[@LINE-2]]:1: warning: replace macro with enum [modernize-macro-to-enum] +// CHECK-MESSAGES: :[[@LINE-3]]:9: warning: macro 'SIZE_OK1' defines an integral constant; prefer an enum instead +// CHECK-MESSAGES: :[[@LINE-3]]:9: warning: macro 'SIZE_OK2' defines an integral constant; prefer an enum instead diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize-macro-to-enum.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize-macro-to-enum.cpp index 06ed2d3f5ca8a..4a697930d0f09 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize-macro-to-enum.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize-macro-to-enum.cpp @@ -213,6 +213,13 @@ // CHECK-FIXES-NEXT: COMPLEX_PAREN6 = ((+1)) // CHECK-FIXES-NEXT: }; +#define GOOD_COMMA (1, 2) +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: replace macro with enum +// CHECK-MESSAGES: :[[@LINE-2]]:9: warning: macro 'GOOD_COMMA' defines an integral constant; prefer an enum instead +// CHECK-FIXES: enum { +// CHECK-FIXES-NEXT: GOOD_COMMA = (1, 2) +// CHECK-FIXES-NEXT: }; + // Macros appearing in conditional expressions can't be replaced // by enums. #define USE_FOO 1 @@ -322,6 +329,9 @@ inline void used_ifndef() {} #define EPS2 1e5 #define EPS3 1. +// Ignore macros invoking comma operator unless they are inside parens. +#define BAD_COMMA 1, 2 + extern void draw(unsigned int Color); void f() diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize-use-emplace.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize-use-emplace.cpp index 4e74d49d33fb7..b869816f8d1da 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize-use-emplace.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize-use-emplace.cpp @@ -10,15 +10,36 @@ namespace std { template -class initializer_list -{ +class initializer_list { public: initializer_list() noexcept {} }; +template +class pair { +public: + pair() = default; + pair(const pair &) = default; + pair(pair &&) = default; + + pair(const T1 &, const T2 &) {} + pair(T1 &&, T2 &&) {} + + template + pair(const pair &){}; + template + pair(pair &&){}; +}; + template class vector { public: + using value_type = T; + + class iterator {}; + class const_iterator {}; + const_iterator begin() { return const_iterator{}; } + vector() = default; vector(initializer_list) {} @@ -27,54 +48,230 @@ class vector { template void emplace_back(Args &&... args){}; + template + iterator emplace(const_iterator pos, Args &&...args){}; ~vector(); }; + template class list { public: + using value_type = T; + + class iterator {}; + class const_iterator {}; + const_iterator begin() { return const_iterator{}; } + void push_back(const T &) {} void push_back(T &&) {} + template + iterator emplace(const_iterator pos, Args &&...args){}; template void emplace_back(Args &&... args){}; + template + void emplace_front(Args &&...args){}; ~list(); }; template class deque { public: + using value_type = T; + + class iterator {}; + class const_iterator {}; + const_iterator begin() { return const_iterator{}; } + void push_back(const T &) {} void push_back(T &&) {} + template + iterator emplace(const_iterator pos, Args &&...args){}; template void emplace_back(Args &&... args){}; + template + void emplace_front(Args &&...args){}; ~deque(); }; -template struct remove_reference { using type = T; }; -template struct remove_reference { using type = T; }; -template struct remove_reference { using type = T; }; +template +class forward_list { +public: + using value_type = T; + + class iterator {}; + class const_iterator {}; + const_iterator begin() { return const_iterator{}; } + + template + void emplace_front(Args &&...args){}; + template + iterator emplace_after(const_iterator pos, Args &&...args){}; +}; -template class pair { +template +class set { public: - pair() = default; - pair(const pair &) = default; - pair(pair &&) = default; + using value_type = T; - pair(const T1 &, const T2 &) {} - pair(T1 &&, T2 &&) {} + class iterator {}; + class const_iterator {}; + const_iterator begin() { return const_iterator{}; } + + template + void emplace(Args &&...args){}; + template + iterator emplace_hint(const_iterator pos, Args &&...args){}; +}; + +template +class map { +public: + using value_type = std::pair; + + class iterator {}; + class const_iterator {}; + const_iterator begin() { return const_iterator{}; } + + template + void emplace(Args &&...args){}; + template + iterator emplace_hint(const_iterator pos, Args &&...args){}; +}; + +template +class multiset { +public: + using value_type = T; + + class iterator {}; + class const_iterator {}; + const_iterator begin() { return const_iterator{}; } + + template + void emplace(Args &&...args){}; + template + iterator emplace_hint(const_iterator pos, Args &&...args){}; +}; + +template +class multimap { +public: + using value_type = std::pair; + + class iterator {}; + class const_iterator {}; + const_iterator begin() { return const_iterator{}; } + + template + void emplace(Args &&...args){}; + template + iterator emplace_hint(const_iterator pos, Args &&...args){}; +}; + +template +class unordered_set { +public: + using value_type = T; + + class iterator {}; + class const_iterator {}; + const_iterator begin() { return const_iterator{}; } + + template + void emplace(Args &&...args){}; + template + iterator emplace_hint(const_iterator pos, Args &&...args){}; +}; + +template +class unordered_map { +public: + using value_type = std::pair; + + class iterator {}; + class const_iterator {}; + const_iterator begin() { return const_iterator{}; } + + template + void emplace(Args &&...args){}; + template + iterator emplace_hint(const_iterator pos, Args &&...args){}; +}; + +template +class unordered_multiset { +public: + using value_type = T; + + class iterator {}; + class const_iterator {}; + const_iterator begin() { return const_iterator{}; } + + template + void emplace(Args &&...args){}; + template + iterator emplace_hint(const_iterator pos, Args &&...args){}; +}; + +template +class unordered_multimap { +public: + using value_type = std::pair; + + class iterator {}; + class const_iterator {}; + const_iterator begin() { return const_iterator{}; } + + template + void emplace(Args &&...args){}; + template + iterator emplace_hint(const_iterator pos, Args &&...args){}; +}; + +template +class stack { +public: + using value_type = T; + + template + void emplace(Args &&...args){}; +}; - template pair(const pair &){}; - template pair(pair &&){}; +template +class queue { +public: + using value_type = T; + + template + void emplace(Args &&...args){}; }; +template +class priority_queue { +public: + using value_type = T; + + template + void emplace(Args &&...args){}; +}; + +template +struct remove_reference { using type = T; }; +template +struct remove_reference { using type = T; }; +template +struct remove_reference { using type = T; }; + template pair::type, typename remove_reference::type> make_pair(T1 &&, T2 &&) { return {}; }; -template class tuple { +template +class tuple { public: tuple() = default; tuple(const tuple &) = default; @@ -83,13 +280,17 @@ template class tuple { tuple(const Ts &...) {} tuple(Ts &&...) {} - template tuple(const tuple &){}; - template tuple(tuple &&) {} + template + tuple(const tuple &){}; + template + tuple(tuple &&) {} - template tuple(const pair &) { + template + tuple(const pair &) { static_assert(sizeof...(Ts) == 2, "Wrong tuple size"); }; - template tuple(pair &&) { + template + tuple(pair &&) { static_assert(sizeof...(Ts) == 2, "Wrong tuple size"); }; }; @@ -118,7 +319,7 @@ class LikeASmallVector { void emplace_back(Args &&... args){}; }; -} // llvm +} // namespace llvm void testInts() { std::vector v; @@ -375,7 +576,7 @@ void testMakePair() { // make_pair cannot be removed here, as X is not constructible with two ints. struct Y { - Y(std::pair&&) {} + Y(std::pair &&) {} }; std::vector y; y.push_back(std::make_pair(2, 3)); @@ -402,7 +603,8 @@ void testMakeTuple() { } namespace test { -template struct Single { +template +struct Single { Single() = default; Single(const Single &) = default; Single(Single &&) = default; @@ -410,11 +612,15 @@ template struct Single { Single(const T &) {} Single(T &&) {} - template Single(const Single &) {} - template Single(Single &&) {} + template + Single(const Single &) {} + template + Single(Single &&) {} - template Single(const std::tuple &) {} - template Single(std::tuple &&) {} + template + Single(const std::tuple &) {} + template + Single(std::tuple &&) {} }; template @@ -605,3 +811,240 @@ void testInitializerList() { x.push_back(PairIntVector(3, {4})); x.push_back({5, {6}}); } + +class Foo { +public: + Foo(){}; + Foo(int){}; + Foo(int, int){}; + Foo(std::pair){}; + +protected: + Foo(char *) : Foo(){}; +}; + +void testSomeEmplaceCases() { + std::vector> v1; + std::vector v2; + std::unordered_map m1; + + v1.emplace_back(std::make_pair("foo", "bar")); + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back + // CHECK-FIXES: v1.emplace_back("foo", "bar"); + + char *foo = "bar"; + v1.emplace_back(std::make_pair(foo, "bar")); + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back + // CHECK-FIXES: v1.emplace_back(foo, "bar"); + + v1.emplace(v1.begin(), std::make_pair("foo", "bar")); + // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: v1.emplace(v1.begin(), "foo", "bar"); + + v2.emplace_back(Foo()); + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back + // CHECK-FIXES: v2.emplace_back(); + + v2.emplace_back(Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back + // CHECK-FIXES: v2.emplace_back(13); + + v2.emplace_back(Foo{13}); + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back + // CHECK-FIXES: v2.emplace_back(13); + + int a = 31; + v2.emplace_back(Foo(13, a)); + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back + // CHECK-FIXES: v2.emplace_back(13, a); + + v2.emplace_back(std::make_pair(3, 3)); + + m1.emplace(std::make_pair(13, "foo")); + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: m1.emplace(13, "foo"); + + std::vector> v3; + v3.emplace_back(std::pair(13, 71)); + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back + v3.emplace_back(std::make_pair(13, 71)); + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back + + std::vector> v4; + v4.emplace_back(std::tuple(13, 31, 71)); + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back + v4.emplace_back(std::make_tuple(13, 31, 71)); + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back + + std::vector> v5; + v5.emplace_back(test::Single(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back + v5.emplace_back(test::MakeSingle(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back +} + +void testAllSTLEmplacyFunctions() { + std::vector vector; + std::deque deque; + std::forward_list forward_list; + std::list list; + std::set set; + std::map map; + std::multiset multiset; + std::multimap multimap; + std::unordered_set unordered_set; + std::unordered_map unordered_map; + std::unordered_multiset unordered_multiset; + std::unordered_multimap unordered_multimap; + std::stack stack; + std::queue queue; + std::priority_queue priority_queue; + + vector.emplace_back(Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: unnecessary temporary object created while calling emplace_back + // CHECK-FIXES: vector.emplace_back(13); + + vector.emplace(vector.begin(), Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: vector.emplace(vector.begin(), 13); + + deque.emplace(deque.begin(), Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: deque.emplace(deque.begin(), 13); + + deque.emplace_front(Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: unnecessary temporary object created while calling emplace_front + // CHECK-FIXES: deque.emplace_front(13); + + deque.emplace_back(Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unnecessary temporary object created while calling emplace_back + // CHECK-FIXES: deque.emplace_back(13); + + forward_list.emplace_after(forward_list.begin(), Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:52: warning: unnecessary temporary object created while calling emplace_after + // CHECK-FIXES: forward_list.emplace_after(forward_list.begin(), 13); + + forward_list.emplace_front(Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace_front + // CHECK-FIXES: forward_list.emplace_front(13); + + list.emplace(list.begin(), Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: list.emplace(list.begin(), 13); + + list.emplace_back(Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unnecessary temporary object created while calling emplace_back + // CHECK-FIXES: list.emplace_back(13); + + list.emplace_front(Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unnecessary temporary object created while calling emplace_front + // CHECK-FIXES: list.emplace_front(13); + + set.emplace(Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: set.emplace(13); + + set.emplace_hint(set.begin(), Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: unnecessary temporary object created while calling emplace_hint + // CHECK-FIXES: set.emplace_hint(set.begin(), 13); + + map.emplace(std::make_pair(13, Foo(13))); + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: map.emplace(13, Foo(13)); + + map.emplace_hint(map.begin(), std::make_pair(13, Foo(13))); + // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: unnecessary temporary object created while calling emplace_hint + // CHECK-FIXES: map.emplace_hint(map.begin(), 13, Foo(13)); + + multiset.emplace(Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: multiset.emplace(13); + + multiset.emplace_hint(multiset.begin(), Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: unnecessary temporary object created while calling emplace_hint + // CHECK-FIXES: multiset.emplace_hint(multiset.begin(), 13); + + multimap.emplace(std::make_pair(13, Foo(13))); + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: multimap.emplace(13, Foo(13)); + + multimap.emplace_hint(multimap.begin(), std::make_pair(13, Foo(13))); + // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: unnecessary temporary object created while calling emplace_hint + // CHECK-FIXES: multimap.emplace_hint(multimap.begin(), 13, Foo(13)); + + unordered_set.emplace(Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: unordered_set.emplace(13); + + unordered_set.emplace_hint(unordered_set.begin(), Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:53: warning: unnecessary temporary object created while calling emplace_hint + // CHECK-FIXES: unordered_set.emplace_hint(unordered_set.begin(), 13); + + unordered_map.emplace(std::make_pair(13, Foo(13))); + // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: unordered_map.emplace(13, Foo(13)); + + unordered_map.emplace_hint(unordered_map.begin(), std::make_pair(13, Foo(13))); + // CHECK-MESSAGES: :[[@LINE-1]]:53: warning: unnecessary temporary object created while calling emplace_hint + // CHECK-FIXES: unordered_map.emplace_hint(unordered_map.begin(), 13, Foo(13)); + + unordered_multiset.emplace(Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: unordered_multiset.emplace(13); + unordered_multiset.emplace_hint(unordered_multiset.begin(), Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:63: warning: unnecessary temporary object created while calling emplace_hint + // CHECK-FIXES: unordered_multiset.emplace_hint(unordered_multiset.begin(), 13); + + unordered_multimap.emplace(std::make_pair(13, Foo(13))); + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: unordered_multimap.emplace(13, Foo(13)); + unordered_multimap.emplace_hint(unordered_multimap.begin(), std::make_pair(13, Foo(13))); + // CHECK-MESSAGES: :[[@LINE-1]]:63: warning: unnecessary temporary object created while calling emplace_hint + // CHECK-FIXES: unordered_multimap.emplace_hint(unordered_multimap.begin(), 13, Foo(13)); + + stack.emplace(Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: stack.emplace(13); + + queue.emplace(Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: queue.emplace(13); + + priority_queue.emplace(Foo(13)); + // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: unnecessary temporary object created while calling emplace + // CHECK-FIXES: priority_queue.emplace(13); +} + +struct Bar { +public: + Bar(){}; + void testWithPrivateAndProtectedCtor() { + std::vector vec; + + vec.emplace_back(Bar(13)); + vec.emplace_back(Bar(13, 13)); + } + +protected: + Bar(int){}; + +private: + Bar(int, int){}; +}; + +void testPossibleFalsePositives() { + struct Y { + Y(std::pair &&) {} + }; + std::vector y; + y.emplace_back(std::make_pair(2, 3)); + + std::vector> v; + v.emplace_back(std::make_pair(0, 3)); + + struct D { + D(...) {} + operator char() const { return 0; } + }; + v.emplace_back(std::make_pair(Something(), 2)); +} 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 d5578cf16f59e..96b4014025b78 100644 --- a/clang-tools-extra/test/pp-trace/pp-trace-include.cpp +++ b/clang-tools-extra/test/pp-trace/pp-trace-include.cpp @@ -51,6 +51,7 @@ // CHECK-NEXT: FileType: C_User // CHECK-NEXT: PrevFID: (getFileEntryForID failed) // CHECK-NEXT: - Callback: InclusionDirective +// CHECK-NEXT: HashLoc: "{{.*}}{{[/\\]}}pp-trace-include.cpp:3:1" // CHECK-NEXT: IncludeTok: include // CHECK-NEXT: FileName: "Inputs/Level1A.h" // CHECK-NEXT: IsAngled: false @@ -65,6 +66,7 @@ // CHECK-NEXT: FileType: C_User // CHECK-NEXT: PrevFID: (invalid) // CHECK-NEXT: - Callback: InclusionDirective +// CHECK-NEXT: HashLoc: "{{.*}}{{[/\\]}}Inputs/Level1A.h:1:1" // CHECK-NEXT: IncludeTok: include // CHECK-NEXT: FileName: "Level2A.h" // CHECK-NEXT: IsAngled: false @@ -95,6 +97,7 @@ // CHECK-NEXT: FileType: C_User // CHECK-NEXT: PrevFID: "{{.*}}{{[/\\]}}Inputs/Level1A.h" // CHECK-NEXT: - Callback: InclusionDirective +// CHECK-NEXT: HashLoc: "{{.*}}{{[/\\]}}pp-trace-include.cpp:4:1" // CHECK-NEXT: IncludeTok: include // CHECK-NEXT: FileName: "Inputs/Level1B.h" // CHECK-NEXT: IsAngled: false @@ -109,6 +112,7 @@ // CHECK-NEXT: FileType: C_User // CHECK-NEXT: PrevFID: (invalid) // CHECK-NEXT: - Callback: InclusionDirective +// CHECK-NEXT: HashLoc: "{{.*}}{{[/\\]}}Inputs/Level1B.h:1:1" // CHECK-NEXT: IncludeTok: include // CHECK-NEXT: FileName: "Level2B.h" // CHECK-NEXT: IsAngled: false diff --git a/clang-tools-extra/test/pp-trace/pp-trace-modules.cpp b/clang-tools-extra/test/pp-trace/pp-trace-modules.cpp index 028c967a4e0d8..32d6c48e5d448 100644 --- a/clang-tools-extra/test/pp-trace/pp-trace-modules.cpp +++ b/clang-tools-extra/test/pp-trace/pp-trace-modules.cpp @@ -1,5 +1,5 @@ // RUN: rm -rf %t -// RUN: pp-trace -callbacks '*,-FileChanged,-MacroDefined' %s -- -x objective-c++ -undef -target x86_64 -std=c++11 -fmodules -fmodules-cache-path=%t -I%S -I%S/Input | FileCheck --strict-whitespace %s +// RUN: pp-trace -callbacks '*,-FileChanged,-MacroDefined' %s -- -x objective-c++ -undef -target x86_64 -std=c++11 -fmodules -fcxx-modules -fmodules-cache-path=%t -I%S -I%S/Input | FileCheck --strict-whitespace %s // CHECK: --- diff --git a/clang-tools-extra/unittests/clang-tidy/ModernizeModuleTest.cpp b/clang-tools-extra/unittests/clang-tidy/ModernizeModuleTest.cpp index b772c0054de40..4a8c1c3e5f312 100644 --- a/clang-tools-extra/unittests/clang-tidy/ModernizeModuleTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/ModernizeModuleTest.cpp @@ -36,177 +36,241 @@ static std::vector tokenify(const char *Text) { return Tokens; } -static bool matchText(const char *Text) { +static bool matchText(const char *Text, bool AllowComma) { std::vector Tokens{tokenify(Text)}; - modernize::IntegralLiteralExpressionMatcher Matcher(Tokens); + modernize::IntegralLiteralExpressionMatcher Matcher(Tokens, AllowComma); return Matcher.match(); } +static modernize::LiteralSize sizeText(const char *Text) { + std::vector Tokens{tokenify(Text)}; + modernize::IntegralLiteralExpressionMatcher Matcher(Tokens, true); + if (Matcher.match()) + return Matcher.largestLiteralSize(); + return modernize::LiteralSize::Unknown; +} + +static const char *toString(modernize::LiteralSize Value) { + switch (Value) { + case modernize::LiteralSize::Int: + return "Int"; + case modernize::LiteralSize::UnsignedInt: + return "UnsignedInt"; + case modernize::LiteralSize::Long: + return "Long"; + case modernize::LiteralSize::UnsignedLong: + return "UnsignedLong"; + case modernize::LiteralSize::LongLong: + return "LongLong"; + case modernize::LiteralSize::UnsignedLongLong: + return "UnsignedLongLong"; + default: + return "Unknown"; + } +} + namespace { -struct Param { +struct MatchParam { + bool AllowComma; bool Matched; const char *Text; - friend std::ostream &operator<<(std::ostream &Str, const Param &Value) { - return Str << "Matched: " << std::boolalpha << Value.Matched << ", Text: '" - << Value.Text << "'"; + friend std::ostream &operator<<(std::ostream &Str, const MatchParam &Value) { + return Str << "Allow operator,: " << std::boolalpha << Value.AllowComma + << ", Matched: " << std::boolalpha << Value.Matched + << ", Text: '" << Value.Text << '\''; } }; -class MatcherTest : public ::testing::TestWithParam {}; +struct SizeParam { + modernize::LiteralSize Size; + const char *Text; + + friend std::ostream &operator<<(std::ostream &Str, const SizeParam &Value) { + return Str << "Size: " << toString(Value.Size) << ", Text: '" << Value.Text << '\''; + } +}; + +class MatcherTest : public ::testing::TestWithParam {}; + +class SizeTest : public ::testing::TestWithParam {}; } // namespace -static const Param Params[] = { +static const MatchParam MatchParams[] = { // Accept integral literals. - {true, "1"}, - {true, "0177"}, - {true, "0xdeadbeef"}, - {true, "0b1011"}, - {true, "'c'"}, + {true, true, "1"}, + {true, true, "0177"}, + {true, true, "0xdeadbeef"}, + {true, true, "0b1011"}, + {true, true, "'c'"}, // Reject non-integral literals. - {false, "1.23"}, - {false, "0x1p3"}, - {false, R"("string")"}, - {false, "1i"}, + {true, false, "1.23"}, + {true, false, "0x1p3"}, + {true, false, R"("string")"}, + {true, false, "1i"}, // Accept literals with these unary operators. - {true, "-1"}, - {true, "+1"}, - {true, "~1"}, - {true, "!1"}, + {true, true, "-1"}, + {true, true, "+1"}, + {true, true, "~1"}, + {true, true, "!1"}, // Reject invalid unary operators. - {false, "1-"}, - {false, "1+"}, - {false, "1~"}, - {false, "1!"}, + {true, false, "1-"}, + {true, false, "1+"}, + {true, false, "1~"}, + {true, false, "1!"}, // Accept valid binary operators. - {true, "1+1"}, - {true, "1-1"}, - {true, "1*1"}, - {true, "1/1"}, - {true, "1%2"}, - {true, "1<<1"}, - {true, "1>>1"}, - {true, "1<=>1"}, - {true, "1<1"}, - {true, "1>1"}, - {true, "1<=1"}, - {true, "1>=1"}, - {true, "1==1"}, - {true, "1!=1"}, - {true, "1&1"}, - {true, "1^1"}, - {true, "1|1"}, - {true, "1&&1"}, - {true, "1||1"}, - {true, "1+ +1"}, // A space is needed to avoid being tokenized as ++ or --. - {true, "1- -1"}, - {true, "1,1"}, + {true, true, "1+1"}, + {true, true, "1-1"}, + {true, true, "1*1"}, + {true, true, "1/1"}, + {true, true, "1%2"}, + {true, true, "1<<1"}, + {true, true, "1>>1"}, + {true, true, "1<=>1"}, + {true, true, "1<1"}, + {true, true, "1>1"}, + {true, true, "1<=1"}, + {true, true, "1>=1"}, + {true, true, "1==1"}, + {true, true, "1!=1"}, + {true, true, "1&1"}, + {true, true, "1^1"}, + {true, true, "1|1"}, + {true, true, "1&&1"}, + {true, true, "1||1"}, + {true, true, "1+ +1"}, // A space is needed to avoid being tokenized as ++ or --. + {true, true, "1- -1"}, + // Comma is only valid when inside parentheses. + {true, true, "(1,1)"}, // Reject invalid binary operators. - {false, "1+"}, - {false, "1-"}, - {false, "1*"}, - {false, "1/"}, - {false, "1%"}, - {false, "1<<"}, - {false, "1>>"}, - {false, "1<=>"}, - {false, "1<"}, - {false, "1>"}, - {false, "1<="}, - {false, "1>="}, - {false, "1=="}, - {false, "1!="}, - {false, "1&"}, - {false, "1^"}, - {false, "1|"}, - {false, "1&&"}, - {false, "1||"}, - {false, "1,"}, - {false, ",1"}, + {true, false, "1+"}, + {true, false, "1-"}, + {true, false, "1*"}, + {true, false, "1/"}, + {true, false, "1%"}, + {true, false, "1<<"}, + {true, false, "1>>"}, + {true, false, "1<=>"}, + {true, false, "1<"}, + {true, false, "1>"}, + {true, false, "1<="}, + {true, false, "1>="}, + {true, false, "1=="}, + {true, false, "1!="}, + {true, false, "1&"}, + {true, false, "1^"}, + {true, false, "1|"}, + {true, false, "1&&"}, + {true, false, "1||"}, + {true, false, "1,"}, + {true, false, ",1"}, + {true, false, "1,1"}, // Accept valid ternary operators. - {true, "1?1:1"}, - {true, "1?:1"}, // A gcc extension treats x ? : y as x ? x : y. + {true, true, "1?1:1"}, + {true, true, "1?:1"}, // A gcc extension treats x ? : y as x ? x : y. // Reject invalid ternary operators. - {false, "?"}, - {false, "?1"}, - {false, "?:"}, - {false, "?:1"}, - {false, "?1:"}, - {false, "?1:1"}, - {false, "1?"}, - {false, "1?1"}, - {false, "1?:"}, - {false, "1?1:"}, + {true, false, "?"}, + {true, false, "?1"}, + {true, false, "?:"}, + {true, false, "?:1"}, + {true, false, "?1:"}, + {true, false, "?1:1"}, + {true, false, "1?"}, + {true, false, "1?1"}, + {true, false, "1?:"}, + {true, false, "1?1:"}, // Accept parenthesized expressions. - {true, "(1)"}, - {true, "((+1))"}, - {true, "((+(1)))"}, - {true, "(-1)"}, - {true, "-(1)"}, - {true, "(+1)"}, - {true, "((+1))"}, - {true, "+(1)"}, - {true, "(~1)"}, - {true, "~(1)"}, - {true, "(!1)"}, - {true, "!(1)"}, - {true, "(1+1)"}, - {true, "(1-1)"}, - {true, "(1*1)"}, - {true, "(1/1)"}, - {true, "(1%2)"}, - {true, "(1<<1)"}, - {true, "(1>>1)"}, - {true, "(1<=>1)"}, - {true, "(1<1)"}, - {true, "(1>1)"}, - {true, "(1<=1)"}, - {true, "(1>=1)"}, - {true, "(1==1)"}, - {true, "(1!=1)"}, - {true, "(1&1)"}, - {true, "(1^1)"}, - {true, "(1|1)"}, - {true, "(1&&1)"}, - {true, "(1||1)"}, - {true, "(1?1:1)"}, + {true, true, "(1)"}, + {true, true, "((+1))"}, + {true, true, "((+(1)))"}, + {true, true, "(-1)"}, + {true, true, "-(1)"}, + {true, true, "(+1)"}, + {true, true, "((+1))"}, + {true, true, "+(1)"}, + {true, true, "(~1)"}, + {true, true, "~(1)"}, + {true, true, "(!1)"}, + {true, true, "!(1)"}, + {true, true, "(1+1)"}, + {true, true, "(1-1)"}, + {true, true, "(1*1)"}, + {true, true, "(1/1)"}, + {true, true, "(1%2)"}, + {true, true, "(1<<1)"}, + {true, true, "(1>>1)"}, + {true, true, "(1<=>1)"}, + {true, true, "(1<1)"}, + {true, true, "(1>1)"}, + {true, true, "(1<=1)"}, + {true, true, "(1>=1)"}, + {true, true, "(1==1)"}, + {true, true, "(1!=1)"}, + {true, true, "(1&1)"}, + {true, true, "(1^1)"}, + {true, true, "(1|1)"}, + {true, true, "(1&&1)"}, + {true, true, "(1||1)"}, + {true, true, "(1?1:1)"}, // Accept more complicated "chained" expressions. - {true, "1+1+1"}, - {true, "1+1+1+1"}, - {true, "1+1+1+1+1"}, - {true, "1*1*1"}, - {true, "1*1*1*1"}, - {true, "1*1*1*1*1"}, - {true, "1<<1<<1"}, - {true, "4U>>1>>1"}, - {true, "1<1<1"}, - {true, "1>1>1"}, - {true, "1<=1<=1"}, - {true, "1>=1>=1"}, - {true, "1==1==1"}, - {true, "1!=1!=1"}, - {true, "1&1&1"}, - {true, "1^1^1"}, - {true, "1|1|1"}, - {true, "1&&1&&1"}, - {true, "1||1||1"}, - {true, "1,1,1"}, + {true, true, "1+1+1"}, + {true, true, "1+1+1+1"}, + {true, true, "1+1+1+1+1"}, + {true, true, "1*1*1"}, + {true, true, "1*1*1*1"}, + {true, true, "1*1*1*1*1"}, + {true, true, "1<<1<<1"}, + {true, true, "4U>>1>>1"}, + {true, true, "1<1<1"}, + {true, true, "1>1>1"}, + {true, true, "1<=1<=1"}, + {true, true, "1>=1>=1"}, + {true, true, "1==1==1"}, + {true, true, "1!=1!=1"}, + {true, true, "1&1&1"}, + {true, true, "1^1^1"}, + {true, true, "1|1|1"}, + {true, true, "1&&1&&1"}, + {true, true, "1||1||1"}, + {true, true, "(1,1,1)"}, + + // Optionally reject comma operator + {false, false, "1,1"} }; TEST_P(MatcherTest, MatchResult) { - EXPECT_TRUE(matchText(GetParam().Text) == GetParam().Matched); + const MatchParam &Param = GetParam(); + + EXPECT_TRUE(matchText(Param.Text, Param.AllowComma) == Param.Matched); +} + +INSTANTIATE_TEST_SUITE_P(IntegralLiteralExpressionMatcherTests, MatcherTest, + ::testing::ValuesIn(MatchParams)); + +static const SizeParam SizeParams[] = { + {modernize::LiteralSize::Int, "1"}, + {modernize::LiteralSize::UnsignedInt, "1U"}, + {modernize::LiteralSize::Long, "1L"}, + {modernize::LiteralSize::UnsignedLong, "1UL"}, + {modernize::LiteralSize::UnsignedLong, "1LU"}, + {modernize::LiteralSize::LongLong, "1LL"}, + {modernize::LiteralSize::UnsignedLongLong, "1ULL"}, + {modernize::LiteralSize::UnsignedLongLong, "1LLU"}}; + +TEST_P(SizeTest, TokenSize) { + EXPECT_EQ(sizeText(GetParam().Text), GetParam().Size); } -INSTANTIATE_TEST_SUITE_P(TokenExpressionParserTests, MatcherTest, - ::testing::ValuesIn(Params)); +INSTANTIATE_TEST_SUITE_P(IntegralLiteralExpressionMatcherTests, SizeTest, + ::testing::ValuesIn(SizeParams)); } // namespace test } // namespace tidy diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake b/clang/cmake/caches/Fuchsia-stage2.cmake index 6a00556e977f4..4e3ed6086dec5 100644 --- a/clang/cmake/caches/Fuchsia-stage2.cmake +++ b/clang/cmake/caches/Fuchsia-stage2.cmake @@ -112,6 +112,7 @@ foreach(target aarch64-unknown-linux-gnu;armv7-unknown-linux-gnueabihf;i386-unkn set(RUNTIMES_${target}_CMAKE_MODULE_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "") set(RUNTIMES_${target}_CMAKE_EXE_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "") set(RUNTIMES_${target}_COMPILER_RT_USE_BUILTINS_LIBRARY ON CACHE BOOL "") + set(RUNTIMES_${target}_COMPILER_RT_USE_LLVM_UNWINDER ON CACHE BOOL "") set(RUNTIMES_${target}_COMPILER_RT_CAN_EXECUTE_TESTS ON CACHE BOOL "") set(RUNTIMES_${target}_LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "") set(RUNTIMES_${target}_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") @@ -179,6 +180,7 @@ if(FUCHSIA_SDK) set(RUNTIMES_${target}_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "") set(RUNTIMES_${target}_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") set(RUNTIMES_${target}_COMPILER_RT_USE_BUILTINS_LIBRARY ON CACHE BOOL "") + set(RUNTIMES_${target}_COMPILER_RT_USE_LLVM_UNWINDER ON CACHE BOOL "") set(RUNTIMES_${target}_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") set(RUNTIMES_${target}_LIBUNWIND_HIDE_SYMBOLS ON CACHE BOOL "") set(RUNTIMES_${target}_LIBUNWIND_INSTALL_STATIC_LIBRARY OFF CACHE BOOL "") diff --git a/clang/cmake/modules/AddClang.cmake b/clang/cmake/modules/AddClang.cmake index 9bbbfc032b7df..299f8ce6e2fb4 100644 --- a/clang/cmake/modules/AddClang.cmake +++ b/clang/cmake/modules/AddClang.cmake @@ -184,5 +184,8 @@ function(clang_target_link_libraries target type) else() target_link_libraries(${target} ${type} ${ARGN}) endif() + if (TARGET obj.${target}) + target_link_libraries(obj.${target} ${ARGN}) + endif() endfunction() diff --git a/clang/docs/APINotes.rst b/clang/docs/APINotes.rst index 4ac4c01cdefba..a6e200e8bffde 100644 --- a/clang/docs/APINotes.rst +++ b/clang/docs/APINotes.rst @@ -22,11 +22,11 @@ the compiler. That's API notes. API notes use a YAML-based file format. YAML is a format best explained by -example, so here is a `small example`__ from the compiler test suite of API +example, so here is a `small example +`_ +from the compiler test suite of API notes for a hypothetical "SomeKit" framework. -__ test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKit.apinotes - Usage ===== diff --git a/clang/docs/ClangOffloadPackager.rst b/clang/docs/ClangOffloadPackager.rst index 2211f3bd600f3..1664e415fe774 100644 --- a/clang/docs/ClangOffloadPackager.rst +++ b/clang/docs/ClangOffloadPackager.rst @@ -76,7 +76,7 @@ along with some other integer information. The image kind lets us easily identify the type of image stored here without needing to inspect the binary. The offloading kind is used to determine which registration code or linking semantics are necessary for this image. These are stored as enumerations with -the following values for the :ref:`offload kind` and the :ref:`image kind`. .. table:: Image Kind @@ -95,7 +95,7 @@ the following values for the :ref:`offload kind`_ intrinsic +for more information. + +This is useful to implement a custom version of ``memset``, implement a +``libc`` memset or work around the absence of a ``libc``. + +Note that the `size` argument must be a compile time constant. + +Note that this intrinsic cannot yet be called in a ``constexpr`` context. Atomic Min/Max builtins with memory ordering -------------------------------------------- diff --git a/clang/docs/LibASTMatchersTutorial.rst b/clang/docs/LibASTMatchersTutorial.rst index 3f396dd39ded1..37c9f178fa8df 100644 --- a/clang/docs/LibASTMatchersTutorial.rst +++ b/clang/docs/LibASTMatchersTutorial.rst @@ -399,7 +399,7 @@ in the callback. So we start with: .. code-block:: c++ - hasCondition(binaryOperator(hasOperatorName("<")) + hasCondition(binaryOperator(hasOperatorName("<"))) It makes sense to ensure that the left-hand side is a reference to a variable, and that the right-hand side has integer type. @@ -529,7 +529,7 @@ address, all we need to do is make sure neither ``ValueDecl`` (base class of } If execution reaches the end of ``LoopPrinter::run()``, we know that the -loop shell that looks like +loop shell looks like .. code-block:: c++ diff --git a/clang/docs/OffloadingDesign.rst b/clang/docs/OffloadingDesign.rst index 43a0c0d2c29f7..5df8a320b4da7 100644 --- a/clang/docs/OffloadingDesign.rst +++ b/clang/docs/OffloadingDesign.rst @@ -258,7 +258,7 @@ create an executable device image. This is done using a Clang tool, see :doc:`ClangLinkerWrapper` for more information. This tool works as a wrapper over the host linking job. It scans the input object files for the offloading section ``.llvm.offloading``. The device files stored in this section are then -extracted and passed tot he appropriate linking job. The linked device image is +extracted and passed to the appropriate linking job. The linked device image is then :ref:`wrapped ` to create the symbols used to load the device image and link it with the host. diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst index 88e3050d3622c..1f233e63815fa 100644 --- a/clang/docs/OpenMPSupport.rst +++ b/clang/docs/OpenMPSupport.rst @@ -262,7 +262,7 @@ want to help with the implementation. +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ |Category | Feature | Status | Reviews | +==============================+==============================================================+==========================+=======================================================================+ -| atomic extension | 'compare' clause on atomic construct | :good:`worked on` | | +| atomic extension | 'compare' clause on atomic construct | :good:`done` | D120290, D120007, D118632, D120200, D116261, D118547, D116637 | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ | atomic extension | 'fail' clause on atomic construct | :part:`worked on` | | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ @@ -312,7 +312,7 @@ want to help with the implementation. +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ | memory model extension | seq_cst clause on flush construct | :none:`unclaimed` | | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc extension | 'omp_all_memory' keyword and use in 'depend' clause | :none:`unclaimed` | | +| misc extension | 'omp_all_memory' keyword and use in 'depend' clause | :good:`done` | D125828, D126321 | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ | misc extension | error directive | :none:`unclaimed` | | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c34d29c8762d4..2f17fbf406285 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -110,12 +110,12 @@ Bug Fixes `51414 `_, `51416 `_, and `51641 `_. -- The builtin function __builtin_dump_struct would crash clang when the target +- The builtin function __builtin_dump_struct would crash clang when the target struct contains a bitfield. It now correctly handles bitfields. This fixes Issue `Issue 54462 `_. - Statement expressions are now disabled in default arguments in general. This fixes Issue `Issue 53488 `_. -- According to `CWG 1394 `_ and +- According to `CWG 1394 `_ and `C++20 [dcl.fct.def.general]p2 `_, Clang should not diagnose incomplete types in function definitions if the function body is "= delete;". This fixes Issue `Issue 52802 `_. @@ -149,8 +149,8 @@ Bug Fixes because there is no way to fully qualify the enumerator name, so this "extension" was unintentional and useless. This fixes `Issue 42372 `_. -- Clang will now find and emit a call to an allocation function in a - promise_type body for coroutines if there is any allocation function +- Clang will now find and emit a call to an allocation function in a + promise_type body for coroutines if there is any allocation function declaration in the scope of promise_type. Additionally, to implement CWG2585, a coroutine will no longer generate a call to a global allocation function with the signature (std::size_t, p0, ..., pn). @@ -158,6 +158,23 @@ Bug Fixes - Implement `CWG 2394 `_: Const class members may be initialized with a defaulted default constructor under the same conditions it would be allowed for a const object elsewhere. +- ``__has_unique_object_representations`` no longer reports that ``_BitInt`` types + have unique object representations if they have padding bits. +- Unscoped and scoped enumeration types can no longer be initialized from a + brace-init-list containing a single element of a different scoped enumeration + type. +- Allow use of an elaborated type specifier as a ``_Generic`` selection + association in C++ mode. This fixes + `Issue 55562 `_. +- Clang will allow calling a ``consteval`` function in a default argument. This + fixes `Issue 48230 `_. +- Fixed memory leak due to ``VarTemplateSpecializationDecl`` using + ``TemplateArgumentListInfo`` instead of ``ASTTemplateArgumentListInfo``. +- An initializer for a static variable declaration, which is nested + inside a statement expression in an aggregate initializer, is now + emitted as a dynamic initializer. Previously the variable would + incorrectly be zero-initialized. In contexts where a dynamic + initializer is not allowed this is now diagnosed as an error. Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,6 +258,15 @@ Improvements to Clang's diagnostics suggest ``#else`` as an alternative. ``#elifdef`` and ``#elifndef`` are only suggested when in C2x or C++2b mode. Fixes `Issue 51598 `_. +- The ``-Wdeprecated`` diagnostic will now warn on out-of-line ``constexpr`` + declarations downgraded to definitions in C++1z, in addition to the + existing warning on out-of-line ``const`` declarations. +- ``-Wshift-overflow`` will not warn for signed left shifts in C++20 mode + (and newer), as it will always wrap and never overflow. This fixes + `Issue 52873 `_. +- When using class templates without arguments, clang now tells developers + that template arguments are missing in certain contexts. + This fixes `Issue 55962 `_. Non-comprehensive list of changes in this release ------------------------------------------------- @@ -276,6 +302,13 @@ New Compiler Flags ``-mfix-cortex-a72-aes-1655431``. The pass is enabled when using either of these cpus with ``-mcpu=`` and can be disabled using ``-mno-fix-cortex-a57-aes-1742098`` or ``-mno-fix-cortex-a72-aes-1655431``. +- Added the ``-fexperimental-max-bitint-width=`` option to increase the maximum + allowed bit width of ``_BitInt`` types beyond the default of 128 bits. Some + operations, such as division or float-to-integer conversion, on ``_BitInt`` + types with more than 128 bits currently crash clang. This option will be + removed in the future once clang supports all such operations. +- Added the ``-print-diagnostic-options`` option, which prints a list of + warnings the compiler supports. Deprecated Compiler Flags ------------------------- @@ -328,6 +361,12 @@ Attribute Changes in Clang builtins (corresponding to the specific names listed in the attribute) in the body of the function the attribute is on. +- When the ``weak`` attribute is applied to a const qualified variable clang no longer + tells the backend it is allowed to optimize based on initializer value. + +- Added the ``clang::annotate_type`` attribute, which can be used to add + annotations to types (see documentation for details). + Windows Support --------------- @@ -337,6 +376,11 @@ Windows Support JustMyCode feature. Note, you may need to manually add ``/JMC`` as additional compile options in the Visual Studio since it currently assumes clang-cl does not support ``/JMC``. +- Implemented generation of SEH unwind information on ARM. (C++ exception + handling in MSVC mode is still unimplemented though.) + +- Switched MinGW mode on ARM to use SEH instead of DWARF for unwind information. + AIX Support ----------- @@ -350,11 +394,6 @@ AIX Support C Language Changes in Clang --------------------------- -- Finished implementing support for DR423. We already correctly handled - stripping qualifiers from cast expressions, but we did not strip qualifiers - on function return types. We now properly treat the function as though it - were declarated with an unqualified, non-atomic return type. Fixes - `Issue 39595 `_. C2x Feature Support ------------------- @@ -435,6 +474,10 @@ ABI Changes in Clang such packing. Clang now matches the gcc behavior (except on Darwin and PS4). You can switch back to the old ABI behavior with the flag: ``-fclang-abi-compat=14.0``. +- When compiling C for ARM or AArch64, a zero-length bitfield in a ``struct`` + (e.g. ``int : 0``) no longer prevents the structure from being considered a + homogeneous floating-point or vector aggregate. The new behavior agrees with + the AAPCS specification, and matches the similar bug fix in GCC 12.1. OpenMP Support in Clang ----------------------- @@ -449,6 +492,9 @@ CUDA Support in Clang X86 Support in Clang -------------------- +- Support ``-mharden-sls=[none|all|return|indirect-jmp]`` for straight-line + speculation hardening. + DWARF Support in Clang ---------------------- @@ -515,9 +561,15 @@ Static Analyzer - Added a new checker ``alpha.unix.cstring.UninitializedRead`` this will check for uninitialized reads from common memory copy/manipulation functions such as ``memcpy``, ``mempcpy``, ``memmove``, ``memcmp``, ` - `strcmp``, ``strncmp``, ``strcpy``, ``strlen``, ``strsep`` and many more. Although + `strcmp``, ``strncmp``, ``strcpy``, ``strlen``, ``strsep`` and many more. Although this checker currently is in list of alpha checkers due to a false positive. +- Deprecate the ``-analyzer-store region`` and + ``-analyzer-opt-analyze-nested-blocks`` analyzer flags. + These flags are still accepted, but a warning will be displayed. + These flags will be rejected, thus turned into a hard error starting with + ``clang-16``. + .. _release-notes-ubsan: Undefined Behavior Sanitizer (UBSan) diff --git a/clang/docs/SafeStack.rst b/clang/docs/SafeStack.rst index 8b5557bf59b05..c585315dff882 100644 --- a/clang/docs/SafeStack.rst +++ b/clang/docs/SafeStack.rst @@ -18,7 +18,7 @@ buffer overflows on the unsafe stack cannot be used to overwrite anything on the safe stack. SafeStack is a part of the `Code-Pointer Integrity (CPI) Project -`_. +`_. Performance ----------- @@ -84,7 +84,7 @@ Known security limitations A complete protection against control-flow hijack attacks requires combining SafeStack with another mechanism that enforces the integrity of code pointers that are stored on the heap or the unsafe stack, such as `CPI -`_, or a forward-edge control flow integrity +`_, or a forward-edge control flow integrity mechanism that enforces correct calling conventions at indirect call sites, such as `IFCC `_ with arity checks. Clang has control-flow integrity protection scheme for :doc:`C++ virtual @@ -186,7 +186,7 @@ Deprecated: This builtin function is an alias for Design ====== -Please refer to the `Code-Pointer Integrity `__ +Please refer to the `Code-Pointer Integrity `__ project page for more information about the design of the SafeStack and its related technologies. diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index b8c468333a67b..e12dc72407b13 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -3626,6 +3626,23 @@ Clang expects the GCC executable "gcc.exe" compiled for `Some tests might fail `_ on ``x86_64-w64-mingw32``. +AIX +^^^ + +The ``-mdefault-visibility-export-mapping=`` option can be used to control +mapping of default visibility to an explicit shared object export +(i.e. XCOFF exported visibility). Three values are provided for the option: + +* ``-mdefault-visibility-export-mapping=none``: no additional export + information is created for entities with default visibility. +* ``-mdefault-visibility-export-mapping=explicit``: mark entities for export + if they have explict (e.g. via an attribute) default visibility from the + source, including RTTI. +* ``-mdefault-visibility-export-mapping=all``: set XCOFF exported visibility + for all entities with default visibility from any source. This gives a + export behavior similar to ELF platforms where all entities with default + visibility are exported. + .. _spir-v: SPIR-V support diff --git a/clang/docs/analyzer/developer-docs/nullability.rst b/clang/docs/analyzer/developer-docs/nullability.rst index d54a2e9369c7a..f4be0b57719ee 100644 --- a/clang/docs/analyzer/developer-docs/nullability.rst +++ b/clang/docs/analyzer/developer-docs/nullability.rst @@ -4,7 +4,8 @@ Nullability Checks This document is a high level description of the nullablility checks. These checks intended to use the annotations that is described in this -RFC: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2015-March/041798.html. +RFC: https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672 +(`Mailman `_) Let's consider the following 2 categories: diff --git a/clang/docs/tools/dump_format_style.py b/clang/docs/tools/dump_format_style.py index fb074435e753e..e8bf29cfd2bee 100755 --- a/clang/docs/tools/dump_format_style.py +++ b/clang/docs/tools/dump_format_style.py @@ -267,6 +267,9 @@ class State: name = re.sub(r'struct\s+(\w+)\s*\{', '\\1', line) nested_struct = NestedStruct(name, comment) elif line.endswith(';'): + prefix = '// ' + if line.startswith(prefix): + line = line[len(prefix):] state = State.InStruct field_type, field_name = re.match(r'([<>:\w(,\s)]+)\s+(\w+);', line).groups() diff --git a/clang/include/clang/AST/ASTImportError.h b/clang/include/clang/AST/ASTImportError.h index 034bd50cc7e15..405790b6ded3f 100644 --- a/clang/include/clang/AST/ASTImportError.h +++ b/clang/include/clang/AST/ASTImportError.h @@ -18,7 +18,8 @@ namespace clang { -class ImportError : public llvm::ErrorInfo { +class ASTImportError : public llvm::ErrorInfo { + public: /// \brief Kind of error when importing an AST component. enum ErrorKind { @@ -31,13 +32,13 @@ class ImportError : public llvm::ErrorInfo { static char ID; - ImportError() : Error(Unknown) {} - ImportError(const ImportError &Other) : Error(Other.Error) {} - ImportError &operator=(const ImportError &Other) { + ASTImportError() : Error(Unknown) {} + ASTImportError(const ASTImportError &Other) : Error(Other.Error) {} + ASTImportError &operator=(const ASTImportError &Other) { Error = Other.Error; return *this; } - ImportError(ErrorKind Error) : Error(Error) {} + ASTImportError(ErrorKind Error) : Error(Error) {} std::string toString() const; diff --git a/clang/include/clang/AST/ASTImporter.h b/clang/include/clang/AST/ASTImporter.h index 7d413115d769c..e38ffa50ad4ab 100644 --- a/clang/include/clang/AST/ASTImporter.h +++ b/clang/include/clang/AST/ASTImporter.h @@ -231,7 +231,7 @@ class TypeSourceInfo; /// imported. The same declaration may or may not be included in /// ImportedDecls. This map is updated continuously during imports and never /// cleared (like ImportedDecls). - llvm::DenseMap ImportDeclErrors; + llvm::DenseMap ImportDeclErrors; /// Mapping from the already-imported declarations in the "to" /// context to the corresponding declarations in the "from" context. @@ -564,10 +564,10 @@ class TypeSourceInfo; /// Return if import of the given declaration has failed and if yes /// the kind of the problem. This gives the first error encountered with /// the node. - llvm::Optional getImportDeclErrorIfAny(Decl *FromD) const; + llvm::Optional getImportDeclErrorIfAny(Decl *FromD) const; /// Mark (newly) imported declaration with error. - void setImportDeclError(Decl *From, ImportError Error); + void setImportDeclError(Decl *From, ASTImportError Error); /// Determine whether the given types are structurally /// equivalent. diff --git a/clang/include/clang/AST/ASTImporterSharedState.h b/clang/include/clang/AST/ASTImporterSharedState.h index a64c9d6be455f..ce7fb290c9765 100644 --- a/clang/include/clang/AST/ASTImporterSharedState.h +++ b/clang/include/clang/AST/ASTImporterSharedState.h @@ -36,7 +36,7 @@ class ASTImporterSharedState { /// imported. The same declaration may or may not be included in /// ImportedFromDecls. This map is updated continuously during imports and /// never cleared (like ImportedFromDecls). - llvm::DenseMap ImportErrors; + llvm::DenseMap ImportErrors; /// Set of the newly created declarations. llvm::DenseSet NewDecls; @@ -65,15 +65,15 @@ class ASTImporterSharedState { LookupTable->remove(ND); } - llvm::Optional getImportDeclErrorIfAny(Decl *ToD) const { + llvm::Optional getImportDeclErrorIfAny(Decl *ToD) const { auto Pos = ImportErrors.find(ToD); if (Pos != ImportErrors.end()) return Pos->second; else - return Optional(); + return Optional(); } - void setImportDeclError(Decl *To, ImportError Error) { + void setImportDeclError(Decl *To, ASTImportError Error) { ImportErrors[To] = Error; } diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index f2c5c01ac88de..093dc9a773c75 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -467,6 +467,10 @@ class ASTNodeTraverser void VisitBindingDecl(const BindingDecl *D) { if (Traversal == TK_IgnoreUnlessSpelledInSource) return; + + if (const auto *V = D->getHoldingVar()) + Visit(V); + if (const auto *E = D->getBinding()) Visit(E); } diff --git a/clang/include/clang/AST/AbstractTypeReader.h b/clang/include/clang/AST/AbstractTypeReader.h index c9162b1779bc6..e44bbf61c0ed0 100644 --- a/clang/include/clang/AST/AbstractTypeReader.h +++ b/clang/include/clang/AST/AbstractTypeReader.h @@ -9,8 +9,9 @@ #ifndef LLVM_CLANG_AST_ABSTRACTTYPEREADER_H #define LLVM_CLANG_AST_ABSTRACTTYPEREADER_H -#include "clang/AST/Type.h" #include "clang/AST/AbstractBasicReader.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Type.h" namespace clang { namespace serialization { diff --git a/clang/include/clang/AST/CharUnits.h b/clang/include/clang/AST/CharUnits.h index f14d3abf71e5e..2705f24789e4c 100644 --- a/clang/include/clang/AST/CharUnits.h +++ b/clang/include/clang/AST/CharUnits.h @@ -182,6 +182,12 @@ namespace clang { /// Beware llvm::Align assumes power of two 8-bit bytes. llvm::Align getAsAlign() const { return llvm::Align(Quantity); } + /// getAsMaybeAlign - Returns Quantity as a valid llvm::Align or + /// llvm::None, Beware llvm::MaybeAlign assumes power of two 8-bit bytes. + llvm::MaybeAlign getAsMaybeAlign() const { + return llvm::MaybeAlign(Quantity); + } + /// alignTo - Returns the next integer (mod 2**64) that is /// greater than or equal to this quantity and is a multiple of \p Align. /// Align must be non-zero. diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 66e0bb2c02a1f..a00917913e41d 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -2718,7 +2718,7 @@ class VarTemplateSpecializationDecl : public VarDecl, /// The template arguments used to describe this specialization. const TemplateArgumentList *TemplateArgs; - TemplateArgumentListInfo TemplateArgsInfo; + const ASTTemplateArgumentListInfo *TemplateArgsInfo = nullptr; /// The point where this template was instantiated (if any). SourceLocation PointOfInstantiation; @@ -2773,8 +2773,9 @@ class VarTemplateSpecializationDecl : public VarDecl, // TODO: Always set this when creating the new specialization? void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo); + void setTemplateArgsInfo(const ASTTemplateArgumentListInfo *ArgsInfo); - const TemplateArgumentListInfo &getTemplateArgsInfo() const { + const ASTTemplateArgumentListInfo *getTemplateArgsInfo() const { return TemplateArgsInfo; } diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index ae6442d75dd4b..c6d74d94194bd 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2021,7 +2021,7 @@ DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); }) DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) -#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND) \ +#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \ /* For implicit instantiations ("set x;"), we don't want to \ recurse at all, since the instatiated template isn't written in \ @@ -2034,18 +2034,23 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \ TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \ \ - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); \ - if (!getDerived().shouldVisitTemplateInstantiations() && \ - D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \ + if (getDerived().shouldVisitTemplateInstantiations() || \ + D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \ + /* Traverse base definition for explicit specializations */ \ + TRY_TO(Traverse##DECLKIND##Helper(D)); \ + } else { \ + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); \ + \ /* Returning from here skips traversing the \ declaration context of the *TemplateSpecializationDecl \ (embedded in the DEF_TRAVERSE_DECL() macro) \ which contains the instantiated members of the template. */ \ return true; \ + } \ }) -DEF_TRAVERSE_TMPL_SPEC_DECL(Class) -DEF_TRAVERSE_TMPL_SPEC_DECL(Var) +DEF_TRAVERSE_TMPL_SPEC_DECL(Class, CXXRecord) +DEF_TRAVERSE_TMPL_SPEC_DECL(Var, Var) template bool RecursiveASTVisitor::TraverseTemplateArgumentLocsHelper( diff --git a/clang/include/clang/AST/StmtCXX.h b/clang/include/clang/AST/StmtCXX.h index 5ccf6904048e3..2c71f86768963 100644 --- a/clang/include/clang/AST/StmtCXX.h +++ b/clang/include/clang/AST/StmtCXX.h @@ -497,16 +497,10 @@ class CoreturnStmt : public Stmt { } child_range children() { - if (!getOperand()) - return child_range(SubStmts + SubStmt::PromiseCall, - SubStmts + SubStmt::Count); return child_range(SubStmts, SubStmts + SubStmt::Count); } const_child_range children() const { - if (!getOperand()) - return const_child_range(SubStmts + SubStmt::PromiseCall, - SubStmts + SubStmt::Count); return const_child_range(SubStmts, SubStmts + SubStmt::Count); } diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index dfaf8b5a77385..4ebe7f44aa7ad 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -2848,6 +2848,9 @@ class OMPAtomicDirective : public OMPExecutableDirective { /// This field is 1 for the first(postfix) form of the expression and 0 /// otherwise. uint8_t IsPostfixUpdate : 1; + /// 1 if 'v' is updated only when the condition is false (compare capture + /// only). + uint8_t IsFailOnly : 1; } Flags; /// Build directive with the given start and end location. @@ -2872,6 +2875,7 @@ class OMPAtomicDirective : public OMPExecutableDirective { POS_UpdateExpr, POS_D, POS_Cond, + POS_R, }; /// Set 'x' part of the associated expression/statement. @@ -2884,6 +2888,8 @@ class OMPAtomicDirective : public OMPExecutableDirective { } /// Set 'v' part of the associated expression/statement. void setV(Expr *V) { Data->getChildren()[DataPositionTy::POS_V] = V; } + /// Set 'r' part of the associated expression/statement. + void setR(Expr *R) { Data->getChildren()[DataPositionTy::POS_R] = R; } /// Set 'expr' part of the associated expression/statement. void setExpr(Expr *E) { Data->getChildren()[DataPositionTy::POS_E] = E; } /// Set 'd' part of the associated expression/statement. @@ -2897,6 +2903,8 @@ class OMPAtomicDirective : public OMPExecutableDirective { Expr *X = nullptr; /// 'v' part of the associated expression/statement. Expr *V = nullptr; + // 'r' part of the associated expression/statement. + Expr *R = nullptr; /// 'expr' part of the associated expression/statement. Expr *E = nullptr; /// UE Helper expression of the form: @@ -2911,6 +2919,9 @@ class OMPAtomicDirective : public OMPExecutableDirective { bool IsXLHSInRHSPart; /// True if original value of 'x' must be stored in 'v', not an updated one. bool IsPostfixUpdate; + /// True if 'v' is updated only when the condition is false (compare capture + /// only). + bool IsFailOnly; }; /// Creates directive with a list of \a Clauses and 'x', 'v' and 'expr' @@ -2963,6 +2974,9 @@ class OMPAtomicDirective : public OMPExecutableDirective { /// Return true if 'v' expression must be updated to original value of /// 'x', false if 'v' must be updated to the new value of 'x'. bool isPostfixUpdate() const { return Flags.IsPostfixUpdate; } + /// Return true if 'v' is updated only when the condition is evaluated false + /// (compare capture only). + bool isFailOnly() const { return Flags.IsFailOnly; } /// Get 'v' part of the associated expression/statement. Expr *getV() { return cast_or_null(Data->getChildren()[DataPositionTy::POS_V]); @@ -2970,6 +2984,13 @@ class OMPAtomicDirective : public OMPExecutableDirective { const Expr *getV() const { return cast_or_null(Data->getChildren()[DataPositionTy::POS_V]); } + /// Get 'r' part of the associated expression/statement. + Expr *getR() { + return cast_or_null(Data->getChildren()[DataPositionTy::POS_R]); + } + const Expr *getR() const { + return cast_or_null(Data->getChildren()[DataPositionTy::POS_R]); + } /// Get 'expr' part of the associated expression/statement. Expr *getExpr() { return cast_or_null(Data->getChildren()[DataPositionTy::POS_E]); diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h index e8064121d2796..3ac755ef74a17 100644 --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -618,6 +618,9 @@ struct ASTTemplateArgumentListInfo final ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List); + // FIXME: Is it ever necessary to copy to another context? + ASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo *List); + public: /// The source location of the left angle bracket ('<'). SourceLocation LAngleLoc; @@ -647,6 +650,10 @@ struct ASTTemplateArgumentListInfo final static const ASTTemplateArgumentListInfo * Create(const ASTContext &C, const TemplateArgumentListInfo &List); + + // FIXME: Is it ever necessary to copy to another context? + static const ASTTemplateArgumentListInfo * + Create(const ASTContext &C, const ASTTemplateArgumentListInfo *List); }; /// Represents an explicit template argument list in C++, e.g., diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 45b75fe7960c3..5784839f4f961 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1624,6 +1624,9 @@ class alignas(8) Type : public ExtQualsTypeCommonBase { /// Whether this function has extended parameter information. unsigned HasExtParameterInfos : 1; + /// Whether this function has extra bitfields for the prototype. + unsigned HasExtraBitfields : 1; + /// Whether the function is variadic. unsigned Variadic : 1; @@ -3798,13 +3801,12 @@ class FunctionType : public Type { /// A simple holder for various uncommon bits which do not fit in /// FunctionTypeBitfields. Aligned to alignof(void *) to maintain the - /// alignment of subsequent objects in TrailingObjects. You must update - /// hasExtraBitfields in FunctionProtoType after adding extra data here. + /// alignment of subsequent objects in TrailingObjects. struct alignas(void *) FunctionTypeExtraBitfields { /// The number of types in the exception specification. /// A whole unsigned is not needed here and according to /// [implimits] 8 bits would be enough here. - unsigned NumExceptionType; + unsigned NumExceptionType = 0; }; protected: @@ -3998,6 +4000,10 @@ class FunctionProtoType final Result.ExceptionSpec = ESI; return Result; } + + bool requiresFunctionProtoTypeExtraBitfields() const { + return ExceptionSpec.Type == EST_Dynamic; + } }; private: @@ -4088,16 +4094,13 @@ class FunctionProtoType final return getExceptionSpecSize(getExceptionSpecType(), getNumExceptions()); } - /// Whether the trailing FunctionTypeExtraBitfields is present. - static bool hasExtraBitfields(ExceptionSpecificationType EST) { - // If the exception spec type is EST_Dynamic then we have > 0 exception - // types and the exact number is stored in FunctionTypeExtraBitfields. - return EST == EST_Dynamic; - } - /// Whether the trailing FunctionTypeExtraBitfields is present. bool hasExtraBitfields() const { - return hasExtraBitfields(getExceptionSpecType()); + assert((getExceptionSpecType() != EST_Dynamic || + FunctionTypeBits.HasExtraBitfields) && + "ExtraBitfields are required for given ExceptionSpecType"); + return FunctionTypeBits.HasExtraBitfields; + } bool hasExtQualifiers() const { diff --git a/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h b/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h index 8cc3fa73de9df..2102ed56907bb 100644 --- a/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h +++ b/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h @@ -59,6 +59,14 @@ class UncheckedOptionalAccessModel void transfer(const Stmt *Stmt, SourceLocationsLattice &State, Environment &Env); + bool compareEquivalent(QualType Type, const Value &Val1, + const Environment &Env1, const Value &Val2, + const Environment &Env2) override; + + bool merge(QualType Type, const Value &Val1, const Environment &Env1, + const Value &Val2, const Environment &Env2, Value &MergedVal, + Environment &MergedEnv) override; + private: MatchSwitch> TransferMatchSwitch; }; diff --git a/clang/include/clang/Analysis/FlowSensitive/StorageLocation.h b/clang/include/clang/Analysis/FlowSensitive/StorageLocation.h index f965486537e61..fdfd03129b81e 100644 --- a/clang/include/clang/Analysis/FlowSensitive/StorageLocation.h +++ b/clang/include/clang/Analysis/FlowSensitive/StorageLocation.h @@ -31,6 +31,12 @@ class StorageLocation { StorageLocation(Kind LocKind, QualType Type) : LocKind(LocKind), Type(Type) {} + // Non-copyable because addresses of storage locations are used as their + // identities throughout framework and user code. The framework is responsible + // for construction and destruction of storage locations. + StorageLocation(const StorageLocation &) = delete; + StorageLocation &operator=(const StorageLocation &) = delete; + virtual ~StorageLocation() = default; Kind getKind() const { return LocKind; } diff --git a/clang/include/clang/Analysis/FlowSensitive/Value.h b/clang/include/clang/Analysis/FlowSensitive/Value.h index 859cf7ff21b5b..70348f8745431 100644 --- a/clang/include/clang/Analysis/FlowSensitive/Value.h +++ b/clang/include/clang/Analysis/FlowSensitive/Value.h @@ -26,6 +26,9 @@ namespace clang { namespace dataflow { /// Base class for all values computed by abstract interpretation. +/// +/// Don't use `Value` instances by value. All `Value` instances are allocated +/// and owned by `DataflowAnalysisContext`. class Value { public: enum class Kind { @@ -44,12 +47,32 @@ class Value { explicit Value(Kind ValKind) : ValKind(ValKind) {} + // Non-copyable because addresses of values are used as their identities + // throughout framework and user code. The framework is responsible for + // construction and destruction of values. + Value(const Value &) = delete; + Value &operator=(const Value &) = delete; + virtual ~Value() = default; Kind getKind() const { return ValKind; } + /// Returns the value of the synthetic property with the given `Name` or null + /// if the property isn't assigned a value. + Value *getProperty(llvm::StringRef Name) const { + auto It = Properties.find(Name); + return It == Properties.end() ? nullptr : It->second; + } + + /// Assigns `Val` as the value of the synthetic property with the given + /// `Name`. + void setProperty(llvm::StringRef Name, Value &Val) { + Properties.insert_or_assign(Name, &Val); + } + private: Kind ValKind; + llvm::StringMap Properties; }; /// Models a boolean. @@ -149,44 +172,37 @@ class IntegerValue : public Value { } }; -/// Base class for values that refer to storage locations. -class IndirectionValue : public Value { -public: - /// Constructs a value that refers to `PointeeLoc`. - explicit IndirectionValue(Kind ValueKind, StorageLocation &PointeeLoc) - : Value(ValueKind), PointeeLoc(PointeeLoc) {} - - static bool classof(const Value *Val) { - return Val->getKind() == Kind::Reference || Val->getKind() == Kind::Pointer; - } - - StorageLocation &getPointeeLoc() const { return PointeeLoc; } - -private: - StorageLocation &PointeeLoc; -}; - /// Models a dereferenced pointer. For example, a reference in C++ or an lvalue /// in C. -class ReferenceValue final : public IndirectionValue { +class ReferenceValue final : public Value { public: - explicit ReferenceValue(StorageLocation &PointeeLoc) - : IndirectionValue(Kind::Reference, PointeeLoc) {} + explicit ReferenceValue(StorageLocation &ReferentLoc) + : Value(Kind::Reference), ReferentLoc(ReferentLoc) {} static bool classof(const Value *Val) { return Val->getKind() == Kind::Reference; } + + StorageLocation &getReferentLoc() const { return ReferentLoc; } + +private: + StorageLocation &ReferentLoc; }; /// Models a symbolic pointer. Specifically, any value of type `T*`. -class PointerValue final : public IndirectionValue { +class PointerValue final : public Value { public: explicit PointerValue(StorageLocation &PointeeLoc) - : IndirectionValue(Kind::Pointer, PointeeLoc) {} + : Value(Kind::Pointer), PointeeLoc(PointeeLoc) {} static bool classof(const Value *Val) { return Val->getKind() == Kind::Pointer; } + + StorageLocation &getPointeeLoc() const { return PointeeLoc; } + +private: + StorageLocation &PointeeLoc; }; /// Models a value of `struct` or `class` type, with a flat map of fields to @@ -215,22 +231,8 @@ class StructValue final : public Value { /// Assigns `Val` as the child value for `D`. void setChild(const ValueDecl &D, Value &Val) { Children[&D] = &Val; } - /// Returns the value of the synthetic property with the given `Name` or null - /// if the property isn't assigned a value. - Value *getProperty(llvm::StringRef Name) const { - auto It = Properties.find(Name); - return It == Properties.end() ? nullptr : It->second; - } - - /// Assigns `Val` as the value of the synthetic property with the given - /// `Name`. - void setProperty(llvm::StringRef Name, Value &Val) { - Properties.insert_or_assign(Name, &Val); - } - private: llvm::DenseMap Children; - llvm::StringMap Properties; }; } // namespace dataflow diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index fed29b03a8b14..5f77073413fbf 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -804,6 +804,14 @@ def Annotate : InheritableParamAttr { let Documentation = [Undocumented]; } +def AnnotateType : TypeAttr { + let Spellings = [CXX11<"clang", "annotate_type">, C2x<"clang", "annotate_type">]; + let Args = [StringArgument<"Annotation">, VariadicExprArgument<"Args">]; + let HasCustomParsing = 1; + let AcceptsExprPack = 1; + let Documentation = [AnnotateTypeDocs]; +} + def ARMInterrupt : InheritableAttr, TargetSpecificAttr { // NOTE: If you add any additional spellings, M68kInterrupt's, // MSP430Interrupt's, MipsInterrupt's and AnyX86Interrupt's spellings @@ -1438,7 +1446,7 @@ def Final : InheritableAttr { def MinSize : InheritableAttr { let Spellings = [Clang<"minsize">]; let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>; - let Documentation = [Undocumented]; + let Documentation = [MinSizeDocs]; } def FlagEnum : InheritableAttr { @@ -1926,9 +1934,9 @@ def NonNull : InheritableParamAttr { bool isNonNull(unsigned IdxAST) const { if (!args_size()) return true; - return args_end() != std::find_if( - args_begin(), args_end(), - [=](const ParamIdx &Idx) { return Idx.getASTIndex() == IdxAST; }); + return llvm::any_of(args(), [=](const ParamIdx &Idx) { + return Idx.getASTIndex() == IdxAST; + }); } }]; // FIXME: We should merge duplicates into a single nonnull attribute. @@ -2944,7 +2952,7 @@ def WarnUnusedResult : InheritableAttr { C2x<"", "nodiscard", 201904>, CXX11<"clang", "warn_unused_result">, GCC<"warn_unused_result">]; - let Subjects = SubjectList<[ObjCMethod, Enum, Record, FunctionLike]>; + let Subjects = SubjectList<[ObjCMethod, Enum, Record, FunctionLike, TypedefName]>; let Args = [StringArgument<"Message", 1>]; let Documentation = [WarnUnusedResultsDocs]; let AdditionalMembers = [{ @@ -2959,7 +2967,7 @@ def WarnUnusedResult : InheritableAttr { def Weak : InheritableAttr { let Spellings = [GCC<"weak">]; let Subjects = SubjectList<[Var, Function, CXXRecord]>; - let Documentation = [Undocumented]; + let Documentation = [WeakDocs]; let SimpleHandler = 1; } diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index aedf11a707530..dbb7f695a5a2c 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -5833,6 +5833,15 @@ attribute can also be written using C++11 syntax: ``[[mig::server_routine]]``. }]; } +def MinSizeDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +This function attribute indicates that optimization passes and code generator passes +make choices that keep the function code size as small as possible. Optimizations may +also sacrifice runtime performance in order to minimize the size of the generated code. + }]; +} + def MSAllocatorDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -6477,3 +6486,103 @@ is only supported in compute shaders. The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sv-groupindex }]; } + +def AnnotateTypeDocs : Documentation { + let Category = DocCatType; + let Heading = "annotate_type"; + let Content = [{ +This attribute is used to add annotations to types, typically for use by static +analysis tools that are not integrated into the core Clang compiler (e.g., +Clang-Tidy checks or out-of-tree Clang-based tools). It is a counterpart to the +`annotate` attribute, which serves the same purpose, but for declarations. + +The attribute takes a mandatory string literal argument specifying the +annotation category and an arbitrary number of optional arguments that provide +additional information specific to the annotation category. The optional +arguments must be constant expressions of arbitrary type. + +For example: + +.. code-block:: c++ + + int* [[clang::annotate("category1", "foo", 1)]] f(int[[clang::annotate("category2")]] *); + +The attribute does not have any effect on the semantics of the type system, +neither type checking rules, nor runtime semantics. In particular: + +- ``std::is_same`` is true for all types + ``T``. + +- It is not permissible for overloaded functions or template specializations + to differ merely by an ``annotate_type`` attribute. + +- The presence of an ``annotate_type`` attribute will not affect name + mangling. + }]; +} + +def WeakDocs : Documentation { + let Category = DocCatDecl; + let Content = [{ + +In supported output formats the ``weak`` attribute can be used to +specify that a variable or function should be emitted as a symbol with +``weak`` (if a definition) or ``extern_weak`` (if a declaration of an +external symbol) `linkage +`_. + +If there is a non-weak definition of the symbol the linker will select +that over the weak. They must have same type and alignment (variables +must also have the same size), but may have a different value. + +If there are multiple weak definitions of same symbol, but no non-weak +definition, they should have same type, size, alignment and value, the +linker will select one of them (see also selectany_ attribute). + +If the ``weak`` attribute is applied to a ``const`` qualified variable +definition that variable is no longer consider a compiletime constant +as its value can change during linking (or dynamic linking). This +means that it can e.g no longer be part of an initializer expression. + +.. code-block:: c + + const int ANSWER __attribute__ ((weak)) = 42; + + /* This function may be replaced link-time */ + __attribute__ ((weak)) void debug_log(const char *msg) + { + fprintf(stderr, "DEBUG: %s\n", msg); + } + + int main(int argc, const char **argv) + { + debug_log ("Starting up..."); + + /* This may print something else than "6 * 7 = 42", + if there is a non-weak definition of "ANSWER" in + an object linked in */ + printf("6 * 7 = %d\n", ANSWER); + + return 0; + } + +If an external declaration is marked weak and that symbol does not +exist during linking (possibly dynamic) the address of the symbol will +evaluate to NULL. + +.. code-block:: c + + void may_not_exist(void) __attribute__ ((weak)); + + int main(int argc, const char **argv) + { + if (may_not_exist) { + may_not_exist(); + } else { + printf("Function did not exist\n"); + } + return 0; + } + + }]; +} diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h index 478b9df371209..81a8d21341938 100644 --- a/clang/include/clang/Basic/AttributeCommonInfo.h +++ b/clang/include/clang/Basic/AttributeCommonInfo.h @@ -69,7 +69,7 @@ class AttributeCommonInfo { // Corresponds to the Kind enum. unsigned AttrKind : 16; /// Corresponds to the Syntax enum. - unsigned SyntaxUsed : 3; + unsigned SyntaxUsed : 4; unsigned SpellingIndex : 4; protected: @@ -146,9 +146,25 @@ class AttributeCommonInfo { bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; } bool isGNUScope() const; + bool isClangScope() const; bool isAlignasAttribute() const { // FIXME: Use a better mechanism to determine this. + // We use this in `isCXX11Attribute` below, so it _should_ only return + // true for the `alignas` spelling, but it currently also returns true + // for the `_Alignas` spelling, which only exists in C11. Distinguishing + // between the two is important because they behave differently: + // - `alignas` may only appear in the attribute-specifier-seq before + // the decl-specifier-seq and is therefore associated with the + // declaration. + // - `_Alignas` may appear anywhere within the declaration-specifiers + // and is therefore associated with the `DeclSpec`. + // It's not clear how best to fix this: + // - We have the necessary information in the form of the `SpellingIndex`, + // but we would need to compare against AlignedAttr::Keyword_alignas, + // and we can't depend on clang/AST/Attr.h here. + // - We could test `getAttrName()->getName() == "alignas"`, but this is + // inefficient. return getParsedKind() == AT_Aligned && isKeywordAttribute(); } @@ -164,6 +180,8 @@ class AttributeCommonInfo { return isCXX11Attribute() || isC2xAttribute(); } + bool isGNUAttribute() const { return SyntaxUsed == AS_GNU; } + bool isKeywordAttribute() const { return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword; } diff --git a/clang/include/clang/Basic/Attributes.h b/clang/include/clang/Basic/Attributes.h index 4afb6a1b9ca25..3fc5fbacdb2cb 100644 --- a/clang/include/clang/Basic/Attributes.h +++ b/clang/include/clang/Basic/Attributes.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_BASIC_ATTRIBUTES_H #define LLVM_CLANG_BASIC_ATTRIBUTES_H +#include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/TargetInfo.h" @@ -16,28 +17,11 @@ namespace clang { class IdentifierInfo; -enum class AttrSyntax { - /// Is the identifier known as a GNU-style attribute? - GNU, - /// Is the identifier known as a __declspec-style attribute? - Declspec, - /// Is the identifier known as a [] Microsoft-style attribute? - Microsoft, - // Is the identifier known as a C++-style attribute? - CXX, - // Is the identifier known as a C-style attribute? - C, - // Is the identifier known as a pragma attribute? - Pragma, - // Is the identifier known as a HLSL semantic? - HLSLSemantic, -}; - /// Return the version number associated with the attribute if we /// recognize and implement the attribute specified by the given information. -int hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, - const IdentifierInfo *Attr, const TargetInfo &Target, - const LangOptions &LangOpts); +int hasAttribute(AttributeCommonInfo::Syntax Syntax, + const IdentifierInfo *Scope, const IdentifierInfo *Attr, + const TargetInfo &Target, const LangOptions &LangOpts); } // end namespace clang diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index e9b8ac6c602a4..c084cc2c4cbdf 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -142,10 +142,12 @@ BUILTIN(__builtin_frexpf128, "LLdLLdi*", "Fn") BUILTIN(__builtin_huge_val, "d", "nc") BUILTIN(__builtin_huge_valf, "f", "nc") BUILTIN(__builtin_huge_vall, "Ld", "nc") +BUILTIN(__builtin_huge_valf16, "x", "nc") BUILTIN(__builtin_huge_valf128, "LLd", "nc") BUILTIN(__builtin_inf , "d" , "nc") BUILTIN(__builtin_inff , "f" , "nc") BUILTIN(__builtin_infl , "Ld" , "nc") +BUILTIN(__builtin_inff16 , "x" , "nc") BUILTIN(__builtin_inff128 , "LLd" , "nc") BUILTIN(__builtin_labs , "LiLi" , "Fnc") BUILTIN(__builtin_llabs, "LLiLLi", "Fnc") @@ -160,10 +162,12 @@ BUILTIN(__builtin_modff128, "LLdLLdLLd*", "Fn") BUILTIN(__builtin_nan, "dcC*" , "FnU") BUILTIN(__builtin_nanf, "fcC*" , "FnU") BUILTIN(__builtin_nanl, "LdcC*", "FnU") +BUILTIN(__builtin_nanf16, "xcC*", "FnU") BUILTIN(__builtin_nanf128, "LLdcC*", "FnU") BUILTIN(__builtin_nans, "dcC*" , "FnU") BUILTIN(__builtin_nansf, "fcC*" , "FnU") BUILTIN(__builtin_nansl, "LdcC*", "FnU") +BUILTIN(__builtin_nansf16, "xcC*", "FnU") BUILTIN(__builtin_nansf128, "LLdcC*", "FnU") BUILTIN(__builtin_powi , "ddi" , "Fnc") BUILTIN(__builtin_powif, "ffi" , "Fnc") @@ -551,10 +555,11 @@ BUILTIN(__builtin_malloc, "v*z", "nF") BUILTIN(__builtin_memchr, "v*vC*iz", "nF") BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF") BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF") -BUILTIN(__builtin_memcpy_inline, "vv*vC*Iz", "nt") +BUILTIN(__builtin_memcpy_inline, "vv*vC*Iz", "n") BUILTIN(__builtin_memmove, "v*v*vC*z", "nF") BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF") BUILTIN(__builtin_memset, "v*v*iz", "nF") +BUILTIN(__builtin_memset_inline, "vv*iIz", "n") BUILTIN(__builtin_printf, "icC*.", "Fp:0:") BUILTIN(__builtin_stpcpy, "c*c*cC*", "nF") BUILTIN(__builtin_stpncpy, "c*c*cC*z", "nF") @@ -1693,6 +1698,9 @@ BUILTIN(__builtin_os_log_format, "v*v*cC*.", "p:0:nt") // CUDA/HIP LANGBUILTIN(__builtin_get_device_side_mangled_name, "cC*.", "ncT", CUDA_LANG) +// HLSL +LANGBUILTIN(WaveActiveCountBits, "Uib", "nc", HLSL_LANG) + // Builtins for XRay BUILTIN(__xray_customevent, "vcC*z", "") BUILTIN(__xray_typedevent, "vzcC*z", "") diff --git a/clang/include/clang/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h index f7348f2b2a7c9..2761f5d282ac0 100644 --- a/clang/include/clang/Basic/Builtins.h +++ b/clang/include/clang/Basic/Builtins.h @@ -42,6 +42,7 @@ enum LanguageID { OCL_PIPE = 0x200, // builtin requires OpenCL pipe. OCL_DSE = 0x400, // builtin requires OpenCL device side enqueue. ALL_OCL_LANGUAGES = 0x800, // builtin for OCL languages. + HLSL_LANG = 0x1000, // builtin requires HLSL. ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages. ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode. ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode. diff --git a/clang/include/clang/Basic/BuiltinsARM.def b/clang/include/clang/Basic/BuiltinsARM.def index be20c24aa28ae..0cea0a9051e5b 100644 --- a/clang/include/clang/Basic/BuiltinsARM.def +++ b/clang/include/clang/Basic/BuiltinsARM.def @@ -197,6 +197,9 @@ BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc") BUILTIN(__builtin_arm_wsr64, "vcC*LLUi", "nc") BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc") +// Misc +BUILTIN(__builtin_sponentry, "v*", "c") + // Builtins for implementing ACLE MVE intrinsics. (Unlike NEON, these // don't need to live in a separate BuiltinsMVE.def, because they // aren't included from both here and BuiltinsAArch64.def.) diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def index 923215cc3e5d0..04934ec2b9e18 100644 --- a/clang/include/clang/Basic/BuiltinsPPC.def +++ b/clang/include/clang/Basic/BuiltinsPPC.def @@ -843,7 +843,7 @@ BUILTIN(__builtin_dcbf, "vvC*", "") // Provided builtins with _mma_ prefix for compatibility. CUSTOM_BUILTIN(mma_lxvp, vsx_lxvp, "W256SLiW256C*", false) -CUSTOM_BUILTIN(mma_stxvp, vsx_stxvp, "vW256SLiW256C*", false) +CUSTOM_BUILTIN(mma_stxvp, vsx_stxvp, "vW256SLiW256*", false) CUSTOM_BUILTIN(mma_assemble_pair, vsx_assemble_pair, "vW256*VV", false) CUSTOM_BUILTIN(mma_disassemble_pair, vsx_disassemble_pair, "vv*W256*", false) CUSTOM_BUILTIN(vsx_build_pair, vsx_assemble_pair, "vW256*VV", false) @@ -855,7 +855,7 @@ CUSTOM_BUILTIN(mma_build_acc, mma_assemble_acc, "vW512*VVVV", false) // This avoids repeating the ID and INTR in the macro expression. UNALIASED_CUSTOM_BUILTIN(vsx_lxvp, "W256SLiW256C*", false) -UNALIASED_CUSTOM_BUILTIN(vsx_stxvp, "vW256SLiW256C*", false) +UNALIASED_CUSTOM_BUILTIN(vsx_stxvp, "vW256SLiW256*", false) UNALIASED_CUSTOM_BUILTIN(vsx_assemble_pair, "vW256*VV", false) UNALIASED_CUSTOM_BUILTIN(vsx_disassemble_pair, "vv*W256*", false) diff --git a/clang/include/clang/Basic/BuiltinsWebAssembly.def b/clang/include/clang/Basic/BuiltinsWebAssembly.def index 24fb24f81fc14..03c6162f62e3f 100644 --- a/clang/include/clang/Basic/BuiltinsWebAssembly.def +++ b/clang/include/clang/Basic/BuiltinsWebAssembly.def @@ -184,5 +184,10 @@ TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_u_i32x4_f32x4, "V4UiV4f", "nc", "rel TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_s_zero_i32x4_f64x2, "V4iV2d", "nc", "relaxed-simd") TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_u_zero_i32x4_f64x2, "V4UiV2d", "nc", "relaxed-simd") +TARGET_BUILTIN(__builtin_wasm_relaxed_q15mulr_s_i16x8, "V8sV8sV8s", "nc", "relaxed-simd") + +TARGET_BUILTIN(__builtin_wasm_dot_i8x16_i7x16_s_i16x8, "V8sV16ScV16Sc", "nc", "relaxed-simd") +TARGET_BUILTIN(__builtin_wasm_dot_i8x16_i7x16_add_s_i32x4, "V4iV16ScV16ScV4i", "nc", "relaxed-simd") + #undef BUILTIN #undef TARGET_BUILTIN diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index d8f667dc387bb..8e89106993c26 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -114,6 +114,10 @@ CODEGENOPT(StackSizeSection , 1, 0) ///< Set when -fstack-size-section is enabl CODEGENOPT(ForceDwarfFrameSection , 1, 0) ///< Set when -fforce-dwarf-frame is ///< enabled. +///< Set when -femit-dwarf-unwind is passed. +ENUM_CODEGENOPT(EmitDwarfUnwind, llvm::EmitDwarfUnwindType, 2, + llvm::EmitDwarfUnwindType::Default) + ///< Set when -fxray-always-emit-customevents is enabled. CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0) diff --git a/clang/include/clang/Basic/DiagnosticCategories.h b/clang/include/clang/Basic/DiagnosticCategories.h index 2bbdeb31a7b7d..14be326f7515f 100644 --- a/clang/include/clang/Basic/DiagnosticCategories.h +++ b/clang/include/clang/Basic/DiagnosticCategories.h @@ -21,7 +21,8 @@ namespace clang { }; enum class Group { -#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups) GroupName, +#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \ + GroupName, #include "clang/Basic/DiagnosticGroups.inc" #undef CATEGORY #undef DIAG_ENTRY diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index c140a33694f37..39dee7e683ff9 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -163,6 +163,8 @@ def err_opencl_unknown_type_specifier : Error< def warn_unknown_attribute_ignored : Warning< "unknown attribute %0 ignored">, InGroup; +def warn_attribute_ignored : Warning<"%0 attribute ignored">, + InGroup; def err_use_of_tag_name_without_tag : Error< "must use '%1' tag to refer to type %0%select{| in this scope}2">; diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 9f4864a33a33b..96219f83b0a53 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -36,10 +36,6 @@ def warn_drv_avr_mcu_not_specified : Warning< "no target microcontroller specified on command line, cannot " "link standard libraries, please pass -mmcu=">, InGroup; -def warn_drv_avr_gcc_not_found: Warning< - "no avr-gcc installation can be found on the system, " - "cannot link standard libraries">, - InGroup; def warn_drv_avr_libc_not_found: Warning< "no avr-libc installation can be found on the system, " "cannot link standard libraries">, @@ -212,6 +208,8 @@ def err_drv_invalid_libcxx_deployment : Error< "invalid deployment target for -stdlib=libc++ (requires %0 or later)">; def err_drv_invalid_argument_to_option : Error< "invalid argument '%0' to -%1">; +def err_drv_missing_sanitizer_ignorelist : Error< + "missing sanitizer ignorelist: '%0'">; def err_drv_malformed_sanitizer_ignorelist : Error< "malformed sanitizer ignorelist: '%0'">; def err_drv_malformed_sanitizer_coverage_allowlist : Error< @@ -455,6 +453,10 @@ def err_analyzer_checker_incompatible_analyzer_option : Error< def err_analyzer_not_built_with_z3 : Error< "analyzer constraint manager 'z3' is only available if LLVM was built with " "-DLLVM_ENABLE_Z3_SOLVER=ON">; +def warn_analyzer_deprecated_option : Warning< + "analyzer option '%0' is deprecated. This flag will be removed in %1, and " + "passing this option will be an error.">, + InGroup; def warn_drv_needs_hvx : Warning< "%0 requires HVX, use -mhvx/-mhvx= to enable it">, @@ -666,6 +668,8 @@ def err_drv_target_variant_invalid : Error< def err_drv_invalid_directx_shader_module : Error< "invalid profile : %0">; +def err_drv_dxc_missing_target_profile : Error< + "target profile option (-T) is missing">; def err_drv_invalid_range_dxil_validator_version : Error< "invalid validator version : %0\n" diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index a7c34038ba3f7..10da02ecbf7e8 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -15,6 +15,8 @@ def Implicit : DiagGroup<"implicit", [ ImplicitInt ]>; +def DeprecatedStaticAnalyzerFlag : DiagGroup<"deprecated-static-analyzer-flag">; + // Empty DiagGroups are recognized by clang but ignored. def ODR : DiagGroup<"odr">; def : DiagGroup<"abi">; @@ -611,7 +613,12 @@ def StaticInInline : DiagGroup<"static-in-inline">; def StaticLocalInInline : DiagGroup<"static-local-in-inline">; def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">; def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>; -def GNUStatementExpression : DiagGroup<"gnu-statement-expression">; +// Allow differentiation between GNU statement expressions in a macro versus +// written directly in source. +def GNUStatementExpressionFromMacroExpansion : + DiagGroup<"gnu-statement-expression-from-macro-expansion">; +def GNUStatementExpression : DiagGroup<"gnu-statement-expression", + [GNUStatementExpressionFromMacroExpansion]>; def StringConcatation : DiagGroup<"string-concatenation">; def StringCompare : DiagGroup<"string-compare">; def StringPlusInt : DiagGroup<"string-plus-int">; diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h index f27bf356888c4..709d5e1dc80d4 100644 --- a/clang/include/clang/Basic/DiagnosticIDs.h +++ b/clang/include/clang/Basic/DiagnosticIDs.h @@ -231,6 +231,9 @@ class DiagnosticIDs : public RefCountedBase { /// "deprecated-declarations". static StringRef getWarningOptionForGroup(diag::Group); + /// Given a diagnostic group ID, return its documentation. + static StringRef getWarningOptionDocumentation(diag::Group GroupID); + /// Given a group ID, returns the flag that toggles the group. /// For example, for "deprecated-declarations", returns /// Group::DeprecatedDeclarations. diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 74930a4690d7b..b0abe2aa517e7 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -174,6 +174,9 @@ def err_stmtexpr_file_scope : Error< "statement expression not allowed at file scope">; def ext_gnu_statement_expr : Extension< "use of GNU statement expression extension">, InGroup; +def ext_gnu_statement_expr_macro : Extension< + "use of GNU statement expression extension from macro expansion">, + InGroup; def ext_gnu_conditional_expr : Extension< "use of GNU ?: conditional expression extension, omitting middle operand">, InGroup; def ext_gnu_empty_initializer : Extension< @@ -1275,7 +1278,7 @@ def warn_pragma_expected_colon : Warning< def warn_pragma_expected_predicate : Warning< "expected %select{'enable', 'disable', 'begin' or 'end'|'disable'}0 - ignoring">, InGroup; def warn_pragma_unknown_extension : Warning< - "unknown OpenCL extension %0 - ignoring">, InGroup; + "OpenCL extension %0 unknown or does not require pragma - ignoring">, InGroup; def warn_pragma_unsupported_extension : Warning< "unsupported OpenCL extension %0 - ignoring">, InGroup; def warn_pragma_extension_is_core : Warning< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 0f8ed0a6e8c31..f2190613d740e 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3354,8 +3354,6 @@ def warn_redeclaration_without_import_attribute : Warning< def warn_dllimport_dropped_from_inline_function : Warning< "%q0 redeclared inline; %1 attribute ignored">, InGroup; -def warn_attribute_ignored : Warning<"%0 attribute ignored">, - InGroup; def warn_nothrow_attribute_ignored : Warning<"'nothrow' attribute conflicts with" " exception specification; attribute ignored">, InGroup; @@ -3392,8 +3390,11 @@ def note_attribute_has_no_effect_on_compile_time_if_here : Note< "annotating the 'if %select{constexpr|consteval}0' statement here">; def err_decl_attribute_invalid_on_stmt : Error< "%0 attribute cannot be applied to a statement">; -def err_stmt_attribute_invalid_on_decl : Error< +def err_attribute_invalid_on_decl : Error< "%0 attribute cannot be applied to a declaration">; +def warn_type_attribute_deprecated_on_decl : Warning< + "applying attribute %0 to a declaration is deprecated; apply it to the type instead">, + InGroup; def warn_declspec_attribute_ignored : Warning< "attribute %0 is ignored, place it after " "\"%select{class|struct|interface|union|enum}1\" to apply attribute to " @@ -6137,6 +6138,9 @@ def note_exits_block_captures_non_trivial_c_struct : Note< def note_exits_compound_literal_scope : Note< "jump exits lifetime of a compound literal that is non-trivial to destruct">; +def err_func_returning_qualified_void : ExtWarn< + "function cannot return qualified void type %0">, + InGroup>; def err_func_returning_array_function : Error< "function cannot return %select{array|function}0 type %1">; def err_field_declared_as_function : Error<"field %0 declared as a function">; @@ -8731,6 +8735,10 @@ def warn_unused_result : Warning< def warn_unused_result_msg : Warning< "ignoring return value of function declared with %0 attribute: %1">, InGroup; +def warn_unused_result_typedef_unsupported_spelling : Warning< + "'[[%select{nodiscard|gnu::warn_unused_result}0]]' attribute ignored when " + "applied to a typedef; consider using '__attribute__((warn_unused_result))' " + "or '[[clang::warn_unused_result]]' instead">, InGroup; def warn_unused_volatile : Warning< "expression result unused; assign into a variable to force a volatile load">, InGroup>; diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index f241d68a23ed9..a7f0ae03e0beb 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -49,6 +49,8 @@ FEATURE(memtag_stack, LangOpts.Sanitize.has(SanitizerKind::MemtagStack)) FEATURE(memtag_heap, LangOpts.Sanitize.has(SanitizerKind::MemtagHeap)) +FEATURE(memtag_globals, + LangOpts.Sanitize.has(SanitizerKind::MemtagGlobals)) FEATURE(xray_instrument, LangOpts.XRayInstrument) FEATURE(undefined_behavior_sanitizer, LangOpts.Sanitize.hasOneOf(SanitizerKind::Undefined)) diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 6e1a01c6c9767..aa346ba239391 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -88,6 +88,7 @@ LANGOPT(C11 , 1, 0, "C11") LANGOPT(C17 , 1, 0, "C17") LANGOPT(C2x , 1, 0, "C2x") LANGOPT(MSVCCompat , 1, 0, "Microsoft Visual C++ full compatibility mode") +LANGOPT(Kernel , 1, 0, "Kernel mode") LANGOPT(MicrosoftExt , 1, 0, "Microsoft C++ extensions") LANGOPT(AsmBlocks , 1, 0, "Microsoft inline asm blocks") LANGOPT(Borland , 1, 0, "Borland extensions") @@ -289,6 +290,7 @@ BENIGN_LANGOPT(DumpRecordLayoutsComplete , 1, 0, "dumping the AST layout of all BENIGN_LANGOPT(DumpVTableLayouts , 1, 0, "dumping the layouts of emitted vtables") LANGOPT(NoConstantCFStrings , 1, 0, "no constant CoreFoundation strings") BENIGN_LANGOPT(InlineVisibilityHidden , 1, 0, "hidden visibility for inline C++ methods") +BENIGN_ENUM_LANGOPT(DefaultVisibilityExportMapping, DefaultVisiblityExportMapping, 2, DefaultVisiblityExportMapping::None, "controls mapping of default visibility to dllexport") BENIGN_LANGOPT(IgnoreXCOFFVisibility, 1, 0, "All the visibility attributes that are specified in the source code are ignored in aix XCOFF.") BENIGN_LANGOPT(VisibilityInlinesHiddenStaticLocalVar, 1, 0, "hidden visibility for static local variables in inline C++ " @@ -445,6 +447,11 @@ ENUM_LANGOPT(ExtendIntArgs, ExtendArgsKind, 1, ExtendArgsKind::ExtendTo32, VALUE_LANGOPT(FuchsiaAPILevel, 32, 0, "Fuchsia API level") +// This option will be removed in the future once the backend +// supports all operations (like division or float-to-integer conversion) +// on large _BitInts. +BENIGN_VALUE_LANGOPT(MaxBitIntWidth, 32, 128, "Maximum width of a _BitInt") + #undef LANGOPT #undef COMPATIBLE_LANGOPT #undef BENIGN_LANGOPT diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 6e7763a4a2b47..cf121de6699c8 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -350,6 +350,14 @@ class LangOptions : public LangOptionsBase { PerThread, }; + enum class DefaultVisiblityExportMapping { + None, + /// map only explicit default visibilities to exported + Explicit, + /// map all default visibilities to exported + All, + }; + public: /// The used language standard. LangStandard::Kind LangStd; @@ -581,6 +589,21 @@ class LangOptions : public LangOptionsBase { bool isSYCL() const { return SYCLIsDevice || SYCLIsHost; } + bool hasDefaultVisibilityExportMapping() const { + return getDefaultVisibilityExportMapping() != + DefaultVisiblityExportMapping::None; + } + + bool isExplicitDefaultVisibilityExportMapping() const { + return getDefaultVisibilityExportMapping() == + DefaultVisiblityExportMapping::Explicit; + } + + bool isAllDefaultVisibilityExportMapping() const { + return getDefaultVisibilityExportMapping() == + DefaultVisiblityExportMapping::All; + } + /// Remap path prefix according to -fmacro-prefix-path option. void remapPathPrefix(SmallVectorImpl &Path) const; }; diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def index 714934445cf95..8e7b6cd0a7e29 100644 --- a/clang/include/clang/Basic/Sanitizers.def +++ b/clang/include/clang/Basic/Sanitizers.def @@ -58,7 +58,8 @@ SANITIZER("kernel-hwaddress", KernelHWAddress) // A variant of AddressSanitizer using AArch64 MTE extension. SANITIZER("memtag-stack", MemtagStack) SANITIZER("memtag-heap", MemtagHeap) -SANITIZER_GROUP("memtag", MemTag, MemtagStack | MemtagHeap) +SANITIZER("memtag-globals", MemtagGlobals) +SANITIZER_GROUP("memtag", MemTag, MemtagStack | MemtagHeap | MemtagGlobals) // MemorySanitizer SANITIZER("memory", Memory) diff --git a/clang/include/clang/Basic/SourceLocation.h b/clang/include/clang/Basic/SourceLocation.h index 543245a811db5..4451523bc9450 100644 --- a/clang/include/clang/Basic/SourceLocation.h +++ b/clang/include/clang/Basic/SourceLocation.h @@ -24,7 +24,7 @@ namespace llvm { class FoldingSetNodeID; -template struct FoldingSetTrait; +template struct FoldingSetTrait; } // namespace llvm @@ -87,7 +87,7 @@ class SourceLocation { friend class ASTReader; friend class ASTWriter; friend class SourceManager; - friend struct llvm::FoldingSetTrait; + friend struct llvm::FoldingSetTrait; public: using UIntTy = uint32_t; @@ -507,7 +507,7 @@ namespace llvm { }; // Allow calling FoldingSetNodeID::Add with SourceLocation object as parameter - template <> struct FoldingSetTrait { + template <> struct FoldingSetTrait { static void Profile(const clang::SourceLocation &X, FoldingSetNodeID &ID); }; diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index e4b5f0b751c48..5877123dab249 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -31,6 +31,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Frontend/OpenMP/OMPGridValues.h" +#include "llvm/IR/DerivedTypes.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/Error.h" #include "llvm/Support/VersionTuple.h" @@ -235,6 +236,8 @@ class TargetInfo : public virtual TransferrableTargetInfo, unsigned MaxOpenCLWorkGroupSize; + Optional MaxBitIntWidth; + Optional DarwinTargetVariantTriple; // TargetInfo Constructor. Default initializes all fields. @@ -595,11 +598,16 @@ class TargetInfo : public virtual TransferrableTargetInfo, // Different targets may support a different maximum width for the _BitInt // type, depending on what operations are supported. virtual size_t getMaxBitIntWidth() const { + // Consider -fexperimental-max-bitint-width= first. + if (MaxBitIntWidth) + return std::min(*MaxBitIntWidth, llvm::IntegerType::MAX_INT_BITS); + // FIXME: this value should be llvm::IntegerType::MAX_INT_BITS, which is // maximum bit width that LLVM claims its IR can support. However, most - // backends currently have a bug where they only support division - // operations on types that are <= 128 bits and crash otherwise. We're - // setting the max supported value to 128 to be conservative. + // backends currently have a bug where they only support float to int + // conversion (and vice versa) on types that are <= 128 bits and crash + // otherwise. We're setting the max supported value to 128 to be + // conservative. return 128; } diff --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td index 18304f55da0c4..933a6c11f3359 100644 --- a/clang/include/clang/Basic/riscv_vector.td +++ b/clang/include/clang/Basic/riscv_vector.td @@ -139,7 +139,7 @@ def HasPassthruOperand : Policy<1>; def HasPolicyOperand : Policy<2>; class RVVBuiltin { + string overloaded_suffix = ""> { // Base name that will be prepended in __builtin_rvv_ and appended the // computed Suffix. string Name = NAME; @@ -148,14 +148,14 @@ class RVVBuiltin { let IRName = intrinsic_name; let MaskedIRName = intrinsic_name # "_mask"; - let MangledName = NAME; + let OverloadedName = NAME; let IntrinsicTypes = [-1, 0]; } @@ -462,29 +462,29 @@ class RVVFloatingUnaryBuiltin; class RVVConvBuiltin + string overloaded_name> : RVVBuiltin { let IntrinsicTypes = [-1, 0]; - let MangledName = mangled_name; + let OverloadedName = overloaded_name; } -class RVVConvToSignedBuiltin - : RVVConvBuiltin<"Iv", "Ivv", "xfd", mangled_name>; +class RVVConvToSignedBuiltin + : RVVConvBuiltin<"Iv", "Ivv", "xfd", overloaded_name>; -class RVVConvToUnsignedBuiltin - : RVVConvBuiltin<"Uv", "Uvv", "xfd", mangled_name>; +class RVVConvToUnsignedBuiltin + : RVVConvBuiltin<"Uv", "Uvv", "xfd", overloaded_name>; -class RVVConvToWidenSignedBuiltin - : RVVConvBuiltin<"Iw", "Iwv", "xf", mangled_name>; +class RVVConvToWidenSignedBuiltin + : RVVConvBuiltin<"Iw", "Iwv", "xf", overloaded_name>; -class RVVConvToWidenUnsignedBuiltin - : RVVConvBuiltin<"Uw", "Uwv", "xf", mangled_name>; +class RVVConvToWidenUnsignedBuiltin + : RVVConvBuiltin<"Uw", "Uwv", "xf", overloaded_name>; -class RVVConvToNarrowingSignedBuiltin - : RVVConvBuiltin<"Iv", "IvFw", "csi", mangled_name>; +class RVVConvToNarrowingSignedBuiltin + : RVVConvBuiltin<"Iv", "IvFw", "csi", overloaded_name>; -class RVVConvToNarrowingUnsignedBuiltin - : RVVConvBuiltin<"Uv", "UvFw", "csi", mangled_name>; +class RVVConvToNarrowingUnsignedBuiltin + : RVVConvBuiltin<"Uv", "UvFw", "csi", overloaded_name>; let HasMaskedOffOperand = false in { multiclass RVVSignedReductionBuiltin { @@ -516,7 +516,7 @@ multiclass RVVWidenBuiltinSet; @@ -532,7 +532,7 @@ multiclass RVVWidenWOp0BuiltinSet; @@ -1424,7 +1424,7 @@ multiclass RVVPseudoVFUnaryBuiltin { multiclass RVVPseudoVWCVTBuiltin> suffixes_prototypes> { let Name = NAME, - MangledName = MName, + OverloadedName = MName, IRName = IR, MaskedIRName = IR # "_mask", ManualCodegen = [{ @@ -1462,7 +1462,7 @@ multiclass RVVPseudoVWCVTBuiltin> suffixes_prototypes> { let Name = NAME, - MangledName = MName, + OverloadedName = MName, IRName = IR, MaskedIRName = IR # "_mask", ManualCodegen = [{ @@ -1497,6 +1497,56 @@ multiclass RVVPseudoVNCVTBuiltin; defm vmv_v : RVVOutBuiltinSet<"vmv_v_v", "csilxfd", @@ -2043,11 +2093,11 @@ let UnMaskedPolicy = HasPassthruOperand, HasUnMaskedOverloaded = false in { // 17. Vector Permutation Instructions // 17.1. Integer Scalar Move Instructions let HasMasked = false, MaskedPolicy = NonePolicy in { - let HasVL = false, MangledName = "vmv_x" in + let HasVL = false, OverloadedName = "vmv_x" in defm vmv_x : RVVOp0BuiltinSet<"vmv_x_s", "csil", [["s", "ve", "ev"], ["s", "UvUe", "UeUv"]]>; - let MangledName = "vmv_s" in + let OverloadedName = "vmv_s" in defm vmv_s : RVVOutBuiltinSet<"vmv_s_x", "csil", [["x", "v", "vve"], ["x", "Uv", "UvUvUe"]]>; @@ -2055,10 +2105,10 @@ let HasMasked = false, MaskedPolicy = NonePolicy in { // 17.2. Floating-Point Scalar Move Instructions let HasMasked = false, MaskedPolicy = NonePolicy in { - let HasVL = false, MangledName = "vfmv_f" in + let HasVL = false, OverloadedName = "vfmv_f" in defm vfmv_f : RVVOp0BuiltinSet<"vfmv_f_s", "xfd", [["s", "ve", "ev"]]>; - let MangledName = "vfmv_s" in + let OverloadedName = "vfmv_s" in defm vfmv_s : RVVOutBuiltinSet<"vfmv_s_f", "xfd", [["f", "v", "vve"], ["x", "Uv", "UvUvUe"]]>; @@ -2144,7 +2194,7 @@ let HasMasked = false, HasVL = false, IRName = "" in { // LMUL truncation // C/C++ Operand: VecTy, IR Operand: VecTy, Index - let Name = "vlmul_trunc_v", MangledName = "vlmul_trunc", MaskedPolicy = NonePolicy, + let Name = "vlmul_trunc_v", OverloadedName = "vlmul_trunc", MaskedPolicy = NonePolicy, ManualCodegen = [{ { ID = Intrinsic::experimental_vector_extract; IntrinsicTypes = {ResultType, Ops[0]->getType()}; @@ -2162,7 +2212,7 @@ let HasMasked = false, HasVL = false, IRName = "" in { // LMUL extension // C/C++ Operand: SubVecTy, IR Operand: VecTy, SubVecTy, Index - let Name = "vlmul_ext_v", MangledName = "vlmul_ext", MaskedPolicy = NonePolicy, + let Name = "vlmul_ext_v", OverloadedName = "vlmul_ext", MaskedPolicy = NonePolicy, ManualCodegen = [{ ID = Intrinsic::experimental_vector_insert; IntrinsicTypes = {ResultType, Ops[0]->getType()}; diff --git a/clang/include/clang/Driver/Compilation.h b/clang/include/clang/Driver/Compilation.h index 260e2a34ed5a7..c5714d3208884 100644 --- a/clang/include/clang/Driver/Compilation.h +++ b/clang/include/clang/Driver/Compilation.h @@ -295,16 +295,22 @@ class Compilation { /// /// \param FailingCommand - For non-zero results, this will be set to the /// Command which failed, if any. + /// \param LogOnly - When true, only tries to log the command, not actually + /// execute it. /// \return The result code of the subprocess. - int ExecuteCommand(const Command &C, const Command *&FailingCommand) const; + int ExecuteCommand(const Command &C, const Command *&FailingCommand, + bool LogOnly = false) const; /// ExecuteJob - Execute a single job. /// /// \param FailingCommands - For non-zero results, this will be a vector of /// failing commands and their associated result code. - void ExecuteJobs( - const JobList &Jobs, - SmallVectorImpl> &FailingCommands) const; + /// \param LogOnly - When true, only tries to log the command, not actually + /// execute it. + void + ExecuteJobs(const JobList &Jobs, + SmallVectorImpl> &FailingCommands, + bool LogOnly = false) const; /// initCompilationForDiagnostics - Remove stale state and suppress output /// so compilation can be reexecuted to generate additional diagnostic diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index f0f294a669d98..774eac613a100 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -12,6 +12,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LLVM.h" #include "clang/Driver/Action.h" +#include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/InputInfo.h" #include "clang/Driver/Options.h" #include "clang/Driver/Phases.h" @@ -94,6 +95,12 @@ class Driver { EmbedBitcode } BitcodeEmbed; + enum OffloadMode { + OffloadHostDevice, + OffloadHost, + OffloadDevice, + } Offload; + /// Header unit mode set by -fmodule-header={user,system}. ModuleHeaderMode CXX20HeaderType; @@ -276,11 +283,6 @@ class Driver { unsigned ProbePrecompiled : 1; public: - /// Force clang to emit reproducer for driver invocation. This is enabled - /// indirectly by setting FORCE_CLANG_DIAGNOSTICS_CRASH environment variable - /// or when using the -gen-reproducer driver flag. - unsigned GenReproducer : 1; - // getFinalPhase - Determine which compilation mode we are in and record // which option we used to determine the final phase. // TODO: Much of what getFinalPhase returns are not actually true compiler @@ -395,6 +397,9 @@ class Driver { bool embedBitcodeInObject() const { return (BitcodeEmbed == EmbedBitcode); } bool embedBitcodeMarkerOnly() const { return (BitcodeEmbed == EmbedMarker); } + bool offloadHostOnly() const { return Offload == OffloadHost; } + bool offloadDeviceOnly() const { return Offload == OffloadDevice; } + /// Compute the desired OpenMP runtime from the flags provided. OpenMPRuntimeKind getOpenMPRuntime(const llvm::opt::ArgList &Args) const; @@ -505,6 +510,35 @@ class Driver { StringRef AdditionalInformation = "", CompilationDiagnosticReport *GeneratedReport = nullptr); + enum class CommandStatus { + Crash = 1, + Error, + Ok, + }; + + enum class ReproLevel { + Off = 0, + OnCrash = static_cast(CommandStatus::Crash), + OnError = static_cast(CommandStatus::Error), + Always = static_cast(CommandStatus::Ok), + }; + + bool maybeGenerateCompilationDiagnostics( + CommandStatus CS, ReproLevel Level, Compilation &C, + const Command &FailingCommand, StringRef AdditionalInformation = "", + CompilationDiagnosticReport *GeneratedReport = nullptr) { + if (static_cast(CS) > static_cast(Level)) + return false; + if (CS != CommandStatus::Crash) + Diags.Report(diag::err_drv_force_crash) + << !::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"); + // Hack to ensure that diagnostic notes get emitted. + Diags.setLastDiagnosticIgnored(false); + generateCompilationDiagnostics(C, FailingCommand, AdditionalInformation, + GeneratedReport); + return true; + } + /// @} /// @name Helper Methods /// @{ diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 0343e48c1a9d1..5fa681f538194 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -558,7 +558,10 @@ def arcmt_migrate_report_output : Separate<["-"], "arcmt-migrate-report-output"> def arcmt_migrate_emit_arc_errors : Flag<["-"], "arcmt-migrate-emit-errors">, HelpText<"Emit ARC errors even if the migrator can fix them">, Flags<[CC1Option]>, MarshallingInfoFlag>; +def gen_reproducer_eq: Joined<["-"], "gen-reproducer=">, Flags<[NoArgumentUnused, CoreOption]>, + HelpText<"Emit reproducer on (option: off, crash (default), error, always)">; def gen_reproducer: Flag<["-"], "gen-reproducer">, InternalDebugOpt, + Alias, AliasArgs<["always"]>, HelpText<"Auto-generates preprocessed source files and a reproduction script">; def gen_cdb_fragment_path: Separate<["-"], "gen-cdb-fragment-path">, InternalDebugOpt, HelpText<"Emit a compilation database fragment to the specified directory">; @@ -772,6 +775,8 @@ def Wa_COMMA : CommaJoined<["-"], "Wa,">, MetaVarName<"">; def Wall : Flag<["-"], "Wall">, Group, Flags<[CC1Option, HelpHidden]>; def WCL4 : Flag<["-"], "WCL4">, Group, Flags<[CC1Option, HelpHidden]>; +def Wsystem_headers : Flag<["-"], "Wsystem-headers">, Group, Flags<[CC1Option, HelpHidden]>; +def Wno_system_headers : Flag<["-"], "Wno-system-headers">, Group, Flags<[CC1Option, HelpHidden]>; def Wdeprecated : Flag<["-"], "Wdeprecated">, Group, Flags<[CC1Option]>, HelpText<"Enable warnings for deprecated constructs and define __DEPRECATED">; def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group, Flags<[CC1Option]>; @@ -1397,6 +1402,7 @@ def fexperimental_new_constant_interpreter : Flag<["-"], "fexperimental-new-cons def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">, Group; def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group, Flags<[NoArgumentUnused, CoreOption]>, + Alias, AliasArgs<["off"]>, HelpText<"Disable auto-generation of preprocessed source files and a script for reproduction during a clang crash">; def fcrash_diagnostics_dir : Joined<["-"], "fcrash-diagnostics-dir=">, Group, Flags<[NoArgumentUnused, CoreOption]>, @@ -1410,7 +1416,7 @@ defm async_exceptions: BoolFOption<"async-exceptions", PosFlag, NegFlag>; defm cxx_modules : BoolFOption<"cxx-modules", LangOpts<"CPlusPlusModules">, Default, - NegFlag, PosFlag, + NegFlag, PosFlag, BothFlags<[NoXarchOption], " modules for C++">>, ShouldParseIf; def fdebug_pass_arguments : Flag<["-"], "fdebug-pass-arguments">, Group; @@ -2174,6 +2180,8 @@ def fms_memptr_rep_EQ : Joined<["-"], "fms-memptr-rep=">, Group, Flags< NormalizedValues<["PPTMK_FullGeneralitySingleInheritance", "PPTMK_FullGeneralityMultipleInheritance", "PPTMK_FullGeneralityVirtualInheritance"]>, MarshallingInfoEnum, "PPTMK_BestCase">; +def fms_kernel : Flag<["-"], "fms-kernel">, Group, Flags<[CC1Option, NoDriverOption]>, + MarshallingInfoFlag>; // __declspec is enabled by default for the PS4 by the driver, and also // enabled for Microsoft Extensions or Borland Extensions, here. // @@ -2745,6 +2753,8 @@ defm strict_vtable_pointers : BoolFOption<"strict-vtable-pointers", " overwriting polymorphic C++ objects">, NegFlag>; def fstrict_overflow : Flag<["-"], "fstrict-overflow">, Group; +def fdriver_only : Flag<["-"], "fdriver-only">, Flags<[NoXarchOption, CoreOption]>, + Group, HelpText<"Only run the driver.">; def fsyntax_only : Flag<["-"], "fsyntax-only">, Flags<[NoXarchOption,CoreOption,CC1Option,FC1Option]>, Group; def ftabstop_EQ : Joined<["-"], "ftabstop=">, Group; @@ -2910,6 +2920,13 @@ def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group def fvisibility_global_new_delete_hidden : Flag<["-"], "fvisibility-global-new-delete-hidden">, Group, HelpText<"Give global C++ operator new and delete declarations hidden visibility">, Flags<[CC1Option]>, MarshallingInfoFlag>; +def mdefault_visibility_export_mapping_EQ : Joined<["-"], "mdefault-visibility-export-mapping=">, + Values<"none,explicit,all">, + NormalizedValuesScope<"LangOptions::DefaultVisiblityExportMapping">, + NormalizedValues<["None", "Explicit", "All"]>, + HelpText<"Mapping between default visibility and export">, + Group, Flags<[CC1Option]>, + MarshallingInfoEnum,"None">; defm new_infallible : BoolFOption<"new-infallible", LangOpts<"NewInfallible">, DefaultFalse, PosFlag, NegFlag, @@ -3038,6 +3055,13 @@ def fmacro_prefix_map_EQ defm force_dwarf_frame : BoolFOption<"force-dwarf-frame", CodeGenOpts<"ForceDwarfFrameSection">, DefaultFalse, PosFlag, NegFlag>; +def femit_dwarf_unwind_EQ : Joined<["-"], "femit-dwarf-unwind=">, + Group, Flags<[CC1Option, CC1AsOption]>, + HelpText<"When to emit DWARF unwind (EH frame) info">, + Values<"always,no-compact-unwind,default">, + NormalizedValues<["Always", "NoCompactUnwind", "Default"]>, + NormalizedValuesScope<"llvm::EmitDwarfUnwindType">, + MarshallingInfoEnum, "Default">; def g_Flag : Flag<["-"], "g">, Group, HelpText<"Generate source-level debug information">; def gline_tables_only : Flag<["-"], "gline-tables-only">, Group, @@ -3521,7 +3545,10 @@ def mbranch_protection_EQ : Joined<["-"], "mbranch-protection=">, HelpText<"Enforce targets of indirect branches and function returns">; def mharden_sls_EQ : Joined<["-"], "mharden-sls=">, - HelpText<"Select straight-line speculation hardening scope">; + HelpText<"Select straight-line speculation hardening scope (ARM/AArch64/X86" + " only). must be: all, none, retbr(ARM/AArch64)," + " blr(ARM/AArch64), comdat(ARM/AArch64), nocomdat(ARM/AArch64)," + " return(X86), indirect-jmp(X86)">; def msimd128 : Flag<["-"], "msimd128">, Group; def mno_simd128 : Flag<["-"], "mno-simd128">, Group; @@ -3996,6 +4023,8 @@ def print_rocm_search_dirs : Flag<["-", "--"], "print-rocm-search-dirs">, HelpText<"Print the paths used for finding ROCm installation">; def print_runtime_dir : Flag<["-", "--"], "print-runtime-dir">, HelpText<"Print the directory pathname containing clangs runtime libraries">; +def print_diagnostic_options : Flag<["-", "--"], "print-diagnostic-options">, + HelpText<"Print all of Clang's warning options">; def private__bundle : Flag<["-"], "private_bundle">; def pthreads : Flag<["-"], "pthreads">; defm pthread : BoolOption<"", "pthread", @@ -4155,7 +4184,8 @@ def why_load : Flag<["-"], "why_load">; def whyload : Flag<["-"], "whyload">, Alias; def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">, Flags<[CC1Option]>, MarshallingInfoFlag>; -def x : JoinedOrSeparate<["-"], "x">, Flags<[NoXarchOption,CC1Option]>, +def x : JoinedOrSeparate<["-"], "x">, +Flags<[NoXarchOption,CC1Option,FlangOption,FC1Option]>, HelpText<"Treat subsequent input files as having type ">, MetaVarName<"">; def y : Joined<["-"], "y">; @@ -4984,8 +5014,9 @@ def analysis_UnoptimizedCFG : Flag<["-"], "unoptimized-cfg">, def analysis_CFGAddImplicitDtors : Flag<["-"], "cfg-add-implicit-dtors">, HelpText<"Add C++ implicit destructors to CFGs for all analyses">; +// We should remove this option in clang-16 release. def analyzer_store : Separate<["-"], "analyzer-store">, - HelpText<"Source Code Analysis - Abstract Memory Store Models">; + HelpText<"Source Code Analysis - Abstract Memory Store Models [DEPRECATED, removing in clang-16]">; def analyzer_store_EQ : Joined<["-"], "analyzer-store=">, Alias; def analyzer_constraints : Separate<["-"], "analyzer-constraints">, @@ -5005,9 +5036,9 @@ def analyzer_purge_EQ : Joined<["-"], "analyzer-purge=">, Alias; def analyzer_opt_analyze_headers : Flag<["-"], "analyzer-opt-analyze-headers">, HelpText<"Force the static analyzer to analyze functions defined in header files">, MarshallingInfoFlag>; +// We should remove this option in clang-16 release. def analyzer_opt_analyze_nested_blocks : Flag<["-"], "analyzer-opt-analyze-nested-blocks">, - HelpText<"Analyze the definitions of blocks in addition to functions">, - MarshallingInfoFlag>; + HelpText<"Analyze the definitions of blocks in addition to functions [DEPRECATED, removing in clang-16]">; def analyzer_display_progress : Flag<["-"], "analyzer-display-progress">, HelpText<"Emit verbose output about the analyzer's progress">, MarshallingInfoFlag>; @@ -6051,7 +6082,7 @@ def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">, // These options cannot be marshalled, because they are used to set up the LangOptions defaults. def finclude_default_header : Flag<["-"], "finclude-default-header">, - HelpText<"Include default header file for OpenCL">; + HelpText<"Include default header file for OpenCL and HLSL">; def fdeclare_opencl_builtins : Flag<["-"], "fdeclare-opencl-builtins">, HelpText<"Add OpenCL builtin function declarations (experimental)">; @@ -6082,6 +6113,12 @@ def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group, def fobjc_gc : Flag<["-"], "fobjc-gc">, Group, HelpText<"Enable Objective-C garbage collection">; +def fexperimental_max_bitint_width_EQ: + Joined<["-"], "fexperimental-max-bitint-width=">, Group, + MetaVarName<"">, + HelpText<"Set the maximum bitwidth for _BitInt (this option is expected to be removed in the future)">, + MarshallingInfoInt>; + } // let Flags = [CC1Option, NoDriverOption] //===----------------------------------------------------------------------===// @@ -6441,6 +6478,11 @@ def _SLASH_validate_charset : CLFlag<"validate-charset">, Alias, AliasArgs<["invalid-source-encoding"]>; def _SLASH_validate_charset_ : CLFlag<"validate-charset-">, Alias, AliasArgs<["no-invalid-source-encoding"]>; +def _SLASH_external_W0 : CLFlag<"external:W0">, HelpText<"Ignore warnings from system headers (default)">, Alias; +def _SLASH_external_W1 : CLFlag<"external:W1">, HelpText<"Enable -Wsystem-headers">, Alias; +def _SLASH_external_W2 : CLFlag<"external:W2">, HelpText<"Enable -Wsystem-headers">, Alias; +def _SLASH_external_W3 : CLFlag<"external:W3">, HelpText<"Enable -Wsystem-headers">, Alias; +def _SLASH_external_W4 : CLFlag<"external:W4">, HelpText<"Enable -Wsystem-headers">, Alias; def _SLASH_W0 : CLFlag<"W0">, HelpText<"Disable all warnings">, Alias; def _SLASH_W1 : CLFlag<"W1">, HelpText<"Enable -Wall">, Alias; def _SLASH_W2 : CLFlag<"W2">, HelpText<"Enable -Wall">, Alias; @@ -6541,7 +6583,7 @@ def _SLASH_EP : CLFlag<"EP">, def _SLASH_external_env : CLJoined<"external:env:">, HelpText<"Add dirs in env var to include search path with warnings suppressed">, MetaVarName<"">; -def _SLASH_FA : CLFlag<"FA">, +def _SLASH_FA : CLJoined<"FA">, HelpText<"Output assembly code file during compilation">; def _SLASH_Fa : CLJoined<"Fa">, HelpText<"Set assembly output file name (with /FA)">, @@ -6709,7 +6751,6 @@ def _SLASH_doc : CLJoined<"doc">; def _SLASH_experimental : CLJoined<"experimental:">; def _SLASH_exportHeader : CLFlag<"exportHeader">; def _SLASH_external : CLJoined<"external:">; -def _SLASH_FA_joined : CLJoined<"FA">; def _SLASH_favor : CLJoined<"favor">; def _SLASH_fsanitize_address_use_after_return : CLJoined<"fsanitize-address-use-after-return">; def _SLASH_fno_sanitize_address_vcasan_lib : CLJoined<"fno-sanitize-address-vcasan-lib">; @@ -6780,6 +6821,8 @@ class DXCJoinedOrSeparate : Option<["/", "-"], name, def dxc_help : Option<["/", "-", "--"], "help", KIND_JOINED>, Group, Flags<[DXCOption, NoXarchOption]>, Alias, HelpText<"Display available options">; +def dxc_no_stdinc : DXCFlag<"hlsl-no-stdinc">, + HelpText<"HLSL only. Disables all standard includes containing non-native compiler types and functions.">; def Fo : DXCJoinedOrSeparate<"Fo">, Alias, HelpText<"Output object file">; def dxil_validator_version : Option<["/", "-"], "validator-version", KIND_SEPARATE>, @@ -6798,6 +6841,8 @@ def target_profile : DXCJoinedOrSeparate<"T">, MetaVarName<"">, "lib_6_3, lib_6_4, lib_6_5, lib_6_6, lib_6_7, lib_6_x," "ms_6_5, ms_6_6, ms_6_7," "as_6_5, as_6_6, as_6_7">; +def dxc_D : Option<["--", "/", "-"], "D", KIND_JOINED_OR_SEPARATE>, + Group, Flags<[DXCOption, NoXarchOption]>, Alias; def emit_pristine_llvm : DXCFlag<"emit-pristine-llvm">, HelpText<"Emit pristine LLVM IR from the frontend by not running any LLVM passes at all." "Same as -S + -emit-llvm + -disable-llvm-passes.">; diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h index a681ad3b2e05b..1b29b1151224f 100644 --- a/clang/include/clang/Driver/SanitizerArgs.h +++ b/clang/include/clang/Driver/SanitizerArgs.h @@ -99,13 +99,18 @@ class SanitizerArgs { bool needsStatsRt() const { return Stats; } bool needsScudoRt() const { return Sanitizers.has(SanitizerKind::Scudo); } - bool hasMemTag() const { return hasMemtagHeap() || hasMemtagStack(); } + bool hasMemTag() const { + return hasMemtagHeap() || hasMemtagStack() || hasMemtagGlobals(); + } bool hasMemtagHeap() const { return Sanitizers.has(SanitizerKind::MemtagHeap); } bool hasMemtagStack() const { return Sanitizers.has(SanitizerKind::MemtagStack); } + bool hasMemtagGlobals() const { + return Sanitizers.has(SanitizerKind::MemtagGlobals); + } const std::string &getMemtagMode() const { assert(!MemtagMode.empty()); return MemtagMode; diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index d53e5d020c4a9..8249060dc7c04 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -398,7 +398,7 @@ struct FormatStyle { /// This option is **deprecated**. See ``NextLine`` of /// ``PackConstructorInitializers``. /// \version 9 - bool AllowAllConstructorInitializersOnNextLine; + // bool AllowAllConstructorInitializersOnNextLine; /// If the function declaration doesn't fit on a line, /// allow putting all parameters of a function declaration onto @@ -1886,7 +1886,7 @@ struct FormatStyle { /// This option is **deprecated**. See ``CurrentLine`` of /// ``PackConstructorInitializers``. /// \version 3.7 - bool ConstructorInitializerAllOnOneLineOrOnePerLine; + // bool ConstructorInitializerAllOnOneLineOrOnePerLine; /// The number of characters to use for indentation of constructor /// initializer lists as well as inheritance lists. diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h index 6cf9f3ff936f1..420246278b478 100644 --- a/clang/include/clang/Frontend/ASTUnit.h +++ b/clang/include/clang/Frontend/ASTUnit.h @@ -696,7 +696,9 @@ class ASTUnit { bool UseDebugInfo = false, bool OnlyLocalDecls = false, CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None, bool AllowASTWithCompilerErrors = false, - bool UserFilesAreVolatile = false); + bool UserFilesAreVolatile = false, + IntrusiveRefCntPtr VFS = + llvm::vfs::getRealFileSystem()); private: /// Helper function for \c LoadFromCompilerInvocation() and diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index b523ad5ef9ff2..1b7eda333b6bd 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -727,8 +727,7 @@ class HeaderSearch { /// frameworks. /// /// \returns The module, if found; otherwise, null. - Module *loadFrameworkModule(StringRef Name, - const DirectoryEntry *Dir, + Module *loadFrameworkModule(StringRef Name, DirectoryEntryRef Dir, bool IsSystem); /// Load all of the module maps within the immediate subdirectories @@ -884,7 +883,7 @@ class HeaderSearch { LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File, bool IsSystem, - const DirectoryEntry *Dir, + DirectoryEntryRef Dir, FileID ID = FileID(), unsigned *Offset = nullptr); @@ -908,8 +907,8 @@ class HeaderSearch { /// /// \returns The result of attempting to load the module map file from the /// named directory. - LoadModuleMapResult loadModuleMapFile(const DirectoryEntry *Dir, - bool IsSystem, bool IsFramework); + LoadModuleMapResult loadModuleMapFile(DirectoryEntryRef Dir, bool IsSystem, + bool IsFramework); }; /// Apply the header search options to get given HeaderSearch object. diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 6d8f03e3ceb1b..9bd4b40a60770 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -952,6 +952,18 @@ class Preprocessor { /// of that list. MacroInfoChain *MIChainHead = nullptr; + /// True if \p Preprocessor::SkipExcludedConditionalBlock() is running. + /// This is used to guard against calling this function recursively. + /// + /// See comments at the use-site for more context about why it is needed. + bool SkippingExcludedConditionalBlock = false; + + /// Keeps track of skipped range mappings that were recorded while skipping + /// excluded conditional directives. It maps the source buffer pointer at + /// the beginning of a skipped block, to the number of bytes that should be + /// skipped. + llvm::DenseMap RecordedSkippedRanges; + void updateOutOfDateIdentifier(IdentifierInfo &II) const; public: @@ -2243,10 +2255,7 @@ class Preprocessor { /// /// \param Tok - Token that represents the directive /// \param Directive - String reference for the directive name - /// \param EndLoc - End location for fixit - void SuggestTypoedDirective(const Token &Tok, - StringRef Directive, - const SourceLocation &EndLoc) const; + void SuggestTypoedDirective(const Token &Tok, StringRef Directive) const; /// We just read a \#if or related directive and decided that the /// subsequent tokens are in the \#if'd out portion of the diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index a20866e410aa4..0eb6f7104a55b 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2075,7 +2075,8 @@ class Parser : public CodeCompletionHandler { SourceLocation *TrailingElseLoc = nullptr); StmtResult ParseStatementOrDeclarationAfterAttributes( StmtVector &Stmts, ParsedStmtContext StmtCtx, - SourceLocation *TrailingElseLoc, ParsedAttributes &Attrs); + SourceLocation *TrailingElseLoc, ParsedAttributes &DeclAttrs, + ParsedAttributes &DeclSpecAttrs); StmtResult ParseExprStatement(ParsedStmtContext StmtCtx); StmtResult ParseLabeledStatement(ParsedAttributes &Attrs, ParsedStmtContext StmtCtx); @@ -2195,7 +2196,8 @@ class Parser : public CodeCompletionHandler { DSC_template_param, // template parameter context DSC_template_type_arg, // template type argument context DSC_objc_method_result, // ObjC method result context, enables 'instancetype' - DSC_condition // condition declaration context + DSC_condition, // condition declaration context + DSC_association // A _Generic selection expression's type association }; /// Is this a context in which we are parsing just a type-specifier (or @@ -2214,6 +2216,7 @@ class Parser : public CodeCompletionHandler { case DeclSpecContext::DSC_type_specifier: case DeclSpecContext::DSC_trailing: case DeclSpecContext::DSC_alias_declaration: + case DeclSpecContext::DSC_association: return true; } llvm_unreachable("Missing DeclSpecContext case"); @@ -2238,7 +2241,7 @@ class Parser : public CodeCompletionHandler { /// so permit class and enum definitions in addition to non-defining class and /// enum elaborated-type-specifiers)? static AllowDefiningTypeSpec - isDefiningTypeSpecifierContext(DeclSpecContext DSC) { + isDefiningTypeSpecifierContext(DeclSpecContext DSC, bool IsCPlusPlus) { switch (DSC) { case DeclSpecContext::DSC_normal: case DeclSpecContext::DSC_class: @@ -2255,6 +2258,10 @@ class Parser : public CodeCompletionHandler { case DeclSpecContext::DSC_type_specifier: return AllowDefiningTypeSpec::NoButErrorRecovery; + case DeclSpecContext::DSC_association: + return IsCPlusPlus ? AllowDefiningTypeSpec::NoButErrorRecovery + : AllowDefiningTypeSpec::Yes; + case DeclSpecContext::DSC_trailing: return AllowDefiningTypeSpec::No; } @@ -2276,6 +2283,7 @@ class Parser : public CodeCompletionHandler { case DeclSpecContext::DSC_template_type_arg: case DeclSpecContext::DSC_type_specifier: case DeclSpecContext::DSC_trailing: + case DeclSpecContext::DSC_association: return false; } llvm_unreachable("Missing DeclSpecContext case"); @@ -2291,6 +2299,7 @@ class Parser : public CodeCompletionHandler { case DeclSpecContext::DSC_top_level: case DeclSpecContext::DSC_condition: case DeclSpecContext::DSC_type_specifier: + case DeclSpecContext::DSC_association: return true; case DeclSpecContext::DSC_objc_method_result: @@ -2316,15 +2325,18 @@ class Parser : public CodeCompletionHandler { DeclGroupPtrTy ParseDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd, - ParsedAttributes &Attrs, + ParsedAttributes &DeclAttrs, + ParsedAttributes &DeclSpecAttrs, SourceLocation *DeclSpecStart = nullptr); DeclGroupPtrTy ParseSimpleDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd, - ParsedAttributes &Attrs, bool RequireSemi, + ParsedAttributes &DeclAttrs, + ParsedAttributes &DeclSpecAttrs, bool RequireSemi, ForRangeInit *FRI = nullptr, SourceLocation *DeclSpecStart = nullptr); bool MightBeDeclarator(DeclaratorContext Context); DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, DeclaratorContext Context, + ParsedAttributes &Attrs, SourceLocation *DeclEnd = nullptr, ForRangeInit *FRI = nullptr); Decl *ParseDeclarationAfterDeclarator(Declarator &D, diff --git a/clang/include/clang/Parse/RAIIObjectsForParser.h b/clang/include/clang/Parse/RAIIObjectsForParser.h index 8e6e03685c507..5ae609e600734 100644 --- a/clang/include/clang/Parse/RAIIObjectsForParser.h +++ b/clang/include/clang/Parse/RAIIObjectsForParser.h @@ -201,9 +201,11 @@ namespace clang { ParsingDeclRAIIObject ParsingRAII; public: - ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, DeclaratorContext C) - : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) { - } + ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, + const ParsedAttributes &DeclarationAttrs, + DeclaratorContext C) + : Declarator(DS, DeclarationAttrs, C), + ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {} const ParsingDeclSpec &getDeclSpec() const { return static_cast(Declarator::getDeclSpec()); @@ -228,9 +230,10 @@ namespace clang { ParsingDeclRAIIObject ParsingRAII; public: - ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS) - : FieldDeclarator(DS), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) { - } + ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS, + const ParsedAttributes &DeclarationAttrs) + : FieldDeclarator(DS, DeclarationAttrs), + ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {} const ParsingDeclSpec &getDeclSpec() const { return static_cast(D.getDeclSpec()); diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index c03ead9c79b34..21d4a53d8e22b 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1786,7 +1786,8 @@ enum class DeclaratorContext { TemplateTypeArg, // Template type argument (in default argument). AliasDecl, // C++11 alias-declaration. AliasTemplate, // C++11 alias-declaration template. - RequiresExpr // C++2a requires-expression. + RequiresExpr, // C++2a requires-expression. + Association // C11 _Generic selection expression association. }; /// Information about one declarator, including the parsed type @@ -1851,9 +1852,13 @@ class Declarator { /// Indicates whether this declarator has an initializer. unsigned HasInitializer : 1; - /// Attrs - Attributes. + /// Attributes attached to the declarator. ParsedAttributes Attrs; + /// Attributes attached to the declaration. See also documentation for the + /// corresponding constructor parameter. + const ParsedAttributesView &DeclarationAttrs; + /// The asm label, if specified. Expr *AsmLabel; @@ -1892,16 +1897,40 @@ class Declarator { friend struct DeclaratorChunk; public: - Declarator(const DeclSpec &ds, DeclaratorContext C) - : DS(ds), Range(ds.getSourceRange()), Context(C), + /// `DS` and `DeclarationAttrs` must outlive the `Declarator`. In particular, + /// take care not to pass temporary objects for these parameters. + /// + /// `DeclarationAttrs` contains [[]] attributes from the + /// attribute-specifier-seq at the beginning of a declaration, which appertain + /// to the declared entity itself. Attributes with other syntax (e.g. GNU) + /// should not be placed in this attribute list; if they occur at the + /// beginning of a declaration, they apply to the `DeclSpec` and should be + /// attached to that instead. + /// + /// Here is an example of an attribute associated with a declaration: + /// + /// [[deprecated]] int x, y; + /// + /// This attribute appertains to all of the entities declared in the + /// declaration, i.e. `x` and `y` in this case. + Declarator(const DeclSpec &DS, const ParsedAttributesView &DeclarationAttrs, + DeclaratorContext C) + : DS(DS), Range(DS.getSourceRange()), Context(C), InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error), GroupingParens(false), FunctionDefinition(static_cast( FunctionDefinitionKind::Declaration)), Redeclaration(false), Extension(false), ObjCIvar(false), ObjCWeakProperty(false), InlineStorageUsed(false), - HasInitializer(false), Attrs(ds.getAttributePool().getFactory()), - AsmLabel(nullptr), TrailingRequiresClause(nullptr), - InventedTemplateParameterList(nullptr) {} + HasInitializer(false), Attrs(DS.getAttributePool().getFactory()), + DeclarationAttrs(DeclarationAttrs), AsmLabel(nullptr), + TrailingRequiresClause(nullptr), + InventedTemplateParameterList(nullptr) { + assert(llvm::all_of(DeclarationAttrs, + [](const ParsedAttr &AL) { + return AL.isStandardAttributeSyntax(); + }) && + "DeclarationAttrs may only contain [[]] attributes"); + } ~Declarator() { clear(); @@ -2024,6 +2053,7 @@ class Declarator { case DeclaratorContext::TrailingReturn: case DeclaratorContext::TrailingReturnVar: case DeclaratorContext::RequiresExpr: + case DeclaratorContext::Association: return true; } llvm_unreachable("unknown context kind!"); @@ -2063,6 +2093,7 @@ class Declarator { case DeclaratorContext::TemplateTypeArg: case DeclaratorContext::TrailingReturn: case DeclaratorContext::TrailingReturnVar: + case DeclaratorContext::Association: return false; } llvm_unreachable("unknown context kind!"); @@ -2106,6 +2137,7 @@ class Declarator { case DeclaratorContext::TemplateTypeArg: case DeclaratorContext::TrailingReturn: case DeclaratorContext::TrailingReturnVar: + case DeclaratorContext::Association: return false; } llvm_unreachable("unknown context kind!"); @@ -2162,6 +2194,7 @@ class Declarator { case DeclaratorContext::TemplateTypeArg: case DeclaratorContext::TrailingReturn: case DeclaratorContext::RequiresExpr: + case DeclaratorContext::Association: return false; } llvm_unreachable("unknown context kind!"); @@ -2384,6 +2417,7 @@ class Declarator { case DeclaratorContext::TrailingReturn: case DeclaratorContext::TrailingReturnVar: case DeclaratorContext::RequiresExpr: + case DeclaratorContext::Association: return false; } llvm_unreachable("unknown context kind!"); @@ -2418,6 +2452,7 @@ class Declarator { case DeclaratorContext::TrailingReturnVar: case DeclaratorContext::TemplateTypeArg: case DeclaratorContext::RequiresExpr: + case DeclaratorContext::Association: return false; case DeclaratorContext::Block: @@ -2524,9 +2559,14 @@ class Declarator { const ParsedAttributes &getAttributes() const { return Attrs; } ParsedAttributes &getAttributes() { return Attrs; } + const ParsedAttributesView &getDeclarationAttributes() const { + return DeclarationAttrs; + } + /// hasAttributes - do we contain any attributes? bool hasAttributes() const { - if (!getAttributes().empty() || getDeclSpec().hasAttributes()) + if (!getAttributes().empty() || !getDeclarationAttributes().empty() || + getDeclSpec().hasAttributes()) return true; for (unsigned i = 0, e = getNumTypeObjects(); i != e; ++i) if (!getTypeObject(i).getAttrs().empty()) @@ -2608,8 +2648,10 @@ class Declarator { struct FieldDeclarator { Declarator D; Expr *BitfieldSize; - explicit FieldDeclarator(const DeclSpec &DS) - : D(DS, DeclaratorContext::Member), BitfieldSize(nullptr) {} + explicit FieldDeclarator(const DeclSpec &DS, + const ParsedAttributes &DeclarationAttrs) + : D(DS, DeclarationAttrs, DeclaratorContext::Member), + BitfieldSize(nullptr) {} }; /// Represents a C++11 virt-specifier-seq. diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h index 554d73b8901d7..2fe5d7c5c7155 100644 --- a/clang/include/clang/Sema/ParsedAttr.h +++ b/clang/include/clang/Sema/ParsedAttr.h @@ -651,6 +651,18 @@ class ParsedAttr final bool isKnownToGCC() const; bool isSupportedByPragmaAttribute() const; + /// Returns whether a [[]] attribute, if specified ahead of a declaration, + /// should be applied to the decl-specifier-seq instead (i.e. whether it + /// "slides" to the decl-specifier-seq). + /// + /// By the standard, attributes specified before the declaration always + /// appertain to the declaration, but historically we have allowed some of + /// these attributes to slide to the decl-specifier-seq, so we need to keep + /// supporting this behavior. + /// + /// This may only be called if isStandardAttributeSyntax() returns true. + bool slidesFromDeclToDeclSpecLegacyBehavior() const; + /// If the parsed attribute has a semantic equivalent, and it would /// have a semantic Spelling enumeration (due to having semantically-distinct /// spelling variations), return the value of that semantic spelling. If the @@ -901,6 +913,12 @@ class ParsedAttributesView { public: SourceRange Range; + + static const ParsedAttributesView &none() { + static const ParsedAttributesView Attrs; + return Attrs; + } + bool empty() const { return AttrList.empty(); } SizeType size() const { return AttrList.size(); } ParsedAttr &operator[](SizeType pos) { return *AttrList[pos]; } @@ -1103,6 +1121,11 @@ class ParsedAttributes : public ParsedAttributesView { mutable AttributePool pool; }; +/// Consumes the attributes from `First` and `Second` and concatenates them into +/// `Result`. Sets `Result.Range` to the combined range of `First` and `Second`. +void takeAndConcatenateAttrs(ParsedAttributes &First, ParsedAttributes &Second, + ParsedAttributes &Result); + /// These constants match the enumerated choices of /// err_attribute_argument_n_type and err_attribute_argument_type. enum AttributeArgumentNType { diff --git a/clang/include/clang/Sema/ParsedTemplate.h b/clang/include/clang/Sema/ParsedTemplate.h index 926cec2c547cd..65182d57246ae 100644 --- a/clang/include/clang/Sema/ParsedTemplate.h +++ b/clang/include/clang/Sema/ParsedTemplate.h @@ -212,9 +212,9 @@ namespace clang { } void Destroy() { - std::for_each( - getTemplateArgs(), getTemplateArgs() + NumArgs, - [](ParsedTemplateArgument &A) { A.~ParsedTemplateArgument(); }); + for (ParsedTemplateArgument &A : + llvm::make_range(getTemplateArgs(), getTemplateArgs() + NumArgs)) + A.~ParsedTemplateArgument(); this->~TemplateIdAnnotation(); free(this); } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 43dbf50d2829d..8a604f6c2a9f3 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4429,8 +4429,38 @@ class Sema final { // Helper for delayed processing of attributes. void ProcessDeclAttributeDelayed(Decl *D, const ParsedAttributesView &AttrList); - void ProcessDeclAttributeList(Scope *S, Decl *D, const ParsedAttributesView &AL, - bool IncludeCXX11Attributes = true); + + // Options for ProcessDeclAttributeList(). + struct ProcessDeclAttributeOptions { + ProcessDeclAttributeOptions() + : IncludeCXX11Attributes(true), IgnoreTypeAttributes(false) {} + + ProcessDeclAttributeOptions WithIncludeCXX11Attributes(bool Val) { + ProcessDeclAttributeOptions Result = *this; + Result.IncludeCXX11Attributes = Val; + return Result; + } + + ProcessDeclAttributeOptions WithIgnoreTypeAttributes(bool Val) { + ProcessDeclAttributeOptions Result = *this; + Result.IgnoreTypeAttributes = Val; + return Result; + } + + // Should C++11 attributes be processed? + bool IncludeCXX11Attributes; + + // Should any type attributes encountered be ignored? + // If this option is false, a diagnostic will be emitted for any type + // attributes of a kind that does not "slide" from the declaration to + // the decl-specifier-seq. + bool IgnoreTypeAttributes; + }; + + void ProcessDeclAttributeList(Scope *S, Decl *D, + const ParsedAttributesView &AttrList, + const ProcessDeclAttributeOptions &Options = + ProcessDeclAttributeOptions()); bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList); @@ -6716,7 +6746,6 @@ class Sema final { NestedNameSpecInfo &IdInfo, bool EnteringContext, CXXScopeSpec &SS, - bool ErrorRecoveryLookup = false, bool *IsCorrectedToColon = nullptr, bool OnlyNamespace = false); @@ -10389,6 +10418,13 @@ class Sema final { void AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI, StringRef Annot, MutableArrayRef Args); + /// ConstantFoldAttrArgs - Folds attribute arguments into ConstantExprs + /// (unless they are value dependent or type dependent). Returns false + /// and emits a diagnostic if one or more of the arguments could not be + /// folded into a constant. + bool ConstantFoldAttrArgs(const AttributeCommonInfo &CI, + MutableArrayRef Args); + /// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular /// declaration. void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI, @@ -12381,10 +12417,8 @@ class Sema final { /// VerifyBitField - verifies that a bit field expression is an ICE and has /// the correct width, and that the field type is valid. /// Returns false on success. - /// Can optionally return whether the bit-field is of width 0 ExprResult VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, - QualType FieldTy, bool IsMsStruct, - Expr *BitWidth, bool *ZeroWidth = nullptr); + QualType FieldTy, bool IsMsStruct, Expr *BitWidth); private: unsigned ForceCUDAHostDeviceDepth = 0; diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index 540d2c9aa87e7..5dcde77b5dd37 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -398,7 +398,7 @@ enum class TemplateSubstitutionKind : char { return newScope; } - /// deletes the given scope, and all otuer scopes, down to the + /// deletes the given scope, and all outer scopes, down to the /// given outermost scope. static void deleteScopes(LocalInstantiationScope *Scope, LocalInstantiationScope *Outermost) { diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 1ed234e644e79..0ea8b9002a974 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -41,7 +41,7 @@ namespace serialization { /// Version 4 of AST files also requires that the version control branch and /// revision match exactly, since there is no backward compatibility of /// AST files at this time. -const unsigned VERSION_MAJOR = 19; +const unsigned VERSION_MAJOR = 20; /// AST file minor version number supported by this version of /// Clang. diff --git a/clang/include/clang/StaticAnalyzer/Core/Analyses.def b/clang/include/clang/StaticAnalyzer/Core/Analyses.def index 88c375ce09255..51803e7c1f0d2 100644 --- a/clang/include/clang/StaticAnalyzer/Core/Analyses.def +++ b/clang/include/clang/StaticAnalyzer/Core/Analyses.def @@ -10,13 +10,6 @@ // //===----------------------------------------------------------------------===// -#ifndef ANALYSIS_STORE -#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) -#endif - -ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", - CreateRegionStoreManager) - #ifndef ANALYSIS_CONSTRAINTS #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) #endif @@ -94,7 +87,6 @@ ANALYSIS_INLINING_MODE( NoRedundancy, "noredundancy", "Do not analyze a function which has been previously inlined") -#undef ANALYSIS_STORE #undef ANALYSIS_CONSTRAINTS #undef ANALYSIS_DIAGNOSTICS #undef ANALYSIS_PURGE diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 0c4f9e6facb69..2baa7f2e0475d 100644 --- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -33,20 +33,6 @@ class CheckerBase; } // namespace ento -/// Analysis - Set of available source code analyses. -enum Analyses { -#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) NAME, -#include "clang/StaticAnalyzer/Core/Analyses.def" -NumAnalyses -}; - -/// AnalysisStores - Set of available analysis store models. -enum AnalysisStores { -#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, -#include "clang/StaticAnalyzer/Core/Analyses.def" -NumStores -}; - /// AnalysisConstraints - Set of available constraint models. enum AnalysisConstraints { #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, @@ -207,7 +193,6 @@ class AnalyzerOptions : public RefCountedBase { /// A key-value table of use-specified configuration values. // TODO: This shouldn't be public. ConfigTable Config; - AnalysisStores AnalysisStoreOpt = RegionStoreModel; AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel; AnalysisDiagClients AnalysisDiagOpt = PD_HTML; AnalysisPurgeMode AnalysisPurgeOpt = PurgeStmt; @@ -244,7 +229,6 @@ class AnalyzerOptions : public RefCountedBase { unsigned ShouldEmitErrorsOnInvalidConfigValue : 1; unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; - unsigned AnalyzeNestedBlocks : 1; unsigned eagerlyAssumeBinOpBifurcation : 1; @@ -306,10 +290,10 @@ class AnalyzerOptions : public RefCountedBase { ShowCheckerOptionList(false), ShowCheckerOptionAlphaList(false), ShowCheckerOptionDeveloperList(false), ShowEnabledCheckerList(false), ShowConfigOptionsList(false), AnalyzeAll(false), - AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false), - eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), - visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false), - PrintStats(false), NoRetryExhausted(false), AnalyzerWerror(false) { + AnalyzerDisplayProgress(false), eagerlyAssumeBinOpBifurcation(false), + TrimGraph(false), visualizeExplodedGraphWithGraphViz(false), + UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false), + AnalyzerWerror(false) { llvm::sort(AnalyzerConfigCmdFlags); } @@ -375,11 +359,6 @@ class AnalyzerOptions : public RefCountedBase { StringRef OptionName, bool SearchInParents = false) const; - /// Retrieves and sets the UserMode. This is a high-level option, - /// which is used to set other low-level options. It is not accessible - /// outside of AnalyzerOptions. - UserModeKind getUserMode() const; - ExplorationStrategyKind getExplorationStrategy() const; CTUPhase1InliningKind getCTUPhase1Inlining() const; @@ -419,15 +398,6 @@ using AnalyzerOptionsRef = IntrusiveRefCntPtr; // For this reason, implement some methods in this header file. //===----------------------------------------------------------------------===// -inline UserModeKind AnalyzerOptions::getUserMode() const { - auto K = llvm::StringSwitch>(UserMode) - .Case("shallow", UMK_Shallow) - .Case("deep", UMK_Deep) - .Default(None); - assert(K.hasValue() && "User mode is invalid."); - return K.getValue(); -} - inline std::vector AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental) { static constexpr llvm::StringLiteral StaticAnalyzerCheckerNames[] = { diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h index c42521376af92..685dc66182ef4 100644 --- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -397,7 +397,7 @@ class TrackConstraintBRVisitor final : public BugReporterVisitor { public: TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption) : Constraint(constraint), Assumption(assumption), - IsZeroCheck(!Assumption && Constraint.getAs()) {} + IsZeroCheck(!Assumption && isa(Constraint)) {} void Profile(llvm::FoldingSetNodeID &ID) const override; diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index 457247bcdf553..59bfbe3dea77b 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -90,9 +90,7 @@ class PointerToMemberData : public llvm::FoldingSetNode { public: PointerToMemberData(const NamedDecl *D, llvm::ImmutableList L) - : D(D), L(L) { - assert(D); - } + : D(D), L(L) {} using iterator = llvm::ImmutableList::iterator; @@ -104,7 +102,7 @@ class PointerToMemberData : public llvm::FoldingSetNode { void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, D, L); } - LLVM_ATTRIBUTE_RETURNS_NONNULL + /// It might return null. const NamedDecl *getDeclaratorDecl() const { return D; } llvm::ImmutableList getCXXBaseList() const { diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h index d1e06297252b3..11c60b6895627 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h @@ -130,19 +130,23 @@ class ConstraintManager { /// Convenience method to query the state to see if a symbol is null or /// not null, or if neither assumption can be made. ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym) { - SaveAndRestore DisableNotify(NotifyAssumeClients, false); - return checkNull(State, Sym); } protected: - /// A flag to indicate that clients should be notified of assumptions. - /// By default this is the case, but sometimes this needs to be restricted - /// to avoid infinite recursions within the ConstraintManager. - /// - /// Note that this flag allows the ConstraintManager to be re-entrant, - /// but not thread-safe. - bool NotifyAssumeClients = true; + /// A helper class to simulate the call stack of nested assume calls. + class AssumeStackTy { + public: + void push(const ProgramState *S) { Aux.push_back(S); } + void pop() { Aux.pop_back(); } + bool contains(const ProgramState *S) const { + return llvm::is_contained(Aux, S); + } + + private: + llvm::SmallVector Aux; + }; + AssumeStackTy AssumeStack; virtual ProgramStateRef assumeInternal(ProgramStateRef state, DefinedSVal Cond, bool Assumption) = 0; diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 6be33d488a9e3..3787f8f01b34e 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -228,6 +228,11 @@ class ExprEngine { const Stmt *getStmt() const; + const LocationContext *getRootLocationContext() const { + assert(G.roots_begin() != G.roots_end()); + return (*G.roots_begin())->getLocation().getLocationContext(); + } + void GenerateAutoTransition(ExplodedNode *N); void enqueueEndOfPath(ExplodedNodeSet &S); void GenerateCallExitNode(ExplodedNode *N); @@ -603,17 +608,6 @@ class ExprEngine { StmtNodeBuilder &Bldr); public: - SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, - NonLoc L, NonLoc R, QualType T) { - return svalBuilder.evalBinOpNN(state, op, L, R, T); - } - - SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, - NonLoc L, SVal R, QualType T) { - return R.isValid() ? svalBuilder.evalBinOpNN(state, op, L, - R.castAs(), T) : R; - } - SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op, SVal LHS, SVal RHS, QualType T) { return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index a61dd0cd9a379..2cb9a6a0a0ed6 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -1183,7 +1183,7 @@ class ElementRegion : public TypedValueRegion { ElementRegion(QualType elementType, NonLoc Idx, const SubRegion *sReg) : TypedValueRegion(sReg, ElementRegionKind), ElementType(elementType), Index(Idx) { - assert((!Idx.getAs() || + assert((!isa(Idx) || Idx.castAs().getValue().isSigned()) && "The index must be signed"); assert(!elementType.isNull() && !elementType->isVoidType() && diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 78abd0a0e42d7..1092d1292255d 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -118,8 +118,6 @@ class ProgramState : public llvm::FoldingSetNode { // overconstrained-related functions. We want to keep this API inaccessible // for Checkers. friend class ConstraintManager; - friend ProgramStateRef reAssume(ProgramStateRef State, - const RangeSet *Constraint, SVal TheValue); bool isPosteriorlyOverconstrained() const { return PosteriorlyOverconstrained; } @@ -729,7 +727,7 @@ inline ProgramStateRef ProgramState::assumeInclusiveRange( if (Val.isUnknown()) return this; - assert(Val.getAs() && "Only NonLocs are supported!"); + assert(isa(Val) && "Only NonLocs are supported!"); return getStateManager().ConstraintMgr->assumeInclusiveRange( this, Val.castAs(), From, To, Assumption); @@ -742,7 +740,7 @@ ProgramState::assumeInclusiveRange(DefinedOrUnknownSVal Val, if (Val.isUnknown()) return std::make_pair(this, this); - assert(Val.getAs() && "Only NonLocs are supported!"); + assert(isa(Val) && "Only NonLocs are supported!"); return getStateManager().ConstraintMgr->assumeInclusiveRangeDual( this, Val.castAs(), From, To); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h index da82a55e36256..15bec97c5be8f 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h @@ -21,29 +21,32 @@ #include "llvm/ADT/ImmutableSet.h" #include "llvm/Support/Allocator.h" #include +#include namespace clang { namespace ento { - template struct ProgramStatePartialTrait; - - /// Declares a program state trait for type \p Type called \p Name, and - /// introduce a type named \c NameTy. - /// The macro should not be used inside namespaces. - #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \ - namespace { \ - class Name {}; \ - using Name ## Ty = Type; \ - } \ - namespace clang { \ - namespace ento { \ - template <> \ - struct ProgramStateTrait \ - : public ProgramStatePartialTrait { \ - static void *GDMIndex() { static int Index; return &Index; } \ - }; \ - } \ - } +template struct ProgramStatePartialTrait; + +/// Declares a program state trait for type \p Type called \p Name, and +/// introduce a type named \c NameTy. +/// The macro should not be used inside namespaces. +#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \ + namespace { \ + class Name {}; \ + using Name##Ty = Type; \ + } \ + namespace clang { \ + namespace ento { \ + template <> \ + struct ProgramStateTrait : public ProgramStatePartialTrait { \ + static void *GDMIndex() { \ + static int Index; \ + return &Index; \ + } \ + }; \ + } \ + } /// Declares a factory for objects of type \p Type in the program state /// manager. The type must provide a ::Factory sub-class. Commonly used for @@ -267,60 +270,27 @@ namespace ento { } }; - // Partial specialization for bool. - template <> struct ProgramStatePartialTrait { - using data_type = bool; - - static data_type MakeData(void *const *p) { - return p ? (data_type) (uintptr_t) *p - : data_type(); - } - - static void *MakeVoidPtr(data_type d) { - return (void *) (uintptr_t) d; - } + template struct DefaultProgramStatePartialTraitImpl { + using data_type = T; + static T MakeData(void *const *P) { return P ? (T)(uintptr_t)*P : T{}; } + static void *MakeVoidPtr(T D) { return (void *)(uintptr_t)D; } }; - // Partial specialization for unsigned. - template <> struct ProgramStatePartialTrait { - using data_type = unsigned; - - static data_type MakeData(void *const *p) { - return p ? (data_type) (uintptr_t) *p - : data_type(); - } - - static void *MakeVoidPtr(data_type d) { - return (void *) (uintptr_t) d; - } - }; - - // Partial specialization for void*. - template <> struct ProgramStatePartialTrait { - using data_type = void *; - - static data_type MakeData(void *const *p) { - return p ? *p - : data_type(); - } - - static void *MakeVoidPtr(data_type d) { - return d; - } - }; - - // Partial specialization for const void *. - template <> struct ProgramStatePartialTrait { - using data_type = const void *; + // Partial specialization for integral types. + template + struct ProgramStatePartialTrait::value>> + : DefaultProgramStatePartialTraitImpl {}; - static data_type MakeData(void *const *p) { - return p ? *p : data_type(); - } + // Partial specialization for enums. + template + struct ProgramStatePartialTrait::value>> + : DefaultProgramStatePartialTraitImpl {}; - static void *MakeVoidPtr(data_type d) { - return const_cast(d); - } - }; + // Partial specialization for pointers. + template + struct ProgramStatePartialTrait + : DefaultProgramStatePartialTraitImpl {}; } // namespace ento } // namespace clang diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index 2154a1dedeeeb..3d247e7887d70 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -120,9 +120,8 @@ class SValBuilder { SVal evalIntegralCast(ProgramStateRef state, SVal val, QualType castTy, QualType originalType); - virtual SVal evalMinus(NonLoc val) = 0; - - virtual SVal evalComplement(NonLoc val) = 0; + SVal evalMinus(NonLoc val); + SVal evalComplement(NonLoc val); /// Create a new value which represents a binary expression with two non- /// location operands. diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 7c5f23b6d466a..69f19f7d85655 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -98,19 +98,12 @@ class SVal { /// Convert to the specified SVal type, asserting that this SVal is of /// the desired type. - template - T castAs() const { - assert(T::classof(*this)); - return *static_cast(this); - } + template T castAs() const { return llvm::cast(*this); } /// Convert to the specified SVal type, returning None if this SVal is /// not of the desired type. - template - Optional getAs() const { - if (!T::classof(*this)) - return None; - return *static_cast(this); + template Optional getAs() const { + return llvm::dyn_cast(*this); } unsigned getRawKind() const { return Kind; } @@ -338,11 +331,6 @@ class ConcreteInt : public NonLoc { return *static_cast(Data); } - // Transfer functions for unary operations on ConcreteInts. - ConcreteInt evalComplement(SValBuilder &svalBuilder) const; - - ConcreteInt evalMinus(SValBuilder &svalBuilder) const; - static bool classof(SVal V) { return V.getBaseKind() == NonLocKind && V.getSubKind() == ConcreteIntKind; } @@ -564,4 +552,28 @@ class ConcreteInt : public Loc { } // namespace ento } // namespace clang +namespace llvm { +template +struct CastInfo< + To, From, + std::enable_if_t::value>> + : public CastIsPossible { + using Self = CastInfo< + To, From, + std::enable_if_t::value>>; + static bool isPossible(const From &V) { + return To::classof(*static_cast(&V)); + } + static Optional castFailed() { return Optional{}; } + static To doCast(const From &f) { + return *static_cast(cast<::clang::ento::SVal>(&f)); + } + static Optional doCastIfPossible(const From &f) { + if (!Self::isPossible(f)) + return Self::castFailed(); + return doCast(f); + } +}; +} // namespace llvm + #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index bdf9662d5d997..2ef083aa16467 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -316,8 +316,6 @@ inline StoreRef &StoreRef::operator=(StoreRef const &newStore) { // FIXME: Do we need to pass ProgramStateManager anymore? std::unique_ptr CreateRegionStoreManager(ProgramStateManager &StMgr); -std::unique_ptr -CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr); } // namespace ento diff --git a/clang/include/clang/Support/RISCVVIntrinsicUtils.h b/clang/include/clang/Support/RISCVVIntrinsicUtils.h index 0a7186d42c856..0e9fe97ab735e 100644 --- a/clang/include/clang/Support/RISCVVIntrinsicUtils.h +++ b/clang/include/clang/Support/RISCVVIntrinsicUtils.h @@ -256,7 +256,7 @@ class RVVType { /// have illegal RVVType. static llvm::Optional computeTypes(BasicType BT, int Log2LMUL, unsigned NF, - llvm::ArrayRef PrototypeSeq); + llvm::ArrayRef Prototype); static llvm::Optional computeType(BasicType BT, int Log2LMUL, PrototypeDescriptor Proto); }; @@ -287,7 +287,7 @@ class RVVIntrinsic { private: std::string BuiltinName; // Builtin name std::string Name; // C intrinsic name. - std::string MangledName; + std::string OverloadedName; std::string IRName; bool IsMasked; bool HasVL; @@ -304,20 +304,22 @@ class RVVIntrinsic { unsigned NF = 1; public: - RVVIntrinsic(llvm::StringRef Name, llvm::StringRef Suffix, llvm::StringRef MangledName, - llvm::StringRef MangledSuffix, llvm::StringRef IRName, bool IsMasked, - bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme, - bool HasUnMaskedOverloaded, bool HasBuiltinAlias, - llvm::StringRef ManualCodegen, const RVVTypes &Types, + RVVIntrinsic(llvm::StringRef Name, llvm::StringRef Suffix, + llvm::StringRef OverloadedName, llvm::StringRef OverloadedSuffix, + llvm::StringRef IRName, bool IsMasked, bool HasMaskedOffOperand, + bool HasVL, PolicyScheme Scheme, bool HasUnMaskedOverloaded, + bool HasBuiltinAlias, llvm::StringRef ManualCodegen, + const RVVTypes &Types, const std::vector &IntrinsicTypes, - const std::vector &RequiredFeatures, unsigned NF); + const std::vector &RequiredFeatures, + unsigned NF); ~RVVIntrinsic() = default; RVVTypePtr getOutputType() const { return OutputType; } const RVVTypes &getInputTypes() const { return InputTypes; } llvm::StringRef getBuiltinName() const { return BuiltinName; } llvm::StringRef getName() const { return Name; } - llvm::StringRef getMangledName() const { return MangledName; } + llvm::StringRef getOverloadedName() const { return OverloadedName; } bool hasVL() const { return HasVL; } bool hasPolicy() const { return Scheme != SchemeNone; } bool hasPassthruOperand() const { return Scheme == HasPassthruOperand; } diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h index 363e159dd990f..e0a4d6a554eb2 100644 --- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h +++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h @@ -149,9 +149,9 @@ class ModuleDepCollectorPP final : public PPCallbacks { /// The parent dependency collector. ModuleDepCollector &MDC; /// Working set of direct modular dependencies. - llvm::DenseSet DirectModularDeps; + llvm::SetVector DirectModularDeps; /// Working set of direct modular dependencies that have already been built. - llvm::DenseSet DirectPrebuiltModularDeps; + llvm::SetVector DirectPrebuiltModularDeps; void handleImport(const Module *Imported); @@ -199,7 +199,7 @@ class ModuleDepCollector final : public DependencyCollector { /// textually included header files. std::vector FileDeps; /// Direct and transitive modular dependencies of the main source file. - std::unordered_map ModularDeps; + llvm::MapVector> ModularDeps; /// Options that control the dependency output generation. std::unique_ptr Opts; /// The original Clang invocation passed to dependency scanner. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 1ee18f913b914..eab6c34bb8f1a 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2684,7 +2684,11 @@ getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context) { if (!RD->isUnion()) return structHasUniqueObjectRepresentations(Context, RD); } - if (!Field->getType()->isReferenceType() && + + // A _BitInt type may not be unique if it has padding bits + // but if it is a bitfield the padding bits are not used. + bool IsBitIntType = Field->getType()->isBitIntType(); + if (!Field->getType()->isReferenceType() && !IsBitIntType && !Context.hasUniqueObjectRepresentations(Field->getType())) return llvm::None; @@ -2692,9 +2696,17 @@ getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context) { Context.toBits(Context.getTypeSizeInChars(Field->getType())); if (Field->isBitField()) { int64_t BitfieldSize = Field->getBitWidthValue(Context); - if (BitfieldSize > FieldSizeInBits) + if (IsBitIntType) { + if ((unsigned)BitfieldSize > + cast(Field->getType())->getNumBits()) + return llvm::None; + } else if (BitfieldSize > FieldSizeInBits) { return llvm::None; + } FieldSizeInBits = BitfieldSize; + } else if (IsBitIntType && + !Context.hasUniqueObjectRepresentations(Field->getType())) { + return llvm::None; } return FieldSizeInBits; } @@ -2792,8 +2804,13 @@ bool ASTContext::hasUniqueObjectRepresentations(QualType Ty) const { return false; // All integrals and enums are unique. - if (Ty->isIntegralOrEnumerationType()) + if (Ty->isIntegralOrEnumerationType()) { + // Except _BitInt types that have padding bits. + if (const auto *BIT = dyn_cast(Ty)) + return getTypeSize(BIT) == BIT->getNumBits(); + return true; + } // All other pointers are unique. if (Ty->isPointerType()) @@ -4451,8 +4468,7 @@ QualType ASTContext::getFunctionTypeInternal( QualType, SourceLocation, FunctionType::FunctionTypeExtraBitfields, FunctionType::ExceptionType, Expr *, FunctionDecl *, FunctionProtoType::ExtParameterInfo, Qualifiers>( - NumArgs, EPI.Variadic, - FunctionProtoType::hasExtraBitfields(EPI.ExceptionSpec.Type), + NumArgs, EPI.Variadic, EPI.requiresFunctionProtoTypeExtraBitfields(), ESH.NumExceptionType, ESH.NumExprPtr, ESH.NumFunctionDeclPtr, EPI.ExtParameterInfos ? NumArgs : 0, EPI.TypeQuals.hasNonFastQualifiers() ? 1 : 0); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 9c4f60511fb2f..8d930ead97d3e 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -84,7 +84,7 @@ namespace clang { using ExpectedSLoc = llvm::Expected; using ExpectedName = llvm::Expected; - std::string ImportError::toString() const { + std::string ASTImportError::toString() const { // FIXME: Improve error texts. switch (Error) { case NameConflict: @@ -98,15 +98,13 @@ namespace clang { return "Invalid error code."; } - void ImportError::log(raw_ostream &OS) const { - OS << toString(); - } + void ASTImportError::log(raw_ostream &OS) const { OS << toString(); } - std::error_code ImportError::convertToErrorCode() const { + std::error_code ASTImportError::convertToErrorCode() const { llvm_unreachable("Function not implemented."); } - char ImportError::ID; + char ASTImportError::ID; template SmallVector @@ -548,6 +546,7 @@ namespace clang { ExpectedDecl VisitUsingDecl(UsingDecl *D); ExpectedDecl VisitUsingShadowDecl(UsingShadowDecl *D); ExpectedDecl VisitUsingDirectiveDecl(UsingDirectiveDecl *D); + ExpectedDecl VisitUsingPackDecl(UsingPackDecl *D); ExpectedDecl ImportUsingShadowDecls(BaseUsingDecl *D, BaseUsingDecl *ToSI); ExpectedDecl VisitUsingEnumDecl(UsingEnumDecl *D); ExpectedDecl VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); @@ -1066,7 +1065,7 @@ using namespace clang; ExpectedType ASTNodeImporter::VisitType(const Type *T) { Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node) << T->getTypeClassName(); - return make_error(ImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct); } ExpectedType ASTNodeImporter::VisitAtomicType(const AtomicType *T){ @@ -1717,7 +1716,7 @@ Error ASTNodeImporter::ImportDeclParts( if (RT && RT->getDecl() == D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return make_error(ImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct); } } } @@ -2240,13 +2239,13 @@ bool ASTNodeImporter::IsStructuralMatch(Decl *From, Decl *To, bool Complain) { ExpectedDecl ASTNodeImporter::VisitDecl(Decl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return make_error(ImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct); } ExpectedDecl ASTNodeImporter::VisitImportDecl(ImportDecl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return make_error(ImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct); } ExpectedDecl ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { @@ -3226,23 +3225,32 @@ static bool isAncestorDeclContextOf(const DeclContext *DC, const Decl *D) { return false; } +static bool hasTypeDeclaredInsideFunction(QualType T, const FunctionDecl *FD) { + if (T.isNull()) + return false; + if (const auto *RecordT = T->getAs()) { + const RecordDecl *RD = RecordT->getDecl(); + assert(RD); + if (isAncestorDeclContextOf(FD, RD)) { + assert(RD->getLexicalDeclContext() == RD->getDeclContext()); + return true; + } + if (const auto *RDTempl = dyn_cast(RD)) + return llvm::count_if(RDTempl->getTemplateArgs().asArray(), + [FD](const TemplateArgument &Arg) { + return hasTypeDeclaredInsideFunction( + Arg.getAsType(), FD); + }); + } + return false; +} + bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) { QualType FromTy = D->getType(); const auto *FromFPT = FromTy->getAs(); assert(FromFPT && "Must be called on FunctionProtoType"); - if (const AutoType *AutoT = - FromFPT->getReturnType()->getContainedAutoType()) { - QualType DeducedT = AutoT->getDeducedType(); - if (const auto *RecordT = - !DeducedT.isNull() ? DeducedT->getAs() : nullptr) { - const RecordDecl *RD = RecordT->getDecl(); - assert(RD); - if (isAncestorDeclContextOf(D, RD)) { - assert(RD->getLexicalDeclContext() == RD->getDeclContext()); - return true; - } - } - } + if (const AutoType *AutoT = FromFPT->getReturnType()->getContainedAutoType()) + return hasTypeDeclaredInsideFunction(AutoT->getDeducedType(), D); if (const auto *TypedefT = FromFPT->getReturnType()->getAs()) { const TypedefNameDecl *TD = TypedefT->getDecl(); assert(TD); @@ -3705,7 +3713,7 @@ ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); - return make_error(ImportError::NameConflict); + return make_error(ASTImportError::NameConflict); } } @@ -3778,7 +3786,7 @@ ExpectedDecl ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); - return make_error(ImportError::NameConflict); + return make_error(ASTImportError::NameConflict); } } @@ -3969,7 +3977,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here) << FoundIvar->getType(); - return make_error(ImportError::NameConflict); + return make_error(ASTImportError::NameConflict); } } @@ -4277,7 +4285,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return make_error(ImportError::NameConflict); + return make_error(ASTImportError::NameConflict); } // Check the number of parameters. @@ -4289,7 +4297,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return make_error(ImportError::NameConflict); + return make_error(ASTImportError::NameConflict); } // Check parameter types. @@ -4305,7 +4313,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here) << (*FoundP)->getType(); - return make_error(ImportError::NameConflict); + return make_error(ASTImportError::NameConflict); } } @@ -4318,7 +4326,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return make_error(ImportError::NameConflict); + return make_error(ASTImportError::NameConflict); } // FIXME: Any other bits we need to merge? @@ -4832,6 +4840,35 @@ ExpectedDecl ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { return ToUsingDir; } +ExpectedDecl ASTNodeImporter::VisitUsingPackDecl(UsingPackDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); + if (ToD) + return ToD; + + auto ToInstantiatedFromUsingOrErr = + Importer.Import(D->getInstantiatedFromUsingDecl()); + if (!ToInstantiatedFromUsingOrErr) + return ToInstantiatedFromUsingOrErr.takeError(); + SmallVector Expansions(D->expansions().size()); + if (Error Err = ImportArrayChecked(D->expansions(), Expansions.begin())) + return std::move(Err); + + UsingPackDecl *ToUsingPack; + if (GetImportedOrCreateDecl(ToUsingPack, D, Importer.getToContext(), DC, + cast(*ToInstantiatedFromUsingOrErr), + Expansions)) + return ToUsingPack; + + addDeclToContexts(D, ToUsingPack); + + return ToUsingPack; +} + ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingValueDecl( UnresolvedUsingValueDecl *D) { DeclContext *DC, *LexicalDC; @@ -5216,7 +5253,7 @@ ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { Importer.FromDiag(D->getLocation(), diag::note_odr_objc_missing_superclass); - return make_error(ImportError::NameConflict); + return make_error(ASTImportError::NameConflict); } } @@ -5255,7 +5292,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here) << FoundProp->getType(); - return make_error(ImportError::NameConflict); + return make_error(ASTImportError::NameConflict); } // FIXME: Check property attributes, getters, setters, etc.? @@ -5360,7 +5397,7 @@ ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { << D->getPropertyDecl()->getDeclName() << (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic); - return make_error(ImportError::NameConflict); + return make_error(ASTImportError::NameConflict); } // For @synthesize, check that we have the same @@ -5375,7 +5412,7 @@ ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { diag::note_odr_objc_synthesize_ivar_here) << D->getPropertyIvarDecl()->getDeclName(); - return make_error(ImportError::NameConflict); + return make_error(ASTImportError::NameConflict); } // Merge the existing implementation with the new implementation. @@ -5705,7 +5742,7 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( } } else { // ODR violation. // FIXME HandleNameConflict - return make_error(ImportError::NameConflict); + return make_error(ASTImportError::NameConflict); } } @@ -5988,9 +6025,10 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( return TInfoOrErr.takeError(); TemplateArgumentListInfo ToTAInfo; - if (Error Err = ImportTemplateArgumentListInfo( - D->getTemplateArgsInfo(), ToTAInfo)) - return std::move(Err); + if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo()) { + if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo)) + return std::move(Err); + } using PartVarSpecDecl = VarTemplatePartialSpecializationDecl; // Create a new specialization. @@ -6182,13 +6220,13 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { ExpectedStmt ASTNodeImporter::VisitStmt(Stmt *S) { Importer.FromDiag(S->getBeginLoc(), diag::err_unsupported_ast_node) << S->getStmtClassName(); - return make_error(ImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct); } ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { if (Importer.returnWithErrorInTest()) - return make_error(ImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct); SmallVector Names; for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { IdentifierInfo *ToII = Importer.Import(S->getOutputIdentifier(I)); @@ -6695,7 +6733,7 @@ ExpectedStmt ASTNodeImporter::VisitObjCAutoreleasePoolStmt( ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) { Importer.FromDiag(E->getBeginLoc(), diag::err_unsupported_ast_node) << E->getStmtClassName(); - return make_error(ImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct); } ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) { @@ -7357,7 +7395,7 @@ ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { } default: llvm_unreachable("Cast expression of unsupported type!"); - return make_error(ImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct); } } @@ -8218,7 +8256,7 @@ ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { ToOperatorLoc, ToRParenLoc, ToAngleBrackets); } else { llvm_unreachable("Unknown cast type"); - return make_error(); + return make_error(); } } @@ -8413,7 +8451,7 @@ ASTImporter::Import(ExprWithCleanups::CleanupObject From) { // FIXME: Handle BlockDecl when we implement importing BlockExpr in // ASTNodeImporter. - return make_error(ImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct); } ExpectedTypePtr ASTImporter::Import(const Type *FromT) { @@ -8764,7 +8802,7 @@ Expected ASTImporter::Import(Decl *FromD) { // Check whether there was a previous failed import. // If yes return the existing error. if (auto Error = getImportDeclErrorIfAny(FromD)) - return make_error(*Error); + return make_error(*Error); // Check whether we've already imported this declaration. Decl *ToD = GetAlreadyImportedOrNull(FromD); @@ -8772,7 +8810,7 @@ Expected ASTImporter::Import(Decl *FromD) { // Already imported (possibly from another TU) and with an error. if (auto Error = SharedState->getImportDeclErrorIfAny(ToD)) { setImportDeclError(FromD, *Error); - return make_error(*Error); + return make_error(*Error); } // If FromD has some updated flags after last import, apply it. @@ -8824,9 +8862,9 @@ Expected ASTImporter::Import(Decl *FromD) { // Error encountered for the first time. // After takeError the error is not usable any more in ToDOrErr. // Get a copy of the error object (any more simple solution for this?). - ImportError ErrOut; + ASTImportError ErrOut; handleAllErrors(ToDOrErr.takeError(), - [&ErrOut](const ImportError &E) { ErrOut = E; }); + [&ErrOut](const ASTImportError &E) { ErrOut = E; }); setImportDeclError(FromD, ErrOut); // Set the error for the mapped to Decl, which is in the "to" context. if (Pos != ImportedDecls.end()) @@ -8861,7 +8899,7 @@ Expected ASTImporter::Import(Decl *FromD) { SavedImportPaths.erase(FromD); // Do not return ToDOrErr, error was taken out of it. - return make_error(ErrOut); + return make_error(ErrOut); } ToD = *ToDOrErr; @@ -8873,7 +8911,7 @@ Expected ASTImporter::Import(Decl *FromD) { if (!ToD) { auto Err = getImportDeclErrorIfAny(FromD); assert(Err); - return make_error(*Err); + return make_error(*Err); } // We could import from the current TU without error. But previously we @@ -8881,7 +8919,7 @@ Expected ASTImporter::Import(Decl *FromD) { // ASTImporter object) and with an error. if (auto Error = SharedState->getImportDeclErrorIfAny(ToD)) { setImportDeclError(FromD, *Error); - return make_error(*Error); + return make_error(*Error); } // Make sure that ImportImpl registered the imported decl. @@ -9346,7 +9384,7 @@ Expected ASTImporter::Import(FileID FromID, bool IsBuiltin) { Cache->getBufferOrNone(FromContext.getDiagnostics(), FromSM.getFileManager(), SourceLocation{}); if (!FromBuf) - return llvm::make_error(ImportError::Unknown); + return llvm::make_error(ASTImportError::Unknown); std::unique_ptr ToBuf = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), @@ -9422,7 +9460,7 @@ Expected ASTImporter::Import(CXXCtorInitializer *From) { *ToExprOrErr, *RParenLocOrErr); } else { // FIXME: assert? - return make_error(); + return make_error(); } } @@ -9751,7 +9789,7 @@ Expected ASTImporter::HandleNameConflict(DeclarationName Name, unsigned NumDecls) { if (ODRHandling == ODRHandlingType::Conservative) // Report error at any name conflict. - return make_error(ImportError::NameConflict); + return make_error(ASTImportError::NameConflict); else // Allow to create the new Decl with the same name. return Name; @@ -9811,16 +9849,16 @@ Decl *ASTImporter::MapImported(Decl *From, Decl *To) { return To; } -llvm::Optional +llvm::Optional ASTImporter::getImportDeclErrorIfAny(Decl *FromD) const { auto Pos = ImportDeclErrors.find(FromD); if (Pos != ImportDeclErrors.end()) return Pos->second; else - return Optional(); + return Optional(); } -void ASTImporter::setImportDeclError(Decl *From, ImportError Error) { +void ASTImporter::setImportDeclError(Decl *From, ASTImportError Error) { auto InsertRes = ImportDeclErrors.insert({From, Error}); (void)InsertRes; // Either we set the error for the first time, or we already had set one and diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 1c5c64d1b3650..bd48a4ab93d1f 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2867,7 +2867,8 @@ Expr *ParmVarDecl::getDefaultArg() { Expr *Arg = getInit(); if (auto *E = dyn_cast_or_null(Arg)) - return E->getSubExpr(); + if (!isa(E)) + return E->getSubExpr(); return Arg; } diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 3b4ed3107e5a8..e7e5f355809b0 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -1335,10 +1335,14 @@ VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const { void VarTemplateSpecializationDecl::setTemplateArgsInfo( const TemplateArgumentListInfo &ArgsInfo) { - TemplateArgsInfo.setLAngleLoc(ArgsInfo.getLAngleLoc()); - TemplateArgsInfo.setRAngleLoc(ArgsInfo.getRAngleLoc()); - for (const TemplateArgumentLoc &Loc : ArgsInfo.arguments()) - TemplateArgsInfo.addArgument(Loc); + TemplateArgsInfo = + ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo); +} + +void VarTemplateSpecializationDecl::setTemplateArgsInfo( + const ASTTemplateArgumentListInfo *ArgsInfo) { + TemplateArgsInfo = + ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index c3dfae5cba061..79d092acccec9 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1522,6 +1522,11 @@ const Attr *CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const { if (const auto *A = TD->getAttr()) return A; + for (const auto *TD = getCallReturnType(Ctx)->getAs(); TD; + TD = TD->desugar()->getAs()) + if (const auto *A = TD->getDecl()->getAttr()) + return A; + // Otherwise, see if the callee is marked nodiscard and return that attribute // instead. const Decl *D = getCalleeDecl(); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index f679dba44f001..65782fbb1eaea 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2552,18 +2552,15 @@ static bool HandleFloatToIntCast(EvalInfo &Info, const Expr *E, return true; } -/// Get rounding mode used for evaluation of the specified expression. -/// \param[out] DynamicRM Is set to true is the requested rounding mode is -/// dynamic. +/// Get rounding mode to use in evaluation of the specified expression. +/// /// If rounding mode is unknown at compile time, still try to evaluate the /// expression. If the result is exact, it does not depend on rounding mode. /// So return "tonearest" mode instead of "dynamic". -static llvm::RoundingMode getActiveRoundingMode(EvalInfo &Info, const Expr *E, - bool &DynamicRM) { +static llvm::RoundingMode getActiveRoundingMode(EvalInfo &Info, const Expr *E) { llvm::RoundingMode RM = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts()).getRoundingMode(); - DynamicRM = (RM == llvm::RoundingMode::Dynamic); - if (DynamicRM) + if (RM == llvm::RoundingMode::Dynamic) RM = llvm::RoundingMode::NearestTiesToEven; return RM; } @@ -2613,8 +2610,7 @@ static bool HandleFloatToFloatCast(EvalInfo &Info, const Expr *E, QualType SrcType, QualType DestType, APFloat &Result) { assert(isa(E) || isa(E)); - bool DynamicRM; - llvm::RoundingMode RM = getActiveRoundingMode(Info, E, DynamicRM); + llvm::RoundingMode RM = getActiveRoundingMode(Info, E); APFloat::opStatus St; APFloat Value = Result; bool ignored; @@ -2849,8 +2845,7 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS, static bool handleFloatFloatBinOp(EvalInfo &Info, const BinaryOperator *E, APFloat &LHS, BinaryOperatorKind Opcode, const APFloat &RHS) { - bool DynamicRM; - llvm::RoundingMode RM = getActiveRoundingMode(Info, E, DynamicRM); + llvm::RoundingMode RM = getActiveRoundingMode(Info, E); APFloat::opStatus St; switch (Opcode) { default: @@ -6560,7 +6555,7 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc, // We don't have a good way to iterate fields in reverse, so collect all the // fields first and then walk them backwards. - SmallVector Fields(RD->field_begin(), RD->field_end()); + SmallVector Fields(RD->fields()); for (const FieldDecl *FD : llvm::reverse(Fields)) { if (FD->isUnnamedBitfield()) continue; @@ -13880,10 +13875,12 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_huge_val: case Builtin::BI__builtin_huge_valf: case Builtin::BI__builtin_huge_vall: + case Builtin::BI__builtin_huge_valf16: case Builtin::BI__builtin_huge_valf128: case Builtin::BI__builtin_inf: case Builtin::BI__builtin_inff: case Builtin::BI__builtin_infl: + case Builtin::BI__builtin_inff16: case Builtin::BI__builtin_inff128: { const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(E->getType()); @@ -13894,6 +13891,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_nans: case Builtin::BI__builtin_nansf: case Builtin::BI__builtin_nansl: + case Builtin::BI__builtin_nansf16: case Builtin::BI__builtin_nansf128: if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), true, Result)) @@ -13903,6 +13901,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_nan: case Builtin::BI__builtin_nanf: case Builtin::BI__builtin_nanl: + case Builtin::BI__builtin_nanf16: case Builtin::BI__builtin_nanf128: // If this is __builtin_nan() turn this into a nan, otherwise we // can't constant fold it. diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp index 102bcca96a389..4977aaa513195 100644 --- a/clang/lib/AST/FormatString.cpp +++ b/clang/lib/AST/FormatString.cpp @@ -760,7 +760,7 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target, return true; case ConversionSpecifier::FreeBSDrArg: case ConversionSpecifier::FreeBSDyArg: - return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4(); + return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS(); default: return false; } @@ -795,7 +795,7 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target, return true; case ConversionSpecifier::FreeBSDrArg: case ConversionSpecifier::FreeBSDyArg: - return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4(); + return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS(); default: return false; } diff --git a/clang/lib/AST/Interp/Function.cpp b/clang/lib/AST/Interp/Function.cpp index 0ed13a92aa38d..6ba97df1cd30e 100644 --- a/clang/lib/AST/Interp/Function.cpp +++ b/clang/lib/AST/Interp/Function.cpp @@ -34,8 +34,7 @@ Function::ParamDescriptor Function::getParamDescriptor(unsigned Offset) const { SourceInfo Function::getSource(CodePtr PC) const { unsigned Offset = PC - getCodeBegin(); using Elem = std::pair; - auto It = std::lower_bound(SrcMap.begin(), SrcMap.end(), Elem{Offset, {}}, - [](Elem A, Elem B) { return A.first < B.first; }); + auto It = llvm::lower_bound(SrcMap, Elem{Offset, {}}, llvm::less_first()); if (It == SrcMap.end() || It->first != Offset) llvm::report_fatal_error("missing source location"); return It->second; diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index a9416397c90d6..91f41778ee68f 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -5646,8 +5646,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, assert(RD && "unexpected type for record value"); // Drop trailing zero-initialized elements. - llvm::SmallVector Fields(RD->field_begin(), - RD->field_end()); + llvm::SmallVector Fields(RD->fields()); while ( !Fields.empty() && (Fields.back()->isUnnamedBitfield() || diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp index 984da9909ce23..c1a345390091b 100644 --- a/clang/lib/AST/Mangle.cpp +++ b/clang/lib/AST/Mangle.cpp @@ -70,9 +70,7 @@ static CCMangling getCallingConvMangling(const ASTContext &Context, // On wasm, the argc/argv form of "main" is renamed so that the startup code // can call it with the correct function signature. - // On Emscripten, users may be exporting "main" and expecting to call it - // themselves, so we can't mangle it. - if (Triple.isWasm() && !Triple.isOSEmscripten()) + if (Triple.isWasm()) if (const FunctionDecl *FD = dyn_cast(ND)) if (FD->isMain() && FD->hasPrototype() && FD->param_size() == 2) return CCM_WasmMainArgcArgv; diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 8827e956fc2f4..6f3ede2ce42a7 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1223,7 +1223,7 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { // Per GCC's documentation, it only applies to non-static data members. return (Packed && ((Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver6) || - Context.getTargetInfo().getTriple().isPS4() || + Context.getTargetInfo().getTriple().isPS() || Context.getTargetInfo().getTriple().isOSAIX())) ? CharUnits::One() : UnpackedAlign; @@ -1261,7 +1261,9 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { (!HasExternalLayout || Offset == CharUnits::Zero()) && EmptySubobjects->CanPlaceBaseAtOffset(Base, CharUnits::Zero())) { setSize(std::max(getSize(), Layout.getSize())); - UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign); + // On PS4/PS5, don't update the alignment, to preserve compatibility. + if (!Context.getTargetInfo().getTriple().isPS()) + UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign); return CharUnits::Zero(); } @@ -1891,7 +1893,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD() || Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver14 || - Target.isPS4() || Target.isOSDarwin())) || + Target.isPS() || Target.isOSDarwin())) || D->hasAttr(); AlignRequirementKind AlignRequirement = AlignRequirementKind::None; diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp index 3535b0620ee50..74d1020e15b66 100644 --- a/clang/lib/AST/StmtOpenMP.cpp +++ b/clang/lib/AST/StmtOpenMP.cpp @@ -868,15 +868,17 @@ OMPAtomicDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef Clauses, Stmt *AssociatedStmt, Expressions Exprs) { auto *Dir = createDirective( - C, Clauses, AssociatedStmt, /*NumChildren=*/6, StartLoc, EndLoc); + C, Clauses, AssociatedStmt, /*NumChildren=*/7, StartLoc, EndLoc); Dir->setX(Exprs.X); Dir->setV(Exprs.V); + Dir->setR(Exprs.R); Dir->setExpr(Exprs.E); Dir->setUpdateExpr(Exprs.UE); Dir->setD(Exprs.D); Dir->setCond(Exprs.Cond); Dir->Flags.IsXLHSInRHSPart = Exprs.IsXLHSInRHSPart ? 1 : 0; Dir->Flags.IsPostfixUpdate = Exprs.IsPostfixUpdate ? 1 : 0; + Dir->Flags.IsFailOnly = Exprs.IsFailOnly ? 1 : 0; return Dir; } @@ -884,7 +886,7 @@ OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { return createEmptyDirective( - C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/6); + C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/7); } OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C, diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index 229a8db21ab63..e0f5916a9a0b7 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -617,6 +617,17 @@ ASTTemplateArgumentListInfo::Create(const ASTContext &C, return new (Mem) ASTTemplateArgumentListInfo(List); } +const ASTTemplateArgumentListInfo * +ASTTemplateArgumentListInfo::Create(const ASTContext &C, + const ASTTemplateArgumentListInfo *List) { + if (!List) + return nullptr; + std::size_t size = + totalSizeToAlloc(List->getNumTemplateArgs()); + void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo)); + return new (Mem) ASTTemplateArgumentListInfo(List); +} + ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo( const TemplateArgumentListInfo &Info) { LAngleLoc = Info.getLAngleLoc(); @@ -628,6 +639,17 @@ ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo( new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); } +ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo( + const ASTTemplateArgumentListInfo *Info) { + LAngleLoc = Info->getLAngleLoc(); + RAngleLoc = Info->getRAngleLoc(); + NumTemplateArgs = Info->getNumTemplateArgs(); + + TemplateArgumentLoc *ArgBuffer = getTrailingObjects(); + for (unsigned i = 0; i != NumTemplateArgs; ++i) + new (&ArgBuffer[i]) TemplateArgumentLoc((*Info)[i]); +} + void ASTTemplateKWAndArgsInfo::initializeFrom( SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info, TemplateArgumentLoc *OutArgArray) { diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index ece4165c51f53..0f168a518707e 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3213,12 +3213,15 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef params, FunctionTypeBits.Variadic = epi.Variadic; FunctionTypeBits.HasTrailingReturn = epi.HasTrailingReturn; - // Fill in the extra trailing bitfields if present. - if (hasExtraBitfields(epi.ExceptionSpec.Type)) { + if (epi.requiresFunctionProtoTypeExtraBitfields()) { + FunctionTypeBits.HasExtraBitfields = true; auto &ExtraBits = *getTrailingObjects(); - ExtraBits.NumExceptionType = epi.ExceptionSpec.Exceptions.size(); + ExtraBits = FunctionTypeExtraBitfields(); + } else { + FunctionTypeBits.HasExtraBitfields = false; } + // Fill in the trailing argument array. auto *argSlot = getTrailingObjects(); for (unsigned i = 0; i != getNumParams(); ++i) { @@ -3229,6 +3232,9 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef params, // Fill in the exception type array if present. if (getExceptionSpecType() == EST_Dynamic) { + auto &ExtraBits = *getTrailingObjects(); + ExtraBits.NumExceptionType = epi.ExceptionSpec.Exceptions.size(); + assert(hasExtraBitfields() && "missing trailing extra bitfields!"); auto *exnSlot = reinterpret_cast(getTrailingObjects()); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index b5286de5b1cab..6b13d38060370 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -80,6 +80,21 @@ namespace { } }; + class DefaultTemplateArgsPolicyRAII { + PrintingPolicy &Policy; + bool Old; + + public: + explicit DefaultTemplateArgsPolicyRAII(PrintingPolicy &Policy) + : Policy(Policy), Old(Policy.SuppressDefaultTemplateArgs) { + Policy.SuppressDefaultTemplateArgs = false; + } + + ~DefaultTemplateArgsPolicyRAII() { + Policy.SuppressDefaultTemplateArgs = Old; + } + }; + class ElaboratedTypePolicyRAII { PrintingPolicy &Policy; bool SuppressTagKeyword; @@ -1470,6 +1485,7 @@ void TypePrinter::printTemplateId(const TemplateSpecializationType *T, IncludeStrongLifetimeRAII Strong(Policy); TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl(); + // FIXME: Null TD never excercised in test suite. if (FullyQualify && TD) { if (!Policy.SuppressScope) AppendScope(TD->getDeclContext(), OS, TD->getDeclName()); @@ -1479,7 +1495,9 @@ void TypePrinter::printTemplateId(const TemplateSpecializationType *T, T->getTemplateName().print(OS, Policy); } - printTemplateArgumentList(OS, T->template_arguments(), Policy); + DefaultTemplateArgsPolicyRAII TemplateArgs(Policy); + const TemplateParameterList *TPL = TD ? TD->getTemplateParameters() : nullptr; + printTemplateArgumentList(OS, T->template_arguments(), Policy, TPL); spaceBeforePlaceHolder(OS); } @@ -1688,6 +1706,15 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, if (T->getAttrKind() == attr::AddressSpace) return; + if (T->getAttrKind() == attr::AnnotateType) { + // FIXME: Print the attribute arguments once we have a way to retrieve these + // here. For the meantime, we just print `[[clang::annotate_type(...)]]` + // without the arguments so that we know at least that we had _some_ + // annotation on the type. + OS << " [[clang::annotate_type(...)]]"; + return; + } + OS << " __attribute__(("; switch (T->getAttrKind()) { #define TYPE_ATTR(NAME) @@ -1725,6 +1752,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case attr::UPtr: case attr::AddressSpace: case attr::CmseNSCall: + case attr::AnnotateType: llvm_unreachable("This attribute should have been handled already"); case attr::NSReturnsRetained: diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 1417b95aad931..8379e108fa27b 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -597,6 +597,8 @@ class CFGBuilder { CFGBlock *VisitObjCMessageExpr(ObjCMessageExpr *E, AddStmtChoice asc); CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E); CFGBlock *VisitReturnStmt(Stmt *S); + CFGBlock *VisitCoroutineSuspendExpr(CoroutineSuspendExpr *S, + AddStmtChoice asc); CFGBlock *VisitSEHExceptStmt(SEHExceptStmt *S); CFGBlock *VisitSEHFinallyStmt(SEHFinallyStmt *S); CFGBlock *VisitSEHLeaveStmt(SEHLeaveStmt *S); @@ -2297,6 +2299,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc, case Stmt::CoreturnStmtClass: return VisitReturnStmt(S); + case Stmt::CoyieldExprClass: + case Stmt::CoawaitExprClass: + return VisitCoroutineSuspendExpr(cast(S), asc); + case Stmt::SEHExceptStmtClass: return VisitSEHExceptStmt(cast(S)); @@ -3152,6 +3158,27 @@ CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) { return B; } +CFGBlock *CFGBuilder::VisitCoroutineSuspendExpr(CoroutineSuspendExpr *E, + AddStmtChoice asc) { + // We're modelling the pre-coro-xform CFG. Thus just evalate the various + // active components of the co_await or co_yield. Note we do not model the + // edge from the builtin_suspend to the exit node. + if (asc.alwaysAdd(*this, E)) { + autoCreateBlock(); + appendStmt(Block, E); + } + CFGBlock *B = Block; + if (auto *R = Visit(E->getResumeExpr())) + B = R; + if (auto *R = Visit(E->getSuspendExpr())) + B = R; + if (auto *R = Visit(E->getReadyExpr())) + B = R; + if (auto *R = Visit(E->getCommonExpr())) + B = R; + return B; +} + CFGBlock *CFGBuilder::VisitSEHExceptStmt(SEHExceptStmt *ES) { // SEHExceptStmt are treated like labels, so they are the first statement in a // block. diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 13fef0d4286cf..370b420b80755 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -50,22 +50,25 @@ llvm::DenseMap intersectDenseMaps(const llvm::DenseMap &Map1, return Result; } +static bool areEquivalentIndirectionValues(Value *Val1, Value *Val2) { + if (auto *IndVal1 = dyn_cast(Val1)) { + auto *IndVal2 = cast(Val2); + return &IndVal1->getReferentLoc() == &IndVal2->getReferentLoc(); + } + if (auto *IndVal1 = dyn_cast(Val1)) { + auto *IndVal2 = cast(Val2); + return &IndVal1->getPointeeLoc() == &IndVal2->getPointeeLoc(); + } + return false; +} + /// Returns true if and only if `Val1` is equivalent to `Val2`. static bool equivalentValues(QualType Type, Value *Val1, const Environment &Env1, Value *Val2, const Environment &Env2, Environment::ValueModel &Model) { - if (Val1 == Val2) - return true; - - if (auto *IndVal1 = dyn_cast(Val1)) { - auto *IndVal2 = cast(Val2); - assert(IndVal1->getKind() == IndVal2->getKind()); - if (&IndVal1->getPointeeLoc() == &IndVal2->getPointeeLoc()) - return true; - } - - return Model.compareEquivalent(Type, *Val1, Env1, *Val2, Env2); + return Val1 == Val2 || areEquivalentIndirectionValues(Val1, Val2) || + Model.compareEquivalent(Type, *Val1, Env1, *Val2, Env2); } /// Attempts to merge distinct values `Val1` and `Val2` in `Env1` and `Env2`, @@ -89,12 +92,8 @@ static Value *mergeDistinctValues(QualType Type, Value *Val1, } // FIXME: add unit tests that cover this statement. - if (auto *IndVal1 = dyn_cast(Val1)) { - auto *IndVal2 = cast(Val2); - assert(IndVal1->getKind() == IndVal2->getKind()); - if (&IndVal1->getPointeeLoc() == &IndVal2->getPointeeLoc()) { - return Val1; - } + if (areEquivalentIndirectionValues(Val1, Val2)) { + return Val1; } // FIXME: Consider destroying `MergedValue` immediately if `ValueModel::merge` @@ -523,7 +522,7 @@ StorageLocation &Environment::skip(StorageLocation &Loc, SkipPast SP) const { // References cannot be chained so we only need to skip past one level of // indirection. if (auto *Val = dyn_cast_or_null(getValue(Loc))) - return Val->getPointeeLoc(); + return Val->getReferentLoc(); return Loc; case SkipPast::ReferenceThenPointer: StorageLocation &LocPastRef = skip(Loc, SkipPast::Reference); diff --git a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp index c797e02cec990..502974186621b 100644 --- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp +++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp @@ -43,7 +43,13 @@ DeclarationMatcher optionalClass() { hasTemplateArgument(0, refersToType(type().bind("T")))); } -auto hasOptionalType() { return hasType(optionalClass()); } +auto optionalOrAliasType() { + return hasUnqualifiedDesugaredType( + recordType(hasDeclaration(optionalClass()))); +} + +/// Matches any of the spellings of the optional types and sugar, aliases, etc. +auto hasOptionalType() { return hasType(optionalOrAliasType()); } auto isOptionalMemberCallWithName( llvm::StringRef MemberName, @@ -158,19 +164,36 @@ auto isValueOrNotEqX() { ComparesToSame(integerLiteral(equals(0))))); } +auto isCallReturningOptional() { + return callExpr(hasType(qualType(anyOf( + optionalOrAliasType(), referenceType(pointee(optionalOrAliasType())))))); +} + +/// Sets `HasValueVal` as the symbolic value that represents the "has_value" +/// property of the optional value `OptionalVal`. +void setHasValue(Value &OptionalVal, BoolValue &HasValueVal) { + OptionalVal.setProperty("has_value", HasValueVal); +} + /// Creates a symbolic value for an `optional` value using `HasValueVal` as the /// symbolic value of its "has_value" property. StructValue &createOptionalValue(Environment &Env, BoolValue &HasValueVal) { auto OptionalVal = std::make_unique(); - OptionalVal->setProperty("has_value", HasValueVal); + setHasValue(*OptionalVal, HasValueVal); return Env.takeOwnership(std::move(OptionalVal)); } /// Returns the symbolic value that represents the "has_value" property of the -/// optional value `Val`. Returns null if `Val` is null. -BoolValue *getHasValue(Value *Val) { - if (auto *OptionalVal = cast_or_null(Val)) { - return cast(OptionalVal->getProperty("has_value")); +/// optional value `OptionalVal`. Returns null if `OptionalVal` is null. +BoolValue *getHasValue(Environment &Env, Value *OptionalVal) { + if (OptionalVal != nullptr) { + auto *HasValueVal = + cast_or_null(OptionalVal->getProperty("has_value")); + if (HasValueVal == nullptr) { + HasValueVal = &Env.makeAtomicBoolValue(); + OptionalVal->setProperty("has_value", *HasValueVal); + } + return HasValueVal; } return nullptr; } @@ -207,26 +230,92 @@ int countOptionalWrappers(const ASTContext &ASTCtx, QualType Type) { .getDesugaredType(ASTCtx)); } +/// Tries to initialize the `optional`'s value (that is, contents), and return +/// its location. Returns nullptr if the value can't be represented. +StorageLocation *maybeInitializeOptionalValueMember(QualType Q, + Value &OptionalVal, + Environment &Env) { + // The "value" property represents a synthetic field. As such, it needs + // `StorageLocation`, like normal fields (and other variables). So, we model + // it with a `ReferenceValue`, since that includes a storage location. Once + // the property is set, it will be shared by all environments that access the + // `Value` representing the optional (here, `OptionalVal`). + if (auto *ValueProp = OptionalVal.getProperty("value")) { + auto *ValueRef = clang::cast(ValueProp); + auto &ValueLoc = ValueRef->getReferentLoc(); + if (Env.getValue(ValueLoc) == nullptr) { + // The property was previously set, but the value has been lost. This can + // happen, for example, because of an environment merge (where the two + // environments mapped the property to different values, which resulted in + // them both being discarded), or when two blocks in the CFG, with neither + // a dominator of the other, visit the same optional value, or even when a + // block is revisited during testing to collect per-statement state. + // FIXME: This situation means that the optional contents are not shared + // between branches and the like. Practically, this lack of sharing + // reduces the precision of the model when the contents are relevant to + // the check, like another optional or a boolean that influences control + // flow. + auto *ValueVal = Env.createValue(ValueLoc.getType()); + if (ValueVal == nullptr) + return nullptr; + Env.setValue(ValueLoc, *ValueVal); + } + return &ValueLoc; + } + + auto Ty = stripReference(Q); + auto *ValueVal = Env.createValue(Ty); + if (ValueVal == nullptr) + return nullptr; + auto &ValueLoc = Env.createStorageLocation(Ty); + Env.setValue(ValueLoc, *ValueVal); + auto ValueRef = std::make_unique(ValueLoc); + OptionalVal.setProperty("value", Env.takeOwnership(std::move(ValueRef))); + return &ValueLoc; +} + void initializeOptionalReference(const Expr *OptionalExpr, const MatchFinder::MatchResult &, LatticeTransferState &State) { - if (auto *OptionalVal = cast_or_null( - State.Env.getValue(*OptionalExpr, SkipPast::Reference))) { + if (auto *OptionalVal = + State.Env.getValue(*OptionalExpr, SkipPast::Reference)) { if (OptionalVal->getProperty("has_value") == nullptr) { - OptionalVal->setProperty("has_value", State.Env.makeAtomicBoolValue()); + setHasValue(*OptionalVal, State.Env.makeAtomicBoolValue()); } } } +/// Returns true if and only if `OptionalVal` is initialized and known to be +/// empty in `Env. +bool isEmptyOptional(const Value &OptionalVal, const Environment &Env) { + auto *HasValueVal = + cast_or_null(OptionalVal.getProperty("has_value")); + return HasValueVal != nullptr && + Env.flowConditionImplies(Env.makeNot(*HasValueVal)); +} + +/// Returns true if and only if `OptionalVal` is initialized and known to be +/// non-empty in `Env. +bool isNonEmptyOptional(const Value &OptionalVal, const Environment &Env) { + auto *HasValueVal = + cast_or_null(OptionalVal.getProperty("has_value")); + return HasValueVal != nullptr && Env.flowConditionImplies(*HasValueVal); +} + void transferUnwrapCall(const Expr *UnwrapExpr, const Expr *ObjectExpr, LatticeTransferState &State) { - if (auto *OptionalVal = cast_or_null( - State.Env.getValue(*ObjectExpr, SkipPast::ReferenceThenPointer))) { - auto *HasValueVal = getHasValue(OptionalVal); - assert(HasValueVal != nullptr); - - if (State.Env.flowConditionImplies(*HasValueVal)) - return; + if (auto *OptionalVal = + State.Env.getValue(*ObjectExpr, SkipPast::ReferenceThenPointer)) { + if (State.Env.getStorageLocation(*UnwrapExpr, SkipPast::None) == nullptr) + if (auto *Loc = maybeInitializeOptionalValueMember( + UnwrapExpr->getType(), *OptionalVal, State.Env)) + State.Env.setStorageLocation(*UnwrapExpr, *Loc); + + auto *Prop = OptionalVal->getProperty("has_value"); + if (auto *HasValueVal = cast_or_null(Prop)) { + if (State.Env.flowConditionImplies(*HasValueVal)) + return; + } } // Record that this unwrap is *not* provably safe. @@ -247,12 +336,9 @@ void transferMakeOptionalCall(const CallExpr *E, void transferOptionalHasValueCall(const CXXMemberCallExpr *CallExpr, const MatchFinder::MatchResult &, LatticeTransferState &State) { - if (auto *OptionalVal = cast_or_null( - State.Env.getValue(*CallExpr->getImplicitObjectArgument(), - SkipPast::ReferenceThenPointer))) { - auto *HasValueVal = getHasValue(OptionalVal); - assert(HasValueVal != nullptr); - + if (auto *HasValueVal = getHasValue( + State.Env, State.Env.getValue(*CallExpr->getImplicitObjectArgument(), + SkipPast::ReferenceThenPointer))) { auto &CallExprLoc = State.Env.createStorageLocation(*CallExpr); State.Env.setValue(CallExprLoc, *HasValueVal); State.Env.setStorageLocation(*CallExpr, CallExprLoc); @@ -273,12 +359,11 @@ void transferValueOrImpl(const clang::Expr *ValueOrPredExpr, Result.Nodes.getNodeAs(ValueOrCallID) ->getImplicitObjectArgument(); - auto *OptionalVal = cast_or_null( - Env.getValue(*ObjectArgumentExpr, SkipPast::ReferenceThenPointer)); - if (OptionalVal == nullptr) + auto *HasValueVal = getHasValue( + State.Env, + State.Env.getValue(*ObjectArgumentExpr, SkipPast::ReferenceThenPointer)); + if (HasValueVal == nullptr) return; - auto *HasValueVal = getHasValue(OptionalVal); - assert(HasValueVal != nullptr); auto *ExprValue = cast_or_null( State.Env.getValue(*ValueOrPredExpr, SkipPast::None)); @@ -322,6 +407,18 @@ void transferValueOrNotEqX(const Expr *ComparisonExpr, }); } +void transferCallReturningOptional(const CallExpr *E, + const MatchFinder::MatchResult &Result, + LatticeTransferState &State) { + if (State.Env.getStorageLocation(*E, SkipPast::None) != nullptr) + return; + + auto &Loc = State.Env.createStorageLocation(*E); + State.Env.setStorageLocation(*E, Loc); + State.Env.setValue( + Loc, createOptionalValue(State.Env, State.Env.makeAtomicBoolValue())); +} + void assignOptionalValue(const Expr &E, LatticeTransferState &State, BoolValue &HasValueVal) { if (auto *OptionalLoc = @@ -353,8 +450,9 @@ getValueOrConversionHasValue(const FunctionDecl &F, const Expr &E, // This is a constructor/assignment call for `optional` with argument of // type `optional` such that `T` is constructible from `U`. - if (BoolValue *Val = getHasValue(State.Env.getValue(E, SkipPast::Reference))) - return *Val; + if (auto *HasValueVal = + getHasValue(State.Env, State.Env.getValue(E, SkipPast::Reference))) + return *HasValueVal; return State.Env.makeAtomicBoolValue(); } @@ -375,7 +473,8 @@ void transferAssignment(const CXXOperatorCallExpr *E, BoolValue &HasValueVal, auto *OptionalLoc = State.Env.getStorageLocation(*E->getArg(0), SkipPast::Reference); - assert(OptionalLoc != nullptr); + if (OptionalLoc == nullptr) + return; State.Env.setValue(*OptionalLoc, createOptionalValue(State.Env, HasValueVal)); @@ -462,8 +561,9 @@ auto buildTransferMatchSwitch( return MatchSwitchBuilder() // Attach a symbolic "has_value" state to optional values that we see for // the first time. - .CaseOf(expr(anyOf(declRefExpr(), memberExpr()), hasOptionalType()), - initializeOptionalReference) + .CaseOf( + expr(anyOf(declRefExpr(), memberExpr()), hasOptionalType()), + initializeOptionalReference) // make_optional .CaseOf(isMakeOptionalCall(), transferMakeOptionalCall) @@ -547,6 +647,10 @@ auto buildTransferMatchSwitch( // opt.value_or(X) != X .CaseOf(isValueOrNotEqX(), transferValueOrNotEqX) + // returns optional + .CaseOf(isCallReturningOptional(), + transferCallReturningOptional) + .Build(); } @@ -570,5 +674,31 @@ void UncheckedOptionalAccessModel::transfer(const Stmt *S, TransferMatchSwitch(*S, getASTContext(), State); } +bool UncheckedOptionalAccessModel::compareEquivalent(QualType Type, + const Value &Val1, + const Environment &Env1, + const Value &Val2, + const Environment &Env2) { + return isNonEmptyOptional(Val1, Env1) == isNonEmptyOptional(Val2, Env2); +} + +bool UncheckedOptionalAccessModel::merge(QualType Type, const Value &Val1, + const Environment &Env1, + const Value &Val2, + const Environment &Env2, + Value &MergedVal, + Environment &MergedEnv) { + if (!IsOptionalType(Type)) + return true; + + auto &HasValueVal = MergedEnv.makeAtomicBoolValue(); + if (isNonEmptyOptional(Val1, Env1) && isNonEmptyOptional(Val2, Env2)) + MergedEnv.addToFlowCondition(HasValueVal); + else if (isEmptyOptional(Val1, Env1) && isEmptyOptional(Val2, Env2)) + MergedEnv.addToFlowCondition(MergedEnv.makeNot(HasValueVal)); + setHasValue(MergedVal, HasValueVal); + return true; +} + } // namespace dataflow } // namespace clang diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index fc04e0b55ffc7..a56e277f7962f 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -136,9 +136,6 @@ class TransferVisitor : public ConstStmtVisitor { return; } - InitExpr = D.getInit(); - assert(InitExpr != nullptr); - if (D.getType()->isReferenceType()) { // Initializing a reference variable - do not create a reference to // reference. @@ -147,25 +144,52 @@ class TransferVisitor : public ConstStmtVisitor { auto &Val = Env.takeOwnership(std::make_unique(*InitExprLoc)); Env.setValue(Loc, Val); - return; } } else if (auto *InitExprVal = Env.getValue(*InitExpr, SkipPast::None)) { Env.setValue(Loc, *InitExprVal); - return; } - // We arrive here in (the few) cases where an expression is intentionally - // "uninterpreted". There are two ways to handle this situation: propagate - // the status, so that uninterpreted initializers result in uninterpreted - // variables, or provide a default value. We choose the latter so that later - // refinements of the variable can be used for reasoning about the - // surrounding code. - // - // FIXME. If and when we interpret all language cases, change this to assert - // that `InitExpr` is interpreted, rather than supplying a default value - // (assuming we don't update the environment API to return references). - if (Value *Val = Env.createValue(D.getType())) - Env.setValue(Loc, *Val); + if (Env.getValue(Loc) == nullptr) { + // We arrive here in (the few) cases where an expression is intentionally + // "uninterpreted". There are two ways to handle this situation: propagate + // the status, so that uninterpreted initializers result in uninterpreted + // variables, or provide a default value. We choose the latter so that + // later refinements of the variable can be used for reasoning about the + // surrounding code. + // + // FIXME. If and when we interpret all language cases, change this to + // assert that `InitExpr` is interpreted, rather than supplying a default + // value (assuming we don't update the environment API to return + // references). + if (Value *Val = Env.createValue(D.getType())) + Env.setValue(Loc, *Val); + } + + if (const auto *Decomp = dyn_cast(&D)) { + // If VarDecl is a DecompositionDecl, evaluate each of its bindings. This + // needs to be evaluated after initializing the values in the storage for + // VarDecl, as the bindings refer to them. + // FIXME: Add support for ArraySubscriptExpr. + // FIXME: Consider adding AST nodes that are used for structured bindings + // to the CFG. + for (const auto *B : Decomp->bindings()) { + auto *ME = dyn_cast_or_null(B->getBinding()); + if (ME == nullptr) + continue; + + auto *DE = dyn_cast_or_null(ME->getBase()); + if (DE == nullptr) + continue; + + // ME and its base haven't been visited because they aren't included in + // the statements of the CFG basic block. + VisitDeclRefExpr(DE); + VisitMemberExpr(ME); + + if (auto *Loc = Env.getStorageLocation(*ME, SkipPast::Reference)) + Env.setStorageLocation(*B, *Loc); + } + } } void VisitImplicitCastExpr(const ImplicitCastExpr *S) { diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp index 62eea9c590825..960c9773d192a 100644 --- a/clang/lib/Basic/Attributes.cpp +++ b/clang/lib/Basic/Attributes.cpp @@ -5,9 +5,9 @@ #include "llvm/ADT/StringSwitch.h" using namespace clang; -int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, - const IdentifierInfo *Attr, const TargetInfo &Target, - const LangOptions &LangOpts) { +int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax, + const IdentifierInfo *Scope, const IdentifierInfo *Attr, + const TargetInfo &Target, const LangOptions &LangOpts) { StringRef Name = Attr->getName(); // Normalize the attribute name, __foo__ becomes foo. if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__")) @@ -85,6 +85,10 @@ bool AttributeCommonInfo::isGNUScope() const { return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__")); } +bool AttributeCommonInfo::isClangScope() const { + return ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang")); +} + #include "clang/Sema/AttrParsedAttrKinds.inc" static SmallString<64> normalizeName(const IdentifierInfo *Name, diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp index a8a17994f7fc8..8e2593b103d15 100644 --- a/clang/lib/Basic/DiagnosticIDs.cpp +++ b/clang/lib/Basic/DiagnosticIDs.cpp @@ -607,6 +607,7 @@ namespace { uint16_t NameOffset; uint16_t Members; uint16_t SubGroups; + StringRef Documentation; // String is stored with a pascal-style length byte. StringRef getName() const { @@ -618,12 +619,17 @@ namespace { // Second the table of options, sorted by name for fast binary lookup. static const WarningOption OptionTable[] = { -#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups) \ - {FlagNameOffset, Members, SubGroups}, +#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \ + {FlagNameOffset, Members, SubGroups, Docs}, #include "clang/Basic/DiagnosticGroups.inc" #undef DIAG_ENTRY }; +/// Given a diagnostic group ID, return its documentation. +StringRef DiagnosticIDs::getWarningOptionDocumentation(diag::Group Group) { + return OptionTable[static_cast(Group)].Documentation; +} + StringRef DiagnosticIDs::getWarningOptionForGroup(diag::Group Group) { return OptionTable[static_cast(Group)].getName(); } @@ -653,7 +659,7 @@ StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { } std::vector DiagnosticIDs::getDiagnosticFlags() { - std::vector Res; + std::vector Res{"-W", "-Wno-"}; for (size_t I = 1; DiagGroupNames[I] != '\0';) { std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]); I += DiagGroupNames[I] + 1; diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp index 7791bff388be7..7549f3f2e23b4 100644 --- a/clang/lib/Basic/LangOptions.cpp +++ b/clang/lib/Basic/LangOptions.cpp @@ -117,6 +117,8 @@ void LangOptions::setLangDefaults(LangOptions &Opts, Language Lang, Opts.Digraphs = Std.hasDigraphs(); Opts.HLSL = Lang == Language::HLSL; + if (Opts.HLSL && Opts.IncludeDefaultHeader) + Includes.push_back("hlsl.h"); // Set OpenCL Version. Opts.OpenCL = Std.isOpenCL(); diff --git a/clang/lib/Basic/LangStandards.cpp b/clang/lib/Basic/LangStandards.cpp index a21898dd3c627..5bacc3b164960 100644 --- a/clang/lib/Basic/LangStandards.cpp +++ b/clang/lib/Basic/LangStandards.cpp @@ -61,8 +61,8 @@ LangStandard::Kind clang::getDefaultLanguageStandard(clang::Language Lang, if (CLANG_DEFAULT_STD_C != LangStandard::lang_unspecified) return CLANG_DEFAULT_STD_C; - // The PS4 uses C99 as the default C standard. - if (T.isPS4()) + // The PS4 and PS5 use C99 as the default C standard. + if (T.isPS()) return LangStandard::lang_gnu99; return LangStandard::lang_gnu17; case Language::ObjC: diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index ae7dbfe7eb776..ba821f16c1f03 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -150,6 +150,9 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) { PlatformMinVersion = VersionTuple(); MaxOpenCLWorkGroupSize = 1024; + + MaxBitIntWidth.reset(); + ProgramAddrSpace = 0; } @@ -478,6 +481,9 @@ void TargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) { Diags.Report(diag::err_opt_not_valid_on_target) << "-fprotect-parens"; Opts.ProtectParens = false; } + + if (Opts.MaxBitIntWidth) + MaxBitIntWidth = Opts.MaxBitIntWidth; } bool TargetInfo::initFeatureMap( diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 85c73abde1826..2d6ef998485ae 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -592,6 +592,8 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, return new NaClTargetInfo(Triple, Opts); case llvm::Triple::PS4: return new PS4OSTargetInfo(Triple, Opts); + case llvm::Triple::PS5: + return new PS5OSTargetInfo(Triple, Opts); default: return new X86_64TargetInfo(Triple, Opts); } diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp index a1edc0d53ecba..66e9a22ca1ebb 100644 --- a/clang/lib/Basic/Targets/AMDGPU.cpp +++ b/clang/lib/Basic/Targets/AMDGPU.cpp @@ -462,9 +462,13 @@ void AMDGPUTargetInfo::setAuxTarget(const TargetInfo *Aux) { // supported by AMDGPU. Therefore keep its own format for these two types. auto SaveLongDoubleFormat = LongDoubleFormat; auto SaveFloat128Format = Float128Format; + auto SaveLongDoubleWidth = LongDoubleWidth; + auto SaveLongDoubleAlign = LongDoubleAlign; copyAuxTarget(Aux); LongDoubleFormat = SaveLongDoubleFormat; Float128Format = SaveFloat128Format; + LongDoubleWidth = SaveLongDoubleWidth; + LongDoubleAlign = SaveLongDoubleAlign; // For certain builtin types support on the host target, claim they are // support to pass the compilation of the host code during the device-side // compilation. diff --git a/clang/lib/Basic/Targets/AMDGPU.h b/clang/lib/Basic/Targets/AMDGPU.h index 4e3db7a181f58..5e73a3cb8019a 100644 --- a/clang/lib/Basic/Targets/AMDGPU.h +++ b/clang/lib/Basic/Targets/AMDGPU.h @@ -435,17 +435,17 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo { DiagnosticsEngine &Diags) override { auto TargetIDFeatures = getAllPossibleTargetIDFeatures(getTriple(), getArchNameAMDGCN(GPUKind)); - llvm::for_each(Features, [&](const auto &F) { + for (const auto &F : Features) { assert(F.front() == '+' || F.front() == '-'); if (F == "+wavefrontsize64") WavefrontSize = 64; bool IsOn = F.front() == '+'; StringRef Name = StringRef(F).drop_front(); if (!llvm::is_contained(TargetIDFeatures, Name)) - return; + continue; assert(OffloadArchFeatures.find(Name) == OffloadArchFeatures.end()); OffloadArchFeatures[Name] = IsOn; - }); + } return true; } diff --git a/clang/lib/Basic/Targets/OSTargets.cpp b/clang/lib/Basic/Targets/OSTargets.cpp index 6cf78fd4f2441..f79e20779a3d1 100644 --- a/clang/lib/Basic/Targets/OSTargets.cpp +++ b/clang/lib/Basic/Targets/OSTargets.cpp @@ -215,6 +215,9 @@ static void addVisualCDefines(const LangOptions &Opts, MacroBuilder &Builder) { } } + if (Opts.Kernel) + Builder.defineMacro("_KERNEL_MODE"); + Builder.defineMacro("_INTEGRAL_MAX_BITS", "64"); Builder.defineMacro("__STDC_NO_THREADS__"); diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h index e9832977c7fe8..a814f681b1468 100644 --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -541,8 +541,9 @@ class LLVM_LIBRARY_VISIBILITY PS3PPUTargetInfo : public OSTargetInfo { } }; +// Common base class for PS4/PS5 targets. template -class LLVM_LIBRARY_VISIBILITY PS4OSTargetInfo : public OSTargetInfo { +class LLVM_LIBRARY_VISIBILITY PSOSTargetInfo : public OSTargetInfo { protected: void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, MacroBuilder &Builder) const override { @@ -552,36 +553,66 @@ class LLVM_LIBRARY_VISIBILITY PS4OSTargetInfo : public OSTargetInfo { DefineStd(Builder, "unix", Opts); Builder.defineMacro("__ELF__"); Builder.defineMacro("__SCE__"); - Builder.defineMacro("__ORBIS__"); } public: - PS4OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + PSOSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : OSTargetInfo(Triple, Opts) { this->WCharType = TargetInfo::UnsignedShort; - // On PS4, TLS variable cannot be aligned to more than 32 bytes (256 bits). + // On PS4/PS5, TLS variable cannot be aligned to more than 32 bytes (256 + // bits). this->MaxTLSAlign = 256; - // On PS4, do not honor explicit bit field alignment, + // On PS4/PS5, do not honor explicit bit field alignment, // as in "__attribute__((aligned(2))) int b : 1;". this->UseExplicitBitFieldAlignment = false; - switch (Triple.getArch()) { - default: - case llvm::Triple::x86_64: - this->MCountName = ".mcount"; - this->NewAlign = 256; - this->SuitableAlign = 256; - break; - } + this->MCountName = ".mcount"; + this->NewAlign = 256; + this->SuitableAlign = 256; } + TargetInfo::CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { return (CC == CC_C) ? TargetInfo::CCCR_OK : TargetInfo::CCCR_Error; } }; +// PS4 Target +template +class LLVM_LIBRARY_VISIBILITY PS4OSTargetInfo : public PSOSTargetInfo { +protected: + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { + // Start with base class defines. + PSOSTargetInfo::getOSDefines(Opts, Triple, Builder); + + Builder.defineMacro("__ORBIS__"); + } + +public: + PS4OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : PSOSTargetInfo(Triple, Opts) {} +}; + +// PS5 Target +template +class LLVM_LIBRARY_VISIBILITY PS5OSTargetInfo : public PSOSTargetInfo { +protected: + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { + // Start with base class defines. + PSOSTargetInfo::getOSDefines(Opts, Triple, Builder); + + Builder.defineMacro("__PROSPERO__"); + } + +public: + PS5OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : PSOSTargetInfo(Triple, Opts) {} +}; + // RTEMS Target template class LLVM_LIBRARY_VISIBILITY RTEMSTargetInfo : public OSTargetInfo { diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index 7de40b5db04a3..9120808e298df 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -594,12 +594,12 @@ bool PPCTargetInfo::initFeatureMap( } if (!(ArchDefs & ArchDefinePwr10)) { - if (llvm::find(FeaturesVec, "+mma") != FeaturesVec.end()) { + if (llvm::is_contained(FeaturesVec, "+mma")) { // MMA operations are not available pre-Power10. Diags.Report(diag::err_opt_not_valid_with_opt) << "-mmma" << CPU; return false; } - if (llvm::find(FeaturesVec, "+pcrel") != FeaturesVec.end()) { + if (llvm::is_contained(FeaturesVec, "+pcrel")) { // PC-Relative instructions are not available pre-Power10, // and these instructions also require prefixed instructions support. Diags.Report(diag::err_opt_not_valid_without_opt) @@ -607,13 +607,13 @@ bool PPCTargetInfo::initFeatureMap( << "-mcpu=pwr10 -mprefixed"; return false; } - if (llvm::find(FeaturesVec, "+prefixed") != FeaturesVec.end()) { + if (llvm::is_contained(FeaturesVec, "+prefixed")) { // Prefixed instructions are not available pre-Power10. Diags.Report(diag::err_opt_not_valid_without_opt) << "-mprefixed" << "-mcpu=pwr10"; return false; } - if (llvm::find(FeaturesVec, "+paired-vector-memops") != FeaturesVec.end()) { + if (llvm::is_contained(FeaturesVec, "+paired-vector-memops")) { // Paired vector memops are not available pre-Power10. Diags.Report(diag::err_opt_not_valid_without_opt) << "-mpaired-vector-memops" diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index cc51bf78f0c1a..098bf21d6caa0 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -235,11 +235,9 @@ bool RISCVTargetInfo::initFeatureMap( // RISCVISAInfo makes implications for ISA features std::vector ImpliedFeatures = (*ParseResult)->toFeatureVector(); // Add non-ISA features like `relax` and `save-restore` back - for (std::string Feature : FeaturesVec) { - if (std::find(begin(ImpliedFeatures), end(ImpliedFeatures), Feature) == - end(ImpliedFeatures)) + for (const std::string &Feature : FeaturesVec) + if (!llvm::is_contained(ImpliedFeatures, Feature)) ImpliedFeatures.push_back(Feature); - } return TargetInfo::initFeatureMap(Features, Diags, CPU, ImpliedFeatures); } diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h index 0d12183055e18..6214148adab93 100644 --- a/clang/lib/CodeGen/ABIInfo.h +++ b/clang/lib/CodeGen/ABIInfo.h @@ -100,6 +100,7 @@ namespace swiftcall { virtual bool isHomogeneousAggregateSmallEnough(const Type *Base, uint64_t Members) const; + virtual bool isZeroLengthBitfieldPermittedInHomogeneousAggregate() const; bool isHomogeneousAggregate(QualType Ty, const Type *&Base, uint64_t &Members) const; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 94808e8a625e6..4b294c254e476 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -453,6 +453,7 @@ static bool initTargetOptions(DiagnosticsEngine &Diags, } Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile; + Options.MCOptions.EmitDwarfUnwind = CodeGenOpts.getEmitDwarfUnwind(); Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll; Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels; Options.MCOptions.MCUseDwarfDirectory = @@ -1221,6 +1222,6 @@ void clang::EmbedObject(llvm::Module *M, const CodeGenOptions &CGOpts, } llvm::embedBufferInModule(*M, **ObjectOrErr, ".llvm.offloading", - Align(OffloadBinary::getAlignment())); + Align(object::OffloadBinary::getAlignment())); } } diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index c087aa4635881..2fcfea64ede66 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -32,6 +32,7 @@ class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter { void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name, llvm::BasicBlock *BB, llvm::BasicBlock::iterator InsertPt) const override; + private: CodeGenFunction *CGF = nullptr; }; @@ -45,17 +46,18 @@ class CGBuilderTy : public CGBuilderBaseTy { /// Storing a reference to the type cache here makes it a lot easier /// to build natural-feeling, target-specific IR. const CodeGenTypeCache &TypeCache; + public: CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C) - : CGBuilderBaseTy(C), TypeCache(TypeCache) {} - CGBuilderTy(const CodeGenTypeCache &TypeCache, - llvm::LLVMContext &C, const llvm::ConstantFolder &F, + : CGBuilderBaseTy(C), TypeCache(TypeCache) {} + CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C, + const llvm::ConstantFolder &F, const CGBuilderInserterTy &Inserter) - : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {} + : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {} CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I) - : CGBuilderBaseTy(I), TypeCache(TypeCache) {} + : CGBuilderBaseTy(I), TypeCache(TypeCache) {} CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB) - : CGBuilderBaseTy(BB), TypeCache(TypeCache) {} + : CGBuilderBaseTy(BB), TypeCache(TypeCache) {} llvm::ConstantInt *getSize(CharUnits N) { return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity()); @@ -102,7 +104,8 @@ class CGBuilderTy : public CGBuilderBaseTy { using CGBuilderBaseTy::CreateAlignedStore; llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr, - CharUnits Align, bool IsVolatile = false) { + CharUnits Align, + bool IsVolatile = false) { return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile); } @@ -165,8 +168,8 @@ class CGBuilderTy : public CGBuilderBaseTy { Address CreateElementBitCast(Address Addr, llvm::Type *Ty, const llvm::Twine &Name = "") { auto *PtrTy = Ty->getPointerTo(Addr.getAddressSpace()); - return Address(CreateBitCast(Addr.getPointer(), PtrTy, Name), - Ty, Addr.getAlignment()); + return Address(CreateBitCast(Addr.getPointer(), PtrTy, Name), Ty, + Addr.getAlignment()); } using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; @@ -193,10 +196,10 @@ class CGBuilderTy : public CGBuilderBaseTy { const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - return Address(CreateStructGEP(Addr.getElementType(), - Addr.getPointer(), Index, Name), - ElTy->getElementType(Index), - Addr.getAlignment().alignmentAtOffset(Offset)); + return Address( + CreateStructGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset)); } /// Given @@ -264,10 +267,10 @@ class CGBuilderTy : public CGBuilderBaseTy { CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); - return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), Index, - Name), - Addr.getElementType(), - Addr.getAlignment().alignmentOfArrayElement(EltSize)); + return Address( + CreateGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), + Addr.getElementType(), + Addr.getAlignment().alignmentOfArrayElement(EltSize)); } /// Given a pointer to i8, adjust it by a given constant offset. @@ -341,9 +344,16 @@ class CGBuilderTy : public CGBuilderBaseTy { Dest.getAlignment().getAsAlign(), IsVolatile); } + using CGBuilderBaseTy::CreateMemSetInline; + llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value, + uint64_t Size) { + return CreateMemSetInline(Dest.getPointer(), + Dest.getAlignment().getAsAlign(), Value, + getInt64(Size)); + } + using CGBuilderBaseTy::CreatePreserveStructAccessIndex; - Address CreatePreserveStructAccessIndex(Address Addr, - unsigned Index, + Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index, unsigned FieldIndex, llvm::MDNode *DbgInfo) { llvm::StructType *ElTy = cast(Addr.getElementType()); @@ -363,7 +373,7 @@ class CGBuilderTy : public CGBuilderBaseTy { } }; -} // end namespace CodeGen -} // end namespace clang +} // end namespace CodeGen +} // end namespace clang #endif diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index bdc638299c4bd..c67df4d8137af 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3508,6 +3508,17 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.CreateMemSet(Dest, ByteVal, SizeVal, false); return RValue::get(Dest.getPointer()); } + case Builtin::BI__builtin_memset_inline: { + Address Dest = EmitPointerWithAlignment(E->getArg(0)); + Value *ByteVal = + Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), Builder.getInt8Ty()); + uint64_t Size = + E->getArg(2)->EvaluateKnownConstInt(getContext()).getZExtValue(); + EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), + E->getArg(0)->getExprLoc(), FD, 0); + Builder.CreateMemSetInline(Dest, ByteVal, Size); + return RValue::get(nullptr); + } case Builtin::BI__builtin___memset_chk: { // fold __builtin_memset_chk(x, y, cst1, cst2) to memset iff cst1<=cst2. Expr::EvalResult SizeResult, DstSizeResult; @@ -7783,6 +7794,11 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, AccessKind); } + if (BuiltinID == ARM::BI__builtin_sponentry) { + llvm::Function *F = CGM.getIntrinsic(Intrinsic::sponentry, AllocaInt8PtrTy); + return Builder.CreateCall(F); + } + // Handle MSVC intrinsics before argument evaluation to prevent double // evaluation. if (Optional MsvcIntId = translateArmToMsvcIntrin(BuiltinID)) @@ -18679,6 +18695,26 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, Function *Callee = CGM.getIntrinsic(IntNo); return Builder.CreateCall(Callee, {Vec}); } + case WebAssembly::BI__builtin_wasm_relaxed_q15mulr_s_i16x8: { + Value *LHS = EmitScalarExpr(E->getArg(0)); + Value *RHS = EmitScalarExpr(E->getArg(1)); + Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_relaxed_q15mulr_signed); + return Builder.CreateCall(Callee, {LHS, RHS}); + } + case WebAssembly::BI__builtin_wasm_dot_i8x16_i7x16_s_i16x8: { + Value *LHS = EmitScalarExpr(E->getArg(0)); + Value *RHS = EmitScalarExpr(E->getArg(1)); + Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_dot_i8x16_i7x16_signed); + return Builder.CreateCall(Callee, {LHS, RHS}); + } + case WebAssembly::BI__builtin_wasm_dot_i8x16_i7x16_add_s_i32x4: { + Value *LHS = EmitScalarExpr(E->getArg(0)); + Value *RHS = EmitScalarExpr(E->getArg(1)); + Value *Acc = EmitScalarExpr(E->getArg(2)); + Function *Callee = + CGM.getIntrinsic(Intrinsic::wasm_dot_i8x16_i7x16_add_signed); + return Builder.CreateCall(Callee, {LHS, RHS, Acc}); + } default: return nullptr; } diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 0d838b9aeb529..57eb8b2d93d26 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3466,7 +3466,7 @@ llvm::Value *CodeGenFunction::EmitCMSEClearRecord(llvm::Value *Src, int CharsPerElt = ATy->getArrayElementType()->getScalarSizeInBits() / CharWidth; int MaskIndex = 0; - llvm::Value *R = llvm::UndefValue::get(ATy); + llvm::Value *R = llvm::PoisonValue::get(ATy); for (int I = 0, N = ATy->getArrayNumElements(); I != N; ++I) { uint64_t Mask = buildMultiCharMask(Bits, MaskIndex, CharsPerElt, CharWidth, DataLayout.isBigEndian()); @@ -3640,7 +3640,7 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, // Construct a return type that lacks padding elements. llvm::Type *returnType = RetAI.getUnpaddedCoerceAndExpandType(); - RV = llvm::UndefValue::get(returnType); + RV = llvm::PoisonValue::get(returnType); for (unsigned i = 0, e = results.size(); i != e; ++i) { RV = Builder.CreateInsertValue(RV, results[i], i); } @@ -3747,7 +3747,7 @@ static AggValueSlot createPlaceholderSlot(CodeGenFunction &CGF, // placeholders. llvm::Type *IRTy = CGF.ConvertTypeForMem(Ty); llvm::Type *IRPtrTy = IRTy->getPointerTo(); - llvm::Value *Placeholder = llvm::UndefValue::get(IRPtrTy->getPointerTo()); + llvm::Value *Placeholder = llvm::PoisonValue::get(IRPtrTy->getPointerTo()); // FIXME: When we generate this IR in one pass, we shouldn't need // this win32-specific alignment hack. diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index a10851edfb82c..5035ed34358d2 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -77,7 +77,7 @@ RValue DominatingValue::saved_type::restore(CodeGenFunction &CGF) { auto getSavingAddress = [&](llvm::Value *value) { auto *AI = cast(value); return Address(value, AI->getAllocatedType(), - CharUnits::fromQuantity(AI->getAlignment())); + CharUnits::fromQuantity(AI->getAlign().value())); }; switch (K) { case ScalarLiteral: diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index 96696ebf2903c..4216ca1e2f017 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -654,9 +654,8 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { EmitStmt(Ret); } - // LLVM require the frontend to add the function attribute. See - // Coroutines.rst. - CurFn->addFnAttr("coroutine.presplit", "0"); + // LLVM require the frontend to mark the coroutine. + CurFn->setPresplitCoroutine(); } // Emit coroutine intrinsic and patch up arguments of the token type. diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index a16551e83f93b..f04af0d2cdf88 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -473,7 +473,7 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D, LocalDeclMap.find(&D)->second = Address(castedAddr, elemTy, alignment); CGM.setStaticLocalDeclAddress(&D, castedAddr); - CGM.getSanitizerMetadata()->reportGlobalToASan(var, D); + CGM.getSanitizerMetadata()->reportGlobal(var, D); // Emit global variable debug descriptor for static vars. CGDebugInfo *DI = getDebugInfo(); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 3d7f13aed0aba..cbeb6c938bee7 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -757,23 +757,23 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, } } - uint64_t AlignVal = 0; + llvm::MaybeAlign AlignVal; llvm::Value *PtrAsInt = nullptr; if (SanOpts.has(SanitizerKind::Alignment) && !SkippedChecks.has(SanitizerKind::Alignment)) { - AlignVal = Alignment.getQuantity(); + AlignVal = Alignment.getAsMaybeAlign(); if (!Ty->isIncompleteType() && !AlignVal) AlignVal = CGM.getNaturalTypeAlignment(Ty, nullptr, nullptr, /*ForPointeeType=*/true) - .getQuantity(); + .getAsMaybeAlign(); // The glvalue must be suitably aligned. - if (AlignVal > 1 && - (!PtrToAlloca || PtrToAlloca->getAlignment() < AlignVal)) { + if (AlignVal && *AlignVal > llvm::Align(1) && + (!PtrToAlloca || PtrToAlloca->getAlign() < *AlignVal)) { PtrAsInt = Builder.CreatePtrToInt(Ptr, IntPtrTy); llvm::Value *Align = Builder.CreateAnd( - PtrAsInt, llvm::ConstantInt::get(IntPtrTy, AlignVal - 1)); + PtrAsInt, llvm::ConstantInt::get(IntPtrTy, AlignVal->value() - 1)); llvm::Value *Aligned = Builder.CreateICmpEQ(Align, llvm::ConstantInt::get(IntPtrTy, 0)); if (Aligned != True) @@ -782,12 +782,9 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, } if (Checks.size() > 0) { - // Make sure we're not losing information. Alignment needs to be a power of - // 2 - assert(!AlignVal || (uint64_t)1 << llvm::Log2_64(AlignVal) == AlignVal); llvm::Constant *StaticData[] = { EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(Ty), - llvm::ConstantInt::get(Int8Ty, AlignVal ? llvm::Log2_64(AlignVal) : 1), + llvm::ConstantInt::get(Int8Ty, AlignVal ? llvm::Log2(*AlignVal) : 1), llvm::ConstantInt::get(Int8Ty, TCK)}; EmitCheck(Checks, SanitizerHandler::TypeMismatch, StaticData, PtrAsInt ? PtrAsInt : Ptr); diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index f78443fd20bcd..5232edd6a4afc 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -6159,8 +6159,10 @@ static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, static void emitOMPAtomicCompareExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, + const Expr *V, const Expr *R, const Expr *E, const Expr *D, const Expr *CE, bool IsXBinopExpr, + bool IsPostfixUpdate, bool IsFailOnly, SourceLocation Loc) { llvm::OpenMPIRBuilder &OMPBuilder = CGF.CGM.getOpenMPRuntime().getOMPBuilder(); @@ -6183,24 +6185,60 @@ static void emitOMPAtomicCompareExpr(CodeGenFunction &CGF, LValue XLVal = CGF.EmitLValue(X); Address XAddr = XLVal.getAddress(CGF); - llvm::Value *EVal = CGF.EmitScalarExpr(E); - llvm::Value *DVal = D ? CGF.EmitScalarExpr(D) : nullptr; + + auto EmitRValueWithCastIfNeeded = [&CGF, Loc](const Expr *X, const Expr *E) { + if (X->getType() == E->getType()) + return CGF.EmitScalarExpr(E); + const Expr *NewE = E->IgnoreImplicitAsWritten(); + llvm::Value *V = CGF.EmitScalarExpr(NewE); + if (NewE->getType() == X->getType()) + return V; + return CGF.EmitScalarConversion(V, NewE->getType(), X->getType(), Loc); + }; + + llvm::Value *EVal = EmitRValueWithCastIfNeeded(X, E); + llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(X, D) : nullptr; + if (auto *CI = dyn_cast(EVal)) + EVal = CGF.Builder.CreateIntCast( + CI, XLVal.getAddress(CGF).getElementType(), + E->getType()->hasSignedIntegerRepresentation()); + if (DVal) + if (auto *CI = dyn_cast(DVal)) + DVal = CGF.Builder.CreateIntCast( + CI, XLVal.getAddress(CGF).getElementType(), + D->getType()->hasSignedIntegerRepresentation()); llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{ XAddr.getPointer(), XAddr.getElementType(), X->getType()->hasSignedIntegerRepresentation(), X->getType().isVolatileQualified()}; + llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal; + if (V) { + LValue LV = CGF.EmitLValue(V); + Address Addr = LV.getAddress(CGF); + VOpVal = {Addr.getPointer(), Addr.getElementType(), + V->getType()->hasSignedIntegerRepresentation(), + V->getType().isVolatileQualified()}; + } + if (R) { + LValue LV = CGF.EmitLValue(R); + Address Addr = LV.getAddress(CGF); + ROpVal = {Addr.getPointer(), Addr.getElementType(), + R->getType()->hasSignedIntegerRepresentation(), + R->getType().isVolatileQualified()}; + } CGF.Builder.restoreIP(OMPBuilder.createAtomicCompare( - CGF.Builder, XOpVal, EVal, DVal, AO, Op, IsXBinopExpr)); + CGF.Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr, + IsPostfixUpdate, IsFailOnly)); } static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, llvm::AtomicOrdering AO, bool IsPostfixUpdate, - const Expr *X, const Expr *V, const Expr *E, - const Expr *UE, const Expr *D, const Expr *CE, - bool IsXLHSInRHSPart, bool IsCompareCapture, - SourceLocation Loc) { + const Expr *X, const Expr *V, const Expr *R, + const Expr *E, const Expr *UE, const Expr *D, + const Expr *CE, bool IsXLHSInRHSPart, + bool IsFailOnly, SourceLocation Loc) { switch (Kind) { case OMPC_read: emitOMPAtomicReadExpr(CGF, AO, X, V, Loc); @@ -6217,15 +6255,8 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, IsXLHSInRHSPart, Loc); break; case OMPC_compare: { - if (IsCompareCapture) { - // Emit an error here. - unsigned DiagID = CGF.CGM.getDiags().getCustomDiagID( - DiagnosticsEngine::Error, - "'atomic compare capture' is not supported for now"); - CGF.CGM.getDiags().Report(DiagID); - } else { - emitOMPAtomicCompareExpr(CGF, AO, X, E, D, CE, IsXLHSInRHSPart, Loc); - } + emitOMPAtomicCompareExpr(CGF, AO, X, V, R, E, D, CE, IsXLHSInRHSPart, + IsPostfixUpdate, IsFailOnly, Loc); break; } case OMPC_if: @@ -6352,12 +6383,12 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) { Kind = K; KindsEncountered.insert(K); } - bool IsCompareCapture = false; + // We just need to correct Kind here. No need to set a bool saying it is + // actually compare capture because we can tell from whether V and R are + // nullptr. if (KindsEncountered.contains(OMPC_compare) && - KindsEncountered.contains(OMPC_capture)) { - IsCompareCapture = true; + KindsEncountered.contains(OMPC_capture)) Kind = OMPC_compare; - } if (!MemOrderingSpecified) { llvm::AtomicOrdering DefaultOrder = CGM.getOpenMPRuntime().getDefaultMemoryOrdering(); @@ -6379,8 +6410,9 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) { LexicalScope Scope(*this, S.getSourceRange()); EmitStopPoint(S.getAssociatedStmt()); emitOMPAtomicExpr(*this, Kind, AO, S.isPostfixUpdate(), S.getX(), S.getV(), - S.getExpr(), S.getUpdateExpr(), S.getD(), S.getCondExpr(), - S.isXLHSInRHSPart(), IsCompareCapture, S.getBeginLoc()); + S.getR(), S.getExpr(), S.getUpdateExpr(), S.getD(), + S.getCondExpr(), S.isXLHSInRHSPart(), S.isFailOnly(), + S.getBeginLoc()); } static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index b4ae266f89881..05738c03796be 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -70,9 +70,8 @@ using namespace clang; using namespace CodeGen; static llvm::cl::opt LimitedCoverage( - "limited-coverage-experimental", llvm::cl::ZeroOrMore, llvm::cl::Hidden, - llvm::cl::desc("Emit limited coverage mapping information (experimental)"), - llvm::cl::init(false)); + "limited-coverage-experimental", llvm::cl::Hidden, + llvm::cl::desc("Emit limited coverage mapping information (experimental)")); static const char AnnotationSection[] = "llvm.metadata"; @@ -555,10 +554,8 @@ void CodeGenModule::Release() { CodeGenFunction(*this).EmitCfiCheckStub(); } emitAtAvailableLinkGuard(); - if (Context.getTargetInfo().getTriple().isWasm() && - !Context.getTargetInfo().getTriple().isOSEmscripten()) { + if (Context.getTargetInfo().getTriple().isWasm()) EmitMainVoidAlias(); - } if (getTriple().isAMDGPU()) { // Emit reference of __amdgpu_device_library_preserve_asan_functions to @@ -1217,7 +1214,9 @@ void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV, if (D && D->isExternallyVisible()) { if (D->hasAttr()) GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass); - else if (D->hasAttr() && !GV->isDeclarationForLinker()) + else if ((D->hasAttr() || + shouldMapVisibilityToDLLExport(D)) && + !GV->isDeclarationForLinker()) GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass); } } @@ -2761,21 +2760,14 @@ bool CodeGenModule::isInNoSanitizeList(SanitizerMask Kind, llvm::Function *Fn, return false; } -bool CodeGenModule::isInNoSanitizeList(llvm::GlobalVariable *GV, +bool CodeGenModule::isInNoSanitizeList(SanitizerMask Kind, + llvm::GlobalVariable *GV, SourceLocation Loc, QualType Ty, StringRef Category) const { - // For now globals can be ignored only in ASan and KASan. - const SanitizerMask EnabledAsanMask = - LangOpts.Sanitize.Mask & - (SanitizerKind::Address | SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress | - SanitizerKind::MemTag); - if (!EnabledAsanMask) - return false; const auto &NoSanitizeL = getContext().getNoSanitizeList(); - if (NoSanitizeL.containsGlobal(EnabledAsanMask, GV->getName(), Category)) + if (NoSanitizeL.containsGlobal(Kind, GV->getName(), Category)) return true; - if (NoSanitizeL.containsLocation(EnabledAsanMask, Loc, Category)) + if (NoSanitizeL.containsLocation(Kind, Loc, Category)) return true; // Check global type. if (!Ty.isNull()) { @@ -2787,7 +2779,7 @@ bool CodeGenModule::isInNoSanitizeList(llvm::GlobalVariable *GV, // Only record types (classes, structs etc.) are ignored. if (Ty->isRecordType()) { std::string TypeStr = Ty.getAsString(getContext().getPrintingPolicy()); - if (NoSanitizeL.containsType(EnabledAsanMask, TypeStr, Category)) + if (NoSanitizeL.containsType(Kind, TypeStr, Category)) return true; } } @@ -3667,7 +3659,7 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) { // Fix up function declarations that were created for cpu_specific before // cpu_dispatch was known - if (!dyn_cast(IFunc)) { + if (!isa(IFunc)) { assert(cast(IFunc)->isDeclaration()); auto *GI = llvm::GlobalIFunc::create(DeclTy, 0, Linkage, "", ResolverFunc, &getModule()); @@ -3793,7 +3785,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( } // Handle dropped DLL attributes. - if (D && !D->hasAttr() && !D->hasAttr()) { + if (D && !D->hasAttr() && !D->hasAttr() && + !shouldMapVisibilityToDLLExport(cast_or_null(D))) { Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); setDSOLocal(Entry); } @@ -4105,7 +4098,8 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty, } // Handle dropped DLL attributes. - if (D && !D->hasAttr() && !D->hasAttr()) + if (D && !D->hasAttr() && !D->hasAttr() && + !shouldMapVisibilityToDLLExport(D)) Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); if (LangOpts.OpenMP && !LangOpts.OpenMPSimd && D) @@ -4798,7 +4792,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, if (NeedsGlobalCtor || NeedsGlobalDtor) EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor); - SanitizerMD->reportGlobalToASan(GV, *D, NeedsGlobalCtor); + SanitizerMD->reportGlobal(GV, *D, NeedsGlobalCtor); // Emit global variable debug information. if (CGDebugInfo *DI = getModuleDebugInfo()) @@ -4899,12 +4893,8 @@ llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator( if (Linkage == GVA_Internal) return llvm::Function::InternalLinkage; - if (D->hasAttr()) { - if (IsConstantVariable) - return llvm::GlobalVariable::WeakODRLinkage; - else - return llvm::GlobalVariable::WeakAnyLinkage; - } + if (D->hasAttr()) + return llvm::GlobalVariable::WeakAnyLinkage; if (const auto *FD = D->getAsFunction()) if (FD->isMultiVersion() && Linkage == GVA_AvailableExternally) @@ -5684,8 +5674,7 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S, if (Entry) *Entry = GV; - SanitizerMD->reportGlobalToASan(GV, S->getStrTokenLoc(0), "", - QualType()); + SanitizerMD->reportGlobal(GV, S->getStrTokenLoc(0), ""); return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV), GV->getValueType(), Alignment); @@ -6357,8 +6346,10 @@ void CodeGenModule::EmitMainVoidAlias() { // new-style no-argument main is in used. if (llvm::Function *F = getModule().getFunction("main")) { if (!F->isDeclaration() && F->arg_size() == 0 && !F->isVarArg() && - F->getReturnType()->isIntegerTy(Context.getTargetInfo().getIntWidth())) - addUsedGlobal(llvm::GlobalAlias::create("__main_void", F)); + F->getReturnType()->isIntegerTy(Context.getTargetInfo().getIntWidth())) { + auto *GA = llvm::GlobalAlias::create("__main_void", F); + GA->setVisibility(llvm::GlobalValue::HiddenVisibility); + } } } @@ -6393,6 +6384,10 @@ bool CodeGenModule::CheckAndReplaceExternCIFuncs(llvm::GlobalValue *Elem, // here. llvm::SmallVector CEs; + // It isn't valid to replace the extern-C ifuncs if all we find is itself! + if (Elem == CppFunc) + return false; + // First make sure that all users of this are ifuncs (or ifuncs via a // bitcast), and collect the list of ifuncs and CEs so we can work on them // later. @@ -6461,7 +6456,7 @@ void CodeGenModule::EmitStaticExternCAliases() { // If Val is null, that implies there were multiple declarations that each // had a claim to the unmangled name. In this case, generation of the alias - // is suppressed. See CodeGenModule::MaybeHandleStaticInExterC. + // is suppressed. See CodeGenModule::MaybeHandleStaticInExternC. if (!Val) break; diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 0ac476dd6dbcc..779d94ad62d98 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -798,6 +798,14 @@ class CodeGenModule : public CodeGenTypeCache { void setDSOLocal(llvm::GlobalValue *GV) const; + bool shouldMapVisibilityToDLLExport(const NamedDecl *D) const { + return getLangOpts().hasDefaultVisibilityExportMapping() && D && + (D->getLinkageAndVisibility().getVisibility() == + DefaultVisibility) && + (getLangOpts().isAllDefaultVisibilityExportMapping() || + (getLangOpts().isExplicitDefaultVisibilityExportMapping() && + D->getLinkageAndVisibility().isVisibilityExplicit())); + } void setDLLImportDLLExport(llvm::GlobalValue *GV, GlobalDecl D) const; void setDLLImportDLLExport(llvm::GlobalValue *GV, const NamedDecl *D) const; /// Set visibility, dllimport/dllexport and dso_local. @@ -1306,8 +1314,9 @@ class CodeGenModule : public CodeGenTypeCache { bool isInNoSanitizeList(SanitizerMask Kind, llvm::Function *Fn, SourceLocation Loc) const; - bool isInNoSanitizeList(llvm::GlobalVariable *GV, SourceLocation Loc, - QualType Ty, StringRef Category = StringRef()) const; + bool isInNoSanitizeList(SanitizerMask Kind, llvm::GlobalVariable *GV, + SourceLocation Loc, QualType Ty, + StringRef Category = StringRef()) const; /// Imbue XRay attributes to a function, applying the always/never attribute /// lists in the process. Returns true if we did imbue attributes this way, diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 6657f2a91e3d8..587bcef78ee51 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -23,7 +23,7 @@ #include "llvm/Support/MD5.h" static llvm::cl::opt - EnableValueProfiling("enable-value-profiling", llvm::cl::ZeroOrMore, + EnableValueProfiling("enable-value-profiling", llvm::cl::desc("Enable value profiling"), llvm::cl::Hidden, llvm::cl::init(false)); diff --git a/clang/lib/CodeGen/ConstantInitBuilder.cpp b/clang/lib/CodeGen/ConstantInitBuilder.cpp index 24e3ca19709cb..06d3e44f01b1a 100644 --- a/clang/lib/CodeGen/ConstantInitBuilder.cpp +++ b/clang/lib/CodeGen/ConstantInitBuilder.cpp @@ -114,7 +114,7 @@ void ConstantInitBuilderBase::abandon(size_t newEnd) { if (newEnd == 0) { for (auto &entry : SelfReferences) { auto dummy = entry.Dummy; - dummy->replaceAllUsesWith(llvm::UndefValue::get(dummy->getType())); + dummy->replaceAllUsesWith(llvm::PoisonValue::get(dummy->getType())); dummy->eraseFromParent(); } SelfReferences.clear(); diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 8952125eeefcb..d1cbe109a6cf8 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -60,26 +60,27 @@ CoverageMappingModuleGen::setUpCoverageCallbacks(Preprocessor &PP) { return CoverageInfo; } -void CoverageSourceInfo::AddSkippedRange(SourceRange Range) { +void CoverageSourceInfo::AddSkippedRange(SourceRange Range, + SkippedRange::Kind RangeKind) { if (EmptyLineCommentCoverage && !SkippedRanges.empty() && PrevTokLoc == SkippedRanges.back().PrevTokLoc && SourceMgr.isWrittenInSameFile(SkippedRanges.back().Range.getEnd(), Range.getBegin())) SkippedRanges.back().Range.setEnd(Range.getEnd()); else - SkippedRanges.push_back({Range, PrevTokLoc}); + SkippedRanges.push_back({Range, RangeKind, PrevTokLoc}); } void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) { - AddSkippedRange(Range); + AddSkippedRange(Range, SkippedRange::PPIfElse); } void CoverageSourceInfo::HandleEmptyline(SourceRange Range) { - AddSkippedRange(Range); + AddSkippedRange(Range, SkippedRange::EmptyLine); } bool CoverageSourceInfo::HandleComment(Preprocessor &PP, SourceRange Range) { - AddSkippedRange(Range); + AddSkippedRange(Range, SkippedRange::Comment); return false; } @@ -335,6 +336,8 @@ class CoverageMappingBuilder { /// This shrinks the skipped range if it spans a line that contains a /// non-comment token. If shrinking the skipped range would make it empty, /// this returns None. + /// Note this function can potentially be expensive because + /// getSpellingLineNumber uses getLineNumber, which is expensive. Optional adjustSkippedRange(SourceManager &SM, SourceLocation LocStart, SourceLocation LocEnd, @@ -382,8 +385,13 @@ class CoverageMappingBuilder { auto CovFileID = getCoverageFileID(LocStart); if (!CovFileID) continue; - Optional SR = - adjustSkippedRange(SM, LocStart, LocEnd, I.PrevTokLoc, I.NextTokLoc); + Optional SR; + if (I.isComment()) + SR = adjustSkippedRange(SM, LocStart, LocEnd, I.PrevTokLoc, + I.NextTokLoc); + else if (I.isPPIfElse() || I.isEmptyLine()) + SR = {SM, LocStart, LocEnd}; + if (!SR.hasValue()) continue; auto Region = CounterMappingRegion::makeSkipped( diff --git a/clang/lib/CodeGen/CoverageMappingGen.h b/clang/lib/CodeGen/CoverageMappingGen.h index ae4f435d4ff34..f5282601b6406 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.h +++ b/clang/lib/CodeGen/CoverageMappingGen.h @@ -31,15 +31,29 @@ class Decl; class Stmt; struct SkippedRange { + enum Kind { + PPIfElse, // Preprocessor #if/#else ... + EmptyLine, + Comment, + }; + SourceRange Range; // The location of token before the skipped source range. SourceLocation PrevTokLoc; // The location of token after the skipped source range. SourceLocation NextTokLoc; + // The nature of this skipped range + Kind RangeKind; + + bool isComment() { return RangeKind == Comment; } + bool isEmptyLine() { return RangeKind == EmptyLine; } + bool isPPIfElse() { return RangeKind == PPIfElse; } - SkippedRange(SourceRange Range, SourceLocation PrevTokLoc = SourceLocation(), + SkippedRange(SourceRange Range, Kind K, + SourceLocation PrevTokLoc = SourceLocation(), SourceLocation NextTokLoc = SourceLocation()) - : Range(Range), PrevTokLoc(PrevTokLoc), NextTokLoc(NextTokLoc) {} + : Range(Range), PrevTokLoc(PrevTokLoc), NextTokLoc(NextTokLoc), + RangeKind(K) {} }; /// Stores additional source code information like skipped ranges which @@ -62,7 +76,7 @@ class CoverageSourceInfo : public PPCallbacks, std::vector &getSkippedRanges() { return SkippedRanges; } - void AddSkippedRange(SourceRange Range); + void AddSkippedRange(SourceRange Range, SkippedRange::Kind RangeKind); void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override; diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index c2213c6e0df37..03b06b8bc5220 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3680,12 +3680,14 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) { llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass = llvm::GlobalValue::DefaultStorageClass; - if (CGM.getTriple().isWindowsItaniumEnvironment()) { - auto RD = Ty->getAsCXXRecordDecl(); - if (RD && RD->hasAttr()) + if (auto RD = Ty->getAsCXXRecordDecl()) { + if ((CGM.getTriple().isWindowsItaniumEnvironment() && + RD->hasAttr()) || + (CGM.shouldMapVisibilityToDLLExport(RD) && + !llvm::GlobalValue::isLocalLinkage(Linkage) && + llvmVisibility == llvm::GlobalValue::DefaultVisibility)) DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass; } - return BuildTypeInfo(Ty, Linkage, llvmVisibility, DLLStorageClass); } @@ -4168,9 +4170,9 @@ void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) { getContext().Char32Ty }; llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass = - RD->hasAttr() - ? llvm::GlobalValue::DLLExportStorageClass - : llvm::GlobalValue::DefaultStorageClass; + RD->hasAttr() || CGM.shouldMapVisibilityToDLLExport(RD) + ? llvm::GlobalValue::DLLExportStorageClass + : llvm::GlobalValue::DefaultStorageClass; llvm::GlobalValue::VisibilityTypes Visibility = CodeGenModule::GetLLVMVisibility(RD->getVisibility()); for (const QualType &FundamentalType : FundamentalTypes) { diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 14912c3a415a3..2bc1e8e8c5b9f 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -47,7 +47,11 @@ class MicrosoftCXXABI : public CGCXXABI { : CGCXXABI(CGM), BaseClassDescriptorType(nullptr), ClassHierarchyDescriptorType(nullptr), CompleteObjectLocatorType(nullptr), CatchableTypeType(nullptr), - ThrowInfoType(nullptr) {} + ThrowInfoType(nullptr) { + assert(!(CGM.getLangOpts().isExplicitDefaultVisibilityExportMapping() || + CGM.getLangOpts().isAllDefaultVisibilityExportMapping()) && + "visibility export mapping option unimplemented in this ABI"); + } bool HasThisReturn(GlobalDecl GD) const override; bool hasMostDerivedReturn(GlobalDecl GD) const override; diff --git a/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp index 9fe7e5d1f5c31..d03e5bd508731 100644 --- a/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp +++ b/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp @@ -96,6 +96,10 @@ class PCHContainerGenerator : public ASTConsumer { } bool VisitFunctionDecl(FunctionDecl *D) { + // Skip deduction guides. + if (isa(D)) + return true; + if (isa(D)) // This is not yet supported. Constructing the `this' argument // mandates a CodeGenFunction. diff --git a/clang/lib/CodeGen/SanitizerMetadata.cpp b/clang/lib/CodeGen/SanitizerMetadata.cpp index 51f67622c9419..c3e23c31b37a4 100644 --- a/clang/lib/CodeGen/SanitizerMetadata.cpp +++ b/clang/lib/CodeGen/SanitizerMetadata.cpp @@ -22,21 +22,66 @@ using namespace CodeGen; SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {} -static bool isAsanHwasanOrMemTag(const SanitizerSet& SS) { +// TODO(hctim): Can be removed when we migrate off of llvm.asan.globals. This +// prevents llvm.asan.globals from being emitted for +// __attribute__((disable_sanitizer_instrumentation)) and uses of +// -fsanitize-ignorelist when a sanitizer isn't enabled. +static bool isAsanHwasanOrMemTag(const SanitizerSet &SS) { return SS.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress | - SanitizerKind::MemTag); + SanitizerKind::HWAddress | SanitizerKind::MemTag); } -void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, - SourceLocation Loc, StringRef Name, - QualType Ty, bool IsDynInit, - bool IsExcluded) { - if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) +SanitizerMask expandKernelSanitizerMasks(SanitizerMask Mask) { + if (Mask & (SanitizerKind::Address | SanitizerKind::KernelAddress)) + Mask |= SanitizerKind::Address | SanitizerKind::KernelAddress; + // Note: KHWASan doesn't support globals. + return Mask; +} + +void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, + SourceLocation Loc, StringRef Name, + QualType Ty, + SanitizerMask NoSanitizeAttrMask, + bool IsDynInit) { + SanitizerSet FsanitizeArgument = CGM.getLangOpts().Sanitize; + if (!isAsanHwasanOrMemTag(FsanitizeArgument)) return; - IsDynInit &= !CGM.isInNoSanitizeList(GV, Loc, Ty, "init"); - IsExcluded |= CGM.isInNoSanitizeList(GV, Loc, Ty); + FsanitizeArgument.Mask = expandKernelSanitizerMasks(FsanitizeArgument.Mask); + NoSanitizeAttrMask = expandKernelSanitizerMasks(NoSanitizeAttrMask); + SanitizerSet NoSanitizeAttrSet = {NoSanitizeAttrMask & + FsanitizeArgument.Mask}; + + llvm::GlobalVariable::SanitizerMetadata Meta; + if (GV->hasSanitizerMetadata()) + Meta = GV->getSanitizerMetadata(); + + Meta.NoAddress |= NoSanitizeAttrSet.hasOneOf(SanitizerKind::Address); + Meta.NoAddress |= CGM.isInNoSanitizeList( + FsanitizeArgument.Mask & SanitizerKind::Address, GV, Loc, Ty); + + Meta.NoHWAddress |= NoSanitizeAttrSet.hasOneOf(SanitizerKind::HWAddress); + Meta.NoHWAddress |= CGM.isInNoSanitizeList( + FsanitizeArgument.Mask & SanitizerKind::HWAddress, GV, Loc, Ty); + + Meta.NoMemtag |= NoSanitizeAttrSet.hasOneOf(SanitizerKind::MemTag); + Meta.NoMemtag |= CGM.isInNoSanitizeList( + FsanitizeArgument.Mask & SanitizerKind::MemTag, GV, Loc, Ty); + + if (FsanitizeArgument.has(SanitizerKind::Address)) { + // TODO(hctim): Make this conditional when we migrate off llvm.asan.globals. + IsDynInit &= !CGM.isInNoSanitizeList(SanitizerKind::Address | + SanitizerKind::KernelAddress, + GV, Loc, Ty, "init"); + Meta.IsDynInit = IsDynInit; + } + + bool IsExcluded = Meta.NoAddress || Meta.NoHWAddress || Meta.NoMemtag; + + GV->setSanitizerMetadata(Meta); + + // TODO(hctim): Code below can be removed when we migrate off of + // llvm.asan.globals onto the new metadata attributes. llvm::Metadata *LocDescr = nullptr; llvm::Metadata *GlobalName = nullptr; llvm::LLVMContext &VMContext = CGM.getLLVMContext(); @@ -61,29 +106,31 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, AsanGlobals->addOperand(ThisGlobal); } -void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, - const VarDecl &D, bool IsDynInit) { +void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D, + bool IsDynInit) { if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) return; std::string QualName; llvm::raw_string_ostream OS(QualName); D.printQualifiedName(OS); - bool IsExcluded = false; - for (auto Attr : D.specific_attrs()) - if (Attr->getMask() & SanitizerKind::Address) - IsExcluded = true; - if (D.hasAttr()) - IsExcluded = true; - reportGlobalToASan(GV, D.getLocation(), OS.str(), D.getType(), IsDynInit, - IsExcluded); + auto getNoSanitizeMask = [](const VarDecl &D) { + if (D.hasAttr()) + return SanitizerKind::All; + + SanitizerMask NoSanitizeMask; + for (auto *Attr : D.specific_attrs()) + NoSanitizeMask |= Attr->getMask(); + + return NoSanitizeMask; + }; + + reportGlobal(GV, D.getLocation(), OS.str(), D.getType(), getNoSanitizeMask(D), + IsDynInit); } void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) { - // For now, just make sure the global is not modified by the ASan - // instrumentation. - if (isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) - reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true); + reportGlobal(GV, SourceLocation(), "", QualType(), SanitizerKind::All); } void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) { diff --git a/clang/lib/CodeGen/SanitizerMetadata.h b/clang/lib/CodeGen/SanitizerMetadata.h index 440a54590acc8..41e1dca32aad7 100644 --- a/clang/lib/CodeGen/SanitizerMetadata.h +++ b/clang/lib/CodeGen/SanitizerMetadata.h @@ -14,13 +14,14 @@ #include "clang/AST/Type.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/Sanitizers.h" #include "clang/Basic/SourceLocation.h" namespace llvm { class GlobalVariable; class Instruction; class MDNode; -} +} // namespace llvm namespace clang { class VarDecl; @@ -34,19 +35,25 @@ class SanitizerMetadata { void operator=(const SanitizerMetadata &) = delete; CodeGenModule &CGM; + public: SanitizerMetadata(CodeGenModule &CGM); - void reportGlobalToASan(llvm::GlobalVariable *GV, const VarDecl &D, - bool IsDynInit = false); - void reportGlobalToASan(llvm::GlobalVariable *GV, SourceLocation Loc, - StringRef Name, QualType Ty, bool IsDynInit = false, - bool IsExcluded = false); + void reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D, + bool IsDynInit = false); + void reportGlobal(llvm::GlobalVariable *GV, SourceLocation Loc, + StringRef Name, QualType Ty = {}, + SanitizerMask NoSanitizeAttrMask = {}, + bool IsDynInit = false); void disableSanitizerForGlobal(llvm::GlobalVariable *GV); void disableSanitizerForInstruction(llvm::Instruction *I); + private: + void reportGlobal(llvm::GlobalVariable *GV, SourceLocation Loc, + StringRef Name, QualType Ty, bool IsDynInit, + bool IsExcluded); llvm::MDNode *getLocationMetadata(SourceLocation Loc); }; -} // end namespace CodeGen -} // end namespace clang +} // end namespace CodeGen +} // end namespace clang #endif diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 4b7b301594d77..d481d1c2857bc 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -240,6 +240,11 @@ bool ABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base, return false; } +bool ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() const { + // For compatibility with GCC, ignore empty bitfields in C++ mode. + return getContext().getLangOpts().CPlusPlus; +} + LLVM_DUMP_METHOD void ABIArgInfo::dump() const { raw_ostream &OS = llvm::errs(); OS << "(ABIArgInfo Kind="; @@ -2364,7 +2369,7 @@ class X86_64ABIInfo : public SwiftABIInfo { return false; const llvm::Triple &Triple = getTarget().getTriple(); - if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::PS4) + if (Triple.isOSDarwin() || Triple.isPS()) return false; if (Triple.isOSFreeBSD() && Triple.getOSMajorVersion() >= 10) return false; @@ -3131,7 +3136,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, unsigned idx = 0; bool UseClang11Compat = getContext().getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver11 || - getContext().getTargetInfo().getTriple().isPS4(); + getContext().getTargetInfo().getTriple().isPS(); bool IsUnion = RT->isUnionType() && !UseClang11Compat; for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); @@ -5213,8 +5218,7 @@ bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base, if (isEmptyRecord(getContext(), FT, true)) continue; - // For compatibility with GCC, ignore empty bitfields in C++ mode. - if (getContext().getLangOpts().CPlusPlus && + if (isZeroLengthBitfieldPermittedInHomogeneousAggregate() && FD->isZeroLengthBitField(getContext())) continue; @@ -5511,6 +5515,7 @@ class AArch64ABIInfo : public SwiftABIInfo { bool isHomogeneousAggregateBaseType(QualType Ty) const override; bool isHomogeneousAggregateSmallEnough(const Type *Ty, uint64_t Members) const override; + bool isZeroLengthBitfieldPermittedInHomogeneousAggregate() const override; bool isIllegalVectorType(QualType Ty) const; @@ -5970,6 +5975,16 @@ bool AArch64ABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base, return Members <= 4; } +bool AArch64ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() + const { + // AAPCS64 says that the rule for whether something is a homogeneous + // aggregate is applied to the output of the data layout decision. So + // anything that doesn't affect the data layout also does not affect + // homogeneity. In particular, zero-length bitfields don't stop a struct + // being homogeneous. + return true; +} + Address AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, QualType Ty, CodeGenFunction &CGF) const { ABIArgInfo AI = classifyArgumentType(Ty, /*IsVariadic=*/true, @@ -6339,6 +6354,7 @@ class ARMABIInfo : public SwiftABIInfo { bool isHomogeneousAggregateBaseType(QualType Ty) const override; bool isHomogeneousAggregateSmallEnough(const Type *Ty, uint64_t Members) const override; + bool isZeroLengthBitfieldPermittedInHomogeneousAggregate() const override; bool isEffectivelyAAPCS_VFP(unsigned callConvention, bool acceptHalf) const; @@ -7002,6 +7018,15 @@ bool ARMABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base, return Members <= 4; } +bool ARMABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() const { + // AAPCS32 says that the rule for whether something is a homogeneous + // aggregate is applied to the output of the data layout decision. So + // anything that doesn't affect the data layout also does not affect + // homogeneity. In particular, zero-length bitfields don't stop a struct + // being homogeneous. + return true; +} + bool ARMABIInfo::isEffectivelyAAPCS_VFP(unsigned callConvention, bool acceptHalf) const { // Give precedence to user-specified calling conventions. diff --git a/clang/lib/CrossTU/CrossTranslationUnit.cpp b/clang/lib/CrossTU/CrossTranslationUnit.cpp index 8bc478b99e4a0..8210e8d7c21bb 100644 --- a/clang/lib/CrossTU/CrossTranslationUnit.cpp +++ b/clang/lib/CrossTU/CrossTranslationUnit.cpp @@ -735,20 +735,19 @@ CrossTranslationUnitContext::importDefinitionImpl(const T *D, ASTUnit *Unit) { auto ToDeclOrError = Importer.Import(D); if (!ToDeclOrError) { - handleAllErrors(ToDeclOrError.takeError(), - [&](const ImportError &IE) { - switch (IE.Error) { - case ImportError::NameConflict: - ++NumNameConflicts; - break; - case ImportError::UnsupportedConstruct: - ++NumUnsupportedNodeFound; - break; - case ImportError::Unknown: - llvm_unreachable("Unknown import error happened."); - break; - } - }); + handleAllErrors(ToDeclOrError.takeError(), [&](const ASTImportError &IE) { + switch (IE.Error) { + case ASTImportError::NameConflict: + ++NumNameConflicts; + break; + case ASTImportError::UnsupportedConstruct: + ++NumUnsupportedNodeFound; + break; + case ASTImportError::Unknown: + llvm_unreachable("Unknown import error happened."); + break; + } + }); return llvm::make_error(index_error_code::failed_import); } auto *ToDecl = cast(*ToDeclOrError); diff --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp index 67d941c6c2ab9..b4367a0af81ee 100644 --- a/clang/lib/Driver/Compilation.cpp +++ b/clang/lib/Driver/Compilation.cpp @@ -162,7 +162,8 @@ bool Compilation::CleanupFileMap(const ArgStringMap &Files, } int Compilation::ExecuteCommand(const Command &C, - const Command *&FailingCommand) const { + const Command *&FailingCommand, + bool LogOnly) const { if ((getDriver().CCPrintOptions || getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) { raw_ostream *OS = &llvm::errs(); @@ -191,6 +192,9 @@ int Compilation::ExecuteCommand(const Command &C, C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions); } + if (LogOnly) + return 0; + std::string Error; bool ExecutionFailed; int Res = C.Execute(Redirects, &Error, &ExecutionFailed); @@ -237,7 +241,8 @@ static bool InputsOk(const Command &C, } void Compilation::ExecuteJobs(const JobList &Jobs, - FailingCommandList &FailingCommands) const { + FailingCommandList &FailingCommands, + bool LogOnly) const { // According to UNIX standard, driver need to continue compiling all the // inputs on the command line even one of them failed. // In all but CLMode, execute all the jobs unless the necessary inputs for the @@ -246,7 +251,7 @@ void Compilation::ExecuteJobs(const JobList &Jobs, if (!InputsOk(Job, FailingCommands)) continue; const Command *FailingCommand = nullptr; - if (int Res = ExecuteCommand(Job, FailingCommand)) { + if (int Res = ExecuteCommand(Job, FailingCommand, LogOnly)) { FailingCommands.push_back(std::make_pair(Res, FailingCommand)); // Bail as soon as one command fails in cl driver mode. if (TheDriver.IsCLMode()) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 94925568aec23..7b6e442d7801a 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -192,13 +192,13 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple, IntrusiveRefCntPtr VFS) : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode), SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), - CXX20HeaderType(HeaderMode_None), ModulesModeCXX20(false), - LTOMode(LTOK_None), ClangExecutable(ClangExecutable), - SysRoot(DEFAULT_SYSROOT), DriverTitle(Title), CCCPrintBindings(false), - CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false), - CCGenDiagnostics(false), CCPrintProcessStats(false), - TargetTriple(TargetTriple), Saver(Alloc), CheckInputsExist(true), - ProbePrecompiled(true), GenReproducer(false), + Offload(OffloadHostDevice), CXX20HeaderType(HeaderMode_None), + ModulesModeCXX20(false), LTOMode(LTOK_None), + ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT), + DriverTitle(Title), CCCPrintBindings(false), CCPrintOptions(false), + CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false), + CCPrintProcessStats(false), TargetTriple(TargetTriple), Saver(Alloc), + CheckInputsExist(true), ProbePrecompiled(true), SuppressMissingInputWarning(false) { // Provide a sane fallback if no VFS is specified. if (!this->VFS) @@ -974,7 +974,7 @@ bool Driver::loadConfigFile() { if (llvm::sys::fs::make_absolute(CfgDir).value() != 0) SystemConfigDir.clear(); else - SystemConfigDir = std::string(CfgDir.begin(), CfgDir.end()); + SystemConfigDir = static_cast(CfgDir); } } if (CLOptions->hasArg(options::OPT_config_user_dir_EQ)) { @@ -985,7 +985,7 @@ bool Driver::loadConfigFile() { if (llvm::sys::fs::make_absolute(CfgDir).value() != 0) UserConfigDir.clear(); else - UserConfigDir = std::string(CfgDir.begin(), CfgDir.end()); + UserConfigDir = static_cast(CfgDir); } } } @@ -1217,9 +1217,6 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { CCCPrintBindings = Args.hasArg(options::OPT_ccc_print_bindings); if (const Arg *A = Args.getLastArg(options::OPT_ccc_gcc_name)) CCCGenericGCCName = A->getValue(); - GenReproducer = Args.hasFlag(options::OPT_gen_reproducer, - options::OPT_fno_crash_diagnostics, - !!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")); // Process -fproc-stat-report options. if (const Arg *A = Args.getLastArg(options::OPT_fproc_stat_report_EQ)) { @@ -1240,11 +1237,19 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { T.setObjectFormat(llvm::Triple::COFF); TargetTriple = T.str(); } else if (IsDXCMode()) { - // clang-dxc target is build from target_profile option. - // Just set OS to shader model to select HLSLToolChain. - llvm::Triple T(TargetTriple); - T.setOS(llvm::Triple::ShaderModel); - TargetTriple = T.str(); + // Build TargetTriple from target_profile option for clang-dxc. + if (const Arg *A = Args.getLastArg(options::OPT_target_profile)) { + StringRef TargetProfile = A->getValue(); + if (auto Triple = + toolchains::HLSLToolChain::parseTargetProfile(TargetProfile)) + TargetTriple = Triple.getValue(); + else + Diag(diag::err_drv_invalid_directx_shader_module) << TargetProfile; + + A->claim(); + } else { + Diag(diag::err_drv_dxc_missing_target_profile); + } } if (const Arg *A = Args.getLastArg(options::OPT_target)) @@ -1280,6 +1285,17 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { .Default(SaveTempsCwd); } + if (const Arg *A = Args.getLastArg(options::OPT_offload_host_only, + options::OPT_offload_device_only, + options::OPT_offload_host_device)) { + if (A->getOption().matches(options::OPT_offload_host_only)) + Offload = OffloadHost; + else if (A->getOption().matches(options::OPT_offload_device_only)) + Offload = OffloadDevice; + else + Offload = OffloadHostDevice; + } + setLTOMode(Args); // Process -fembed-bitcode= flags. @@ -1685,6 +1701,19 @@ void Driver::setUpResponseFiles(Compilation &C, Command &Cmd) { int Driver::ExecuteCompilation( Compilation &C, SmallVectorImpl> &FailingCommands) { + if (C.getArgs().hasArg(options::OPT_fdriver_only)) { + if (C.getArgs().hasArg(options::OPT_v)) + C.getJobs().Print(llvm::errs(), "\n", true); + + C.ExecuteJobs(C.getJobs(), FailingCommands, /*LogOnly=*/true); + + // If there were errors building the compilation, quit now. + if (!FailingCommands.empty() || Diags.hasErrorOccurred()) + return 1; + + return 0; + } + // Just print if -### was present. if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) { C.getJobs().Print(llvm::errs(), "\n", true); @@ -2006,6 +2035,13 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { return false; } + if (C.getArgs().hasArg(options::OPT_print_diagnostic_options)) { + std::vector Flags = DiagnosticIDs::getDiagnosticFlags(); + for (std::size_t I = 0; I != Flags.size(); I += 2) + llvm::outs() << " " << Flags[I] << "\n " << Flags[I + 1] << "\n\n"; + return false; + } + // FIXME: The following handlers should use a callback mechanism, we don't // know what the client would like to do. if (Arg *A = C.getArgs().getLastArg(options::OPT_print_file_name_EQ)) { @@ -2909,15 +2945,8 @@ class OffloadingActionBuilder final { ? C.getSingleOffloadToolChain() : C.getSingleOffloadToolChain()); - Arg *PartialCompilationArg = Args.getLastArg( - options::OPT_offload_host_only, options::OPT_offload_device_only, - options::OPT_offload_host_device); - CompileHostOnly = - PartialCompilationArg && PartialCompilationArg->getOption().matches( - options::OPT_offload_host_only); - CompileDeviceOnly = - PartialCompilationArg && PartialCompilationArg->getOption().matches( - options::OPT_offload_device_only); + CompileHostOnly = C.getDriver().offloadHostOnly(); + CompileDeviceOnly = C.getDriver().offloadDeviceOnly(); EmitLLVM = Args.getLastArg(options::OPT_emit_llvm); EmitAsm = Args.getLastArg(options::OPT_S); FixedCUID = Args.getLastArgValue(options::OPT_cuid_EQ); @@ -4246,11 +4275,6 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, // Claim ignored clang-cl options. Args.ClaimAllArgs(options::OPT_cl_ignored_Group); - - // Claim --offload-host-only and --offload-compile-host-device, which may be - // passed to non-CUDA compilations and should not trigger warnings there. - Args.ClaimAllArgs(options::OPT_offload_host_only); - Args.ClaimAllArgs(options::OPT_offload_host_device); } /// Returns the canonical name for the offloading architecture when using a HIP @@ -4369,18 +4393,10 @@ Action *Driver::BuildOffloadingActions(Compilation &C, llvm::opt::DerivedArgList &Args, const InputTy &Input, Action *HostAction) const { - const Arg *Mode = Args.getLastArg(options::OPT_offload_host_only, - options::OPT_offload_device_only, - options::OPT_offload_host_device); - const bool HostOnly = - Mode && Mode->getOption().matches(options::OPT_offload_host_only); - const bool DeviceOnly = - Mode && Mode->getOption().matches(options::OPT_offload_device_only); - // Don't build offloading actions if explicitly disabled or we do not have a // valid source input and compile action to embed it in. If preprocessing only // ignore embedding. - if (HostOnly || !types::isSrcFile(Input.first) || + if (offloadHostOnly() || !types::isSrcFile(Input.first) || !(isa(HostAction) || getFinalPhase(Args) == phases::Preprocess)) return HostAction; @@ -4468,7 +4484,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C, } } - if (DeviceOnly) + if (offloadDeviceOnly()) return C.MakeAction(DDeps, types::TY_Nothing); Action *OffloadPackager = @@ -4750,6 +4766,8 @@ void Driver::BuildJobs(Compilation &C) const { C.getArgs().hasArg(options::OPT_Qunused_arguments)) return; + // Claim -fdriver-only here. + (void)C.getArgs().hasArg(options::OPT_fdriver_only); // Claim -### here. (void)C.getArgs().hasArg(options::OPT__HASH_HASH_HASH); @@ -5398,8 +5416,9 @@ InputInfoList Driver::BuildJobsForActionNoCache( // action. std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix( A->getOffloadingDeviceKind(), TC->getTriple().normalize(), - /*CreatePrefixForHost=*/!!A->getOffloadingHostActiveKinds() && - !AtTopLevel); + /*CreatePrefixForHost=*/isa(A) || + !(A->getOffloadingHostActiveKinds() == Action::OFK_None || + AtTopLevel)); if (isa(JA)) { if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) BaseInput = FinalOutput->getValue(); @@ -5636,7 +5655,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, bool IsHIPNoRDC = JA.getOffloadingDeviceKind() == Action::OFK_HIP && !C.getArgs().hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false); - if (IsHIPNoRDC) { + bool UseOutExtension = IsHIPNoRDC || isa(JA); + if (UseOutExtension) { Output = BaseName; llvm::sys::path::replace_extension(Output, ""); } @@ -5645,7 +5665,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, Output += "-"; Output.append(BoundArch); } - if (IsHIPNoRDC) + if (UseOutExtension) Output += ".out"; NamedOutput = C.getArgs().MakeArgString(Output.c_str()); } diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index b63c6e4637060..edb1bfbe9bdf8 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -45,7 +45,8 @@ static const SanitizerMask SupportsCoverage = SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress | SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap | - SanitizerKind::Memory | SanitizerKind::KernelMemory | SanitizerKind::Leak | + SanitizerKind::MemtagGlobals | SanitizerKind::Memory | + SanitizerKind::KernelMemory | SanitizerKind::Leak | SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds | SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | SanitizerKind::DataFlow | SanitizerKind::Fuzzer | @@ -73,7 +74,8 @@ static const SanitizerMask CFIClasses = SanitizerKind::CFIUnrelatedCast; static const SanitizerMask CompatibleWithMinimalRuntime = TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack | - SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap; + SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap | + SanitizerKind::MemtagGlobals; enum CoverageFeature { CoverageFunc = 1 << 0, @@ -168,14 +170,14 @@ static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds, else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors) // If cfi_ignorelist.txt cannot be found in the resource dir, driver // should fail. - D.Diag(clang::diag::err_drv_no_such_file) << Path; + D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) << Path; } validateSpecialCaseListFormat( D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors); } -/// Parse -f(no-)?sanitize-(coverage-)?(white|ignore)list argument's values, +/// Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values, /// diagnosing any invalid file paths and validating special case list format. static void parseSpecialCaseListArg(const Driver &D, const llvm::opt::ArgList &Args, @@ -185,7 +187,7 @@ static void parseSpecialCaseListArg(const Driver &D, unsigned MalformedSCLErrorDiagID, bool DiagnoseErrors) { for (const auto *Arg : Args) { - // Match -fsanitize-(coverage-)?(white|ignore)list. + // Match -fsanitize-(coverage-)?(allow|ignore)list. if (Arg->getOption().matches(SCLOptionID)) { Arg->claim(); std::string SCLPath = Arg->getValue(); @@ -788,7 +790,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, CoverageFeatures |= CoverageFunc; } - // Parse -fsanitize-coverage-(ignore|white)list options if coverage enabled. + // Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled. // This also validates special case lists format. // Here, OptSpecifier() acts as a never-matching command-line argument. // So, there is no way to clear coverage lists but you can append to them. diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp index 123d92664495e..b450f335b5a2a 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -863,10 +863,10 @@ void ROCMToolChain::addClangTargetOptions( DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt, FastRelaxedMath, CorrectSqrt, ABIVer, false)); - llvm::for_each(BCLibs, [&](StringRef BCFile) { + for (StringRef BCFile : BCLibs) { CC1Args.push_back("-mlink-builtin-bitcode"); CC1Args.push_back(DriverArgs.MakeArgString(BCFile)); - }); + } } bool RocmInstallationDetector::checkCommonBitcodeLibs( diff --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp index fa9b8b64029d5..efcd565b510b7 100644 --- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp @@ -125,9 +125,8 @@ const char *AMDGCN::OpenMPLinker::constructLLVMLinkCommand( // the device-libs bitcode through that on the way to this llvm-link SmallVector BCLibs = AMDGPUOpenMPTC.getCommonDeviceLibNames(Args, SubArchName.str()); - llvm::for_each(BCLibs, [&](StringRef BCFile) { + for (StringRef BCFile : BCLibs) CmdArgs.push_back(Args.MakeArgString(BCFile)); - }); } } diff --git a/clang/lib/Driver/ToolChains/AVR.cpp b/clang/lib/Driver/ToolChains/AVR.cpp index 466fc3b20569e..54a9168788585 100644 --- a/clang/lib/Driver/ToolChains/AVR.cpp +++ b/clang/lib/Driver/ToolChains/AVR.cpp @@ -375,8 +375,7 @@ AVRToolChain::AVRToolChain(const Driver &D, const llvm::Triple &Triple, // Only add default libraries if the user hasn't explicitly opted out. if (!Args.hasArg(options::OPT_nostdlib) && - !Args.hasArg(options::OPT_nodefaultlibs) && - GCCInstallation.isValid()) { + !Args.hasArg(options::OPT_nodefaultlibs) && GCCInstallation.isValid()) { GCCInstallPath = GCCInstallation.getInstallPath(); std::string GCCParentPath(GCCInstallation.getParentLibPath()); getProgramPaths().push_back(GCCParentPath + "/../bin"); @@ -429,9 +428,14 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA, // Compute information about the target AVR. std::string CPU = getCPUName(D, Args, getToolChain().getTriple()); llvm::Optional FamilyName = GetMCUFamilyName(CPU); + llvm::Optional AVRLibcRoot = TC.findAVRLibcInstallation(); llvm::Optional SectionAddressData = GetMCUSectionAddressData(CPU); - std::string Linker = getToolChain().GetProgramPath(getShortName()); + // Compute the linker program path, and use GNU "avr-ld" as default. + const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ); + std::string Linker = A ? getToolChain().GetLinkerPath(nullptr) + : getToolChain().GetProgramPath(getShortName()); + ArgStringList CmdArgs; AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); @@ -450,17 +454,11 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (!CPU.empty()) { - Optional FamilyName = GetMCUFamilyName(CPU); - Optional AVRLibcRoot = TC.findAVRLibcInstallation(); - if (!FamilyName) { // We do not have an entry for this CPU in the family // mapping table yet. D.Diag(diag::warn_drv_avr_family_linking_stdlibs_not_implemented) << CPU; - } else if (TC.getGCCInstallPath().empty()) { - // We can not link since there is no avr-ld. - D.Diag(diag::warn_drv_avr_gcc_not_found); } else if (!AVRLibcRoot) { // No avr-libc found and so no runtime linked. D.Diag(diag::warn_drv_avr_libc_not_found); @@ -473,7 +471,6 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA, LinkStdlib = true; } } - if (!LinkStdlib) D.Diag(diag::warn_drv_avr_stdlib_not_linked); } @@ -508,11 +505,15 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("--end-group"); + // Add user specified linker script. + Args.AddAllArgs(CmdArgs, options::OPT_T); + // Specify the family name as the emulation mode to use. // This is almost always required because otherwise avr-ld // will assume 'avr2' and warn about the program being larger // than the bare minimum supports. - CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName)); + if (Linker.find("avr-ld") != std::string::npos) + CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName)); } C.addCommand(std::make_unique( diff --git a/clang/lib/Driver/ToolChains/Arch/VE.h b/clang/lib/Driver/ToolChains/Arch/VE.h index 531433534914c..c47a41df25bc4 100644 --- a/clang/lib/Driver/ToolChains/Arch/VE.h +++ b/clang/lib/Driver/ToolChains/Arch/VE.h @@ -24,7 +24,7 @@ void getVETargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, std::vector &Features); } // end namespace ve -} // namespace tools +} // end namespace tools } // end namespace driver } // end namespace clang diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp index 993e13fdac307..cd7c014faa5e0 100644 --- a/clang/lib/Driver/ToolChains/Arch/X86.cpp +++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp @@ -246,4 +246,20 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple, Name = Name.substr(3); Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name)); } + + // Enable/disable straight line speculation hardening. + if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) { + StringRef Scope = A->getValue(); + if (Scope == "all") { + Features.push_back("+harden-sls-ijmp"); + Features.push_back("+harden-sls-ret"); + } else if (Scope == "return") { + Features.push_back("+harden-sls-ret"); + } else if (Scope == "indirect-jmp") { + Features.push_back("+harden-sls-ijmp"); + } else if (Scope != "none") { + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << Scope; + } + } } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 5106c0e327b87..0f251614eac22 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -38,6 +38,7 @@ #include "clang/Driver/SanitizerArgs.h" #include "clang/Driver/Types.h" #include "clang/Driver/XRayArgs.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Config/llvm-config.h" #include "llvm/Option/ArgList.h" @@ -2405,7 +2406,8 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename, if (!CompilationDatabase) { std::error_code EC; auto File = std::make_unique( - Filename, EC, llvm::sys::fs::OF_TextWithCRLF); + Filename, EC, + llvm::sys::fs::OF_TextWithCRLF | llvm::sys::fs::OF_Append); if (EC) { D.Diag(clang::diag::err_drv_compilationdatabase) << Filename << EC.message(); @@ -2431,6 +2433,7 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename, CDB << ", \"" << escape(Buf) << "\""; } CDB << ", \"" << escape(Input.getFilename()) << "\""; + CDB << ", \"-o\", \"" << escape(Output.getFilename()) << "\""; for (auto &A: Args) { auto &O = A->getOption(); // Skip language selection, which is positional. @@ -2444,6 +2447,9 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename, // Skip inputs. if (O.getKind() == Option::InputClass) continue; + // Skip output. + if (O.getID() == options::OPT_o) + continue; // All other arguments are quoted and appended. ArgStringList ASL; A->render(Args, ASL); @@ -2517,6 +2523,8 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, DefaultIncrementalLinkerCompatible)) CmdArgs.push_back("-mincremental-linker-compatible"); + Args.AddLastArg(CmdArgs, options::OPT_femit_dwarf_unwind_EQ); + // If you add more args here, also add them to the block below that // starts with "// If CollectArgsForIntegratedAssembler() isn't called below". @@ -3157,12 +3165,6 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs, const llvm::Triple &Triple, const InputInfo &Input) { - // Enable region store model by default. - CmdArgs.push_back("-analyzer-store=region"); - - // Treat blocks as analysis entry points. - CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks"); - // Add default argument set. if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) { CmdArgs.push_back("-analyzer-checker=core"); @@ -3477,13 +3479,16 @@ static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs, static void RenderHLSLOptions(const ArgList &Args, ArgStringList &CmdArgs, types::ID InputType) { - const unsigned ForwardedArguments[] = {options::OPT_dxil_validator_version, - options::OPT_S, options::OPT_emit_llvm, - options::OPT_disable_llvm_passes}; + const unsigned ForwardedArguments[] = { + options::OPT_dxil_validator_version, options::OPT_D, options::OPT_S, + options::OPT_emit_llvm, options::OPT_disable_llvm_passes}; for (const auto &Arg : ForwardedArguments) if (const auto *A = Args.getLastArg(Arg)) A->renderAsInput(Args, CmdArgs); + // Add the default headers if dxc_no_stdinc is not set. + if (!Args.hasArg(options::OPT_dxc_no_stdinc)) + CmdArgs.push_back("-finclude-default-header"); } static void RenderARCMigrateToolOptions(const Driver &D, const ArgList &Args, @@ -3596,6 +3601,11 @@ static void RenderBuiltinOptions(const ToolChain &TC, const llvm::Triple &T, } bool Driver::getDefaultModuleCachePath(SmallVectorImpl &Result) { + if (const char *Str = std::getenv("CLANG_MODULE_CACHE_PATH")) { + Twine Path{Str}; + Path.toVector(Result); + return Path.getSingleStringRef() != ""; + } if (llvm::sys::path::cache_directory(Result)) { llvm::sys::path::append(Result, "clang"); llvm::sys::path::append(Result, "ModuleCache"); @@ -3627,12 +3637,6 @@ static void RenderModulesOptions(Compilation &C, const Driver &D, HaveModules = true; } - if (Args.hasFlag(options::OPT_fcxx_modules, options::OPT_fno_cxx_modules, - false)) { - CmdArgs.push_back("-fcxx-modules"); - HaveModules = true; - } - // -fmodule-maps enables implicit reading of module map files. By default, // this is enabled if we are using Clang's flavor of precompiled modules. if (Args.hasFlag(options::OPT_fimplicit_module_maps, @@ -4619,6 +4623,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } Args.ClaimAllArgs(options::OPT_Wa_COMMA); Args.ClaimAllArgs(options::OPT_Xassembler); + Args.ClaimAllArgs(options::OPT_femit_dwarf_unwind_EQ); } if (isa(JA)) { @@ -5971,6 +5976,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, << A->getAsString(Args) << TripleStr; } + if (const Arg *A = + Args.getLastArg(options::OPT_mdefault_visibility_export_mapping_EQ)) { + if (Triple.isOSAIX()) + A->render(Args, CmdArgs); + else + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getAsString(Args) << TripleStr; + } if (Args.hasFlag(options::OPT_fvisibility_inlines_hidden, options::OPT_fno_visibility_inlines_hidden, false)) @@ -7458,6 +7471,12 @@ static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) { EH.NoUnwindC = true; } + if (Args.hasArg(options::OPT__SLASH_kernel)) { + EH.Synch = false; + EH.NoUnwindC = false; + EH.Asynch = false; + } + return EH; } @@ -7602,6 +7621,27 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, CmdArgs.push_back("-fno-wchar"); } + if (Args.hasArg(options::OPT__SLASH_kernel)) { + llvm::Triple::ArchType Arch = getToolChain().getArch(); + std::vector Values = + Args.getAllArgValues(options::OPT__SLASH_arch); + if (!Values.empty()) { + llvm::SmallSet SupportedArches; + if (Arch == llvm::Triple::x86) + SupportedArches.insert("IA32"); + + for (auto &V : Values) + if (!SupportedArches.contains(V)) + D.Diag(diag::err_drv_argument_not_allowed_with) + << std::string("/arch:").append(V) << "/kernel"; + } + + CmdArgs.push_back("-fno-rtti"); + if (Args.hasFlag(options::OPT__SLASH_GR, options::OPT__SLASH_GR_, false)) + D.Diag(diag::err_drv_argument_not_allowed_with) << "/GR" + << "/kernel"; + } + Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg); Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb); if (MostGeneralArg && BestCaseArg) @@ -7671,6 +7711,9 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, CmdArgs.push_back("msvc"); } + if (Args.hasArg(options::OPT__SLASH_kernel)) + CmdArgs.push_back("-fms-kernel"); + if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) { StringRef GuardArgs = A->getValue(); // The only valid options are "cf", "cf,nochecks", "cf-", "ehcont" and diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 45add8ad94a5f..accf79f767249 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -143,28 +143,16 @@ void tools::handleTargetFeaturesGroup(const ArgList &Args, } } -std::vector -tools::unifyTargetFeatures(const std::vector &Features) { - std::vector UnifiedFeatures; - // Find the last of each feature. - llvm::StringMap LastOpt; - for (unsigned I = 0, N = Features.size(); I < N; ++I) { - StringRef Name = Features[I]; - assert(Name[0] == '-' || Name[0] == '+'); - LastOpt[Name.drop_front(1)] = I; - } - - for (unsigned I = 0, N = Features.size(); I < N; ++I) { - // If this feature was overridden, ignore it. - StringRef Name = Features[I]; - llvm::StringMap::iterator LastI = LastOpt.find(Name.drop_front(1)); - assert(LastI != LastOpt.end()); - unsigned Last = LastI->second; - if (Last != I) - continue; - - UnifiedFeatures.push_back(Name); +SmallVector +tools::unifyTargetFeatures(ArrayRef Features) { + // Only add a feature if it hasn't been seen before starting from the end. + SmallVector UnifiedFeatures; + llvm::DenseSet UsedFeatures; + for (StringRef Feature : llvm::reverse(Features)) { + if (UsedFeatures.insert(Feature.drop_front()).second) + UnifiedFeatures.insert(UnifiedFeatures.begin(), Feature); } + return UnifiedFeatures; } @@ -559,6 +547,9 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, CmdArgs.push_back( Args.MakeArgString("-plugin-opt=jobs=" + Twine(Parallelism))); + if (!CLANG_ENABLE_OPAQUE_POINTERS_INTERNAL) + CmdArgs.push_back(Args.MakeArgString("-plugin-opt=no-opaque-pointers")); + // If an explicit debugger tuning argument appeared, pass it along. if (Arg *A = Args.getLastArg(options::OPT_gTune_Group, options::OPT_ggdbN_Group)) { @@ -835,6 +826,12 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC, TC.getTriple().isOSNetBSD() || TC.getTriple().isOSOpenBSD()) CmdArgs.push_back("-lexecinfo"); + // There is no libresolv on Android, FreeBSD, OpenBSD, etc. On musl + // libresolv.a, even if exists, is an empty archive to satisfy POSIX -lresolv + // requirement. + if (TC.getTriple().isOSLinux() && !TC.getTriple().isAndroid() && + !TC.getTriple().isMusl()) + CmdArgs.push_back("-lresolv"); } static void @@ -1782,8 +1779,13 @@ bool tools::GetSDLFromOffloadArchive( for (auto LPath : LibraryPaths) { ArchiveOfBundles.clear(); - AOBFileNames.push_back(Twine(LPath + "/libdevice/lib" + Lib + ".a").str()); - AOBFileNames.push_back(Twine(LPath + "/lib" + Lib + ".a").str()); + llvm::Triple Triple(D.getTargetTriple()); + bool IsMSVC = Triple.isWindowsMSVCEnvironment(); + for (auto Prefix : {"/libdevice/", "/"}) { + if (IsMSVC) + AOBFileNames.push_back(Twine(LPath + Prefix + Lib + ".lib").str()); + AOBFileNames.push_back(Twine(LPath + Prefix + "lib" + Lib + ".a").str()); + } for (auto AOB : AOBFileNames) { if (llvm::sys::fs::exists(AOB)) { diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index b0238612234c5..3052cbf1a3c38 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -173,8 +173,7 @@ void handleTargetFeaturesGroup(const llvm::opt::ArgList &Args, llvm::opt::OptSpecifier Group); /// If there are multiple +xxx or -xxx features, keep the last one. -std::vector -unifyTargetFeatures(const std::vector &Features); +SmallVector unifyTargetFeatures(ArrayRef Features); /// Handles the -save-stats option and returns the filename to save statistics /// to. diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index b0d72c74dcb74..665a3894302ab 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1349,7 +1349,6 @@ void Darwin::addProfileRTLibs(const ArgList &Args, addExportedSymbol(CmdArgs, "___llvm_profile_filename"); addExportedSymbol(CmdArgs, "___llvm_profile_raw_version"); } - addExportedSymbol(CmdArgs, "_lprofDirMode"); } // Align __llvm_prf_{cnts,data} sections to the maximum expected page diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 63e3c080a7e7f..ab9287d880a95 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -19,6 +19,14 @@ using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; +/// Add -x lang to \p CmdArgs for \p Input. +static void addDashXForInput(const ArgList &Args, const InputInfo &Input, + ArgStringList &CmdArgs) { + CmdArgs.push_back("-x"); + // Map the driver type to the frontend type. + CmdArgs.push_back(types::getTypeName(Input.getType())); +} + void Flang::AddFortranDialectOptions(const ArgList &Args, ArgStringList &CmdArgs) const { Args.AddAllArgs( @@ -126,6 +134,9 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA, } assert(Input.isFilename() && "Invalid input."); + + addDashXForInput(Args, Input, CmdArgs); + CmdArgs.push_back(Input.getFilename()); const auto& D = C.getDriver(); diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index b3d414f2dc78f..f4caa5e10609a 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -2130,17 +2130,31 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( // and gcc-toolsets. if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux && D.getVFS().exists("/opt/rh")) { - Prefixes.push_back("/opt/rh/gcc-toolset-11/root/usr"); - Prefixes.push_back("/opt/rh/gcc-toolset-10/root/usr"); - Prefixes.push_back("/opt/rh/devtoolset-11/root/usr"); - Prefixes.push_back("/opt/rh/devtoolset-10/root/usr"); - Prefixes.push_back("/opt/rh/devtoolset-9/root/usr"); - Prefixes.push_back("/opt/rh/devtoolset-8/root/usr"); - Prefixes.push_back("/opt/rh/devtoolset-7/root/usr"); - Prefixes.push_back("/opt/rh/devtoolset-6/root/usr"); - Prefixes.push_back("/opt/rh/devtoolset-4/root/usr"); - Prefixes.push_back("/opt/rh/devtoolset-3/root/usr"); - Prefixes.push_back("/opt/rh/devtoolset-2/root/usr"); + // Find the directory in /opt/rh/ starting with gcc-toolset-* or + // devtoolset-* with the highest version number and add that + // one to our prefixes. + std::string ChosenToolsetDir; + unsigned ChosenToolsetVersion = 0; + std::error_code EC; + for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin("/opt/rh", EC), + LE; + !EC && LI != LE; LI = LI.increment(EC)) { + StringRef ToolsetDir = llvm::sys::path::filename(LI->path()); + unsigned ToolsetVersion; + if ((!ToolsetDir.startswith("gcc-toolset-") && + !ToolsetDir.startswith("devtoolset-")) || + ToolsetDir.substr(ToolsetDir.rfind('-') + 1) + .getAsInteger(10, ToolsetVersion)) + continue; + + if (ToolsetVersion > ChosenToolsetVersion) { + ChosenToolsetVersion = ToolsetVersion; + ChosenToolsetDir = "/opt/rh/" + ToolsetDir.str(); + } + } + + if (ChosenToolsetVersion > 0) + Prefixes.push_back(ChosenToolsetDir + "/root/usr"); } // Fall back to /usr which is used by most non-Solaris systems. diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp index f672d2a108cc9..0111477430eb7 100644 --- a/clang/lib/Driver/ToolChains/HIPAMD.cpp +++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp @@ -147,6 +147,9 @@ void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA, addLinkerCompressDebugSectionsOption(TC, Args, LldArgs); + for (auto *Arg : Args.filtered(options::OPT_Xoffload_linker)) + LldArgs.push_back(Arg->getValue(1)); + LldArgs.append({"-o", Output.getFilename()}); for (auto Input : Inputs) LldArgs.push_back(Input.getFilename()); @@ -243,11 +246,11 @@ void HIPAMDToolChain::addClangTargetOptions( CC1Args.push_back("-fapply-global-visibility-to-externs"); } - llvm::for_each(getHIPDeviceLibs(DriverArgs), [&](auto BCFile) { + for (auto BCFile : getHIPDeviceLibs(DriverArgs)) { CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode" : "-mlink-bitcode-file"); CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path)); - }); + } } llvm::opt::DerivedArgList * diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp index b62395b168ea4..c2b55fdde4b4c 100644 --- a/clang/lib/Driver/ToolChains/HLSL.cpp +++ b/clang/lib/Driver/ToolChains/HLSL.cpp @@ -64,12 +64,12 @@ bool isLegalShaderModel(Triple &T) { return false; } -std::string tryParseProfile(StringRef Profile) { +llvm::Optional tryParseProfile(StringRef Profile) { // [ps|vs|gs|hs|ds|cs|ms|as]_[major]_[minor] SmallVector Parts; Profile.split(Parts, "_"); if (Parts.size() != 3) - return ""; + return NoneType(); Triple::EnvironmentType Kind = StringSwitch(Parts[0]) @@ -84,17 +84,17 @@ std::string tryParseProfile(StringRef Profile) { .Case("as", Triple::EnvironmentType::Amplification) .Default(Triple::EnvironmentType::UnknownEnvironment); if (Kind == Triple::EnvironmentType::UnknownEnvironment) - return ""; + return NoneType(); unsigned long long Major = 0; if (llvm::getAsUnsignedInteger(Parts[1], 0, Major)) - return ""; + return NoneType(); unsigned long long Minor = 0; if (Parts[2] == "x" && Kind == Triple::EnvironmentType::Library) Minor = OfflineLibMinor; else if (llvm::getAsUnsignedInteger(Parts[2], 0, Minor)) - return ""; + return NoneType(); // dxil-unknown-shadermodel-hull llvm::Triple T; @@ -105,7 +105,7 @@ std::string tryParseProfile(StringRef Profile) { if (isLegalShaderModel(T)) return T.getTriple(); else - return ""; + return NoneType(); } bool isLegalValidatorVersion(StringRef ValVersionStr, const Driver &D) { @@ -138,21 +138,10 @@ HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : ToolChain(D, Triple, Args) {} -std::string -HLSLToolChain::ComputeEffectiveClangTriple(const ArgList &Args, - types::ID InputType) const { - if (Arg *A = Args.getLastArg(options::OPT_target_profile)) { - StringRef Profile = A->getValue(); - std::string Triple = tryParseProfile(Profile); - if (Triple == "") { - getDriver().Diag(diag::err_drv_invalid_directx_shader_module) << Profile; - Triple = ToolChain::ComputeEffectiveClangTriple(Args, InputType); - } - A->claim(); - return Triple; - } else { - return ToolChain::ComputeEffectiveClangTriple(Args, InputType); - } +llvm::Optional +clang::driver::toolchains::HLSLToolChain::parseTargetProfile( + StringRef TargetProfile) { + return tryParseProfile(TargetProfile); } DerivedArgList * diff --git a/clang/lib/Driver/ToolChains/HLSL.h b/clang/lib/Driver/ToolChains/HLSL.h index 7774db3762dd3..5573b0cc69e25 100644 --- a/clang/lib/Driver/ToolChains/HLSL.h +++ b/clang/lib/Driver/ToolChains/HLSL.h @@ -29,8 +29,8 @@ class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain { llvm::opt::DerivedArgList * TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const override; - std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args, - types::ID InputType) const override; + static llvm::Optional + parseTargetProfile(StringRef TargetProfile); }; } // end namespace toolchains diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index 43b2bf06e8b43..4309b10603465 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -124,6 +124,8 @@ std::string Linux::getMultiarchTriple(const Driver &D, return "powerpc64-linux-gnu"; case llvm::Triple::ppc64le: return "powerpc64le-linux-gnu"; + case llvm::Triple::riscv64: + return "riscv64-linux-gnu"; case llvm::Triple::sparc: return "sparc-linux-gnu"; case llvm::Triple::sparcv9: diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index 0ba034f4c9a7a..c6e8bd04455e2 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -449,8 +449,8 @@ bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const { // All non-x86_32 Windows targets require unwind tables. However, LLVM // doesn't know how to generate them for all targets, so only enable // the ones that are actually implemented. - return getArch() == llvm::Triple::x86_64 || - getArch() == llvm::Triple::aarch64; + return getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm || + getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64; } bool MSVCToolChain::isPICDefault() const { diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp index ceeaa79bc2021..43466ef2b40f5 100644 --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -478,8 +478,8 @@ bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const { if (ExceptionArg && ExceptionArg->getOption().matches(options::OPT_fseh_exceptions)) return true; - return getArch() == llvm::Triple::x86_64 || - getArch() == llvm::Triple::aarch64; + return getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm || + getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64; } bool toolchains::MinGW::isPICDefault() const { @@ -495,7 +495,8 @@ bool toolchains::MinGW::isPICDefaultForced() const { return true; } llvm::ExceptionHandling toolchains::MinGW::GetExceptionModel(const ArgList &Args) const { - if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64) + if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64 || + getArch() == llvm::Triple::arm || getArch() == llvm::Triple::thumb) return llvm::ExceptionHandling::WinEH; return llvm::ExceptionHandling::DwarfCFI; } diff --git a/clang/lib/Driver/ToolChains/ZOS.h b/clang/lib/Driver/ToolChains/ZOS.h index 50bff09935613..53138306fd410 100644 --- a/clang/lib/Driver/ToolChains/ZOS.h +++ b/clang/lib/Driver/ToolChains/ZOS.h @@ -30,6 +30,8 @@ class LLVM_LIBRARY_VISIBILITY ZOS : public ToolChain { bool IsIntegratedAssemblerDefault() const override { return true; } + unsigned GetDefaultDwarfVersion() const override { return 4; } + void addClangTargetOptions( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind DeviceOffloadingKind) const override; diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp index a7b0a1ac98a78..bffa66c2d9448 100644 --- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp +++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp @@ -199,11 +199,11 @@ struct LocationFileChecker { // Try to reduce the include name the same way we tried to include it. bool IsQuoted = false; if (auto IncludeName = getRelativeIncludeName(CI, FileName, &IsQuoted)) - if (llvm::find_if(KnownFiles, - [&IsQuoted, &IncludeName](const auto &KnownFile) { - return KnownFile.first.equals(*IncludeName) && - KnownFile.second == IsQuoted; - }) != KnownFiles.end()) { + if (llvm::any_of(KnownFiles, + [&IsQuoted, &IncludeName](const auto &KnownFile) { + return KnownFile.first.equals(*IncludeName) && + KnownFile.second == IsQuoted; + })) { KnownFileEntries.insert(File); return true; } diff --git a/clang/lib/Format/BreakableToken.cpp b/clang/lib/Format/BreakableToken.cpp index 6ae112b86ebb6..db82018a4c83c 100644 --- a/clang/lib/Format/BreakableToken.cpp +++ b/clang/lib/Format/BreakableToken.cpp @@ -705,11 +705,9 @@ void BreakableBlockComment::adaptStartOfLine( // contain a trailing whitespace. Prefix = Prefix.substr(0, 1); } - } else { - if (ContentColumn[LineIndex] == 1) { - // This line starts immediately after the decorating *. - Prefix = Prefix.substr(0, 1); - } + } else if (ContentColumn[LineIndex] == 1) { + // This line starts immediately after the decorating *. + Prefix = Prefix.substr(0, 1); } // This is the offset of the end of the last line relative to the start of the // token text in the token. diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 65a391dde3d57..df1aa9da16e39 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1833,7 +1833,9 @@ namespace { class BracesInserter : public TokenAnalyzer { public: BracesInserter(const Environment &Env, const FormatStyle &Style) - : TokenAnalyzer(Env, Style) {} + : TokenAnalyzer(Env, Style) { + this->Style.RemoveBracesLLVM = false; + } std::pair analyze(TokenAnnotator &Annotator, @@ -1875,7 +1877,9 @@ class BracesInserter : public TokenAnalyzer { class BracesRemover : public TokenAnalyzer { public: BracesRemover(const Environment &Env, const FormatStyle &Style) - : TokenAnalyzer(Env, Style) {} + : TokenAnalyzer(Env, Style) { + this->Style.InsertBraces = false; + } std::pair analyze(TokenAnnotator &Annotator, diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 9a5d85cead889..77a59d8585091 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -395,7 +395,7 @@ void UnwrappedLineParser::parseFile() { if (Style.Language == FormatStyle::LK_TextProto) parseBracedList(); else - parseLevel(/*OpeningBrace=*/nullptr, /*CanContainBracedList=*/true); + parseLevel(); // Make sure to format the remaining tokens. // // LK_TextProto is special since its top-level is parsed as the body of a @@ -469,20 +469,26 @@ bool UnwrappedLineParser::precededByCommentOrPPDirective() const { /// \param CanContainBracedList If the content can contain (at any level) a /// braced list. /// \param NextLBracesType The type for left brace found in this level. +/// \param IfKind The \p if statement kind in the level. +/// \param IfLeftBrace The left brace of the \p if block in the level. /// \returns true if a simple block of if/else/for/while, or false otherwise. /// (A simple block has a single statement.) bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace, bool CanContainBracedList, + TokenType NextLBracesType, IfStmtKind *IfKind, - TokenType NextLBracesType) { + FormatToken **IfLeftBrace) { auto NextLevelLBracesType = NextLBracesType == TT_CompoundRequirementLBrace ? TT_BracedListLBrace : TT_Unknown; const bool IsPrecededByCommentOrPPDirective = !Style.RemoveBracesLLVM || precededByCommentOrPPDirective(); + FormatToken *IfLBrace = nullptr; + bool HasDoWhile = false; bool HasLabel = false; unsigned StatementCount = 0; bool SwitchLabelEncountered = false; + do { if (FormatTok->getType() == TT_AttributeMacro) { nextToken(); @@ -494,9 +500,10 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace, else if (FormatTok->getType() == TT_MacroBlockEnd) kind = tok::r_brace; - auto ParseDefault = [this, OpeningBrace, IfKind, NextLevelLBracesType, - &HasLabel, &StatementCount] { - parseStructuralElement(IfKind, !OpeningBrace, NextLevelLBracesType, + auto ParseDefault = [this, OpeningBrace, NextLevelLBracesType, IfKind, + &IfLBrace, &HasDoWhile, &HasLabel, &StatementCount] { + parseStructuralElement(!OpeningBrace, NextLevelLBracesType, IfKind, + &IfLBrace, HasDoWhile ? nullptr : &HasDoWhile, HasLabel ? nullptr : &HasLabel); ++StatementCount; assert(StatementCount > 0 && "StatementCount overflow!"); @@ -522,7 +529,7 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace, continue; } parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u, - /*MunchSemi=*/true, /*KeepBraces=*/true, + /*MunchSemi=*/true, /*KeepBraces=*/true, /*IfKind=*/nullptr, /*UnindentWhitesmithsBraces=*/false, CanContainBracedList, NextLBracesType); ++StatementCount; @@ -536,12 +543,16 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace, return false; } if (FormatTok->isNot(tok::r_brace) || StatementCount != 1 || HasLabel || - IsPrecededByCommentOrPPDirective || + HasDoWhile || IsPrecededByCommentOrPPDirective || precededByCommentOrPPDirective()) { return false; } const FormatToken *Next = Tokens->peekNextToken(); - return Next->isNot(tok::comment) || Next->NewlinesBefore > 0; + if (Next->is(tok::comment) && Next->NewlinesBefore == 0) + return false; + if (IfLeftBrace) + *IfLeftBrace = IfLBrace; + return true; } nextToken(); addUnwrappedLine(); @@ -591,6 +602,7 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace, break; } } while (!eof()); + return false; } @@ -813,10 +825,10 @@ bool UnwrappedLineParser::mightFitOnOneLine( return Line.Level * Style.IndentWidth + Length <= ColumnLimit; } -UnwrappedLineParser::IfStmtKind UnwrappedLineParser::parseBlock( +FormatToken *UnwrappedLineParser::parseBlock( bool MustBeDeclaration, unsigned AddLevels, bool MunchSemi, bool KeepBraces, - bool UnindentWhitesmithsBraces, bool CanContainBracedList, - TokenType NextLBracesType) { + IfStmtKind *IfKind, bool UnindentWhitesmithsBraces, + bool CanContainBracedList, TokenType NextLBracesType) { assert(FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) && "'{' or macro block token expected"); FormatToken *Tok = FormatTok; @@ -832,9 +844,13 @@ UnwrappedLineParser::IfStmtKind UnwrappedLineParser::parseBlock( size_t PPStartHash = computePPHash(); - unsigned InitialLevel = Line->Level; + const unsigned InitialLevel = Line->Level; nextToken(/*LevelDifference=*/AddLevels); + // Bail out if there are too many levels. Otherwise, the stack might overflow. + if (Line->Level > 300) + return nullptr; + if (MacroBlock && FormatTok->is(tok::l_paren)) parseParens(); @@ -857,34 +873,40 @@ UnwrappedLineParser::IfStmtKind UnwrappedLineParser::parseBlock( if (AddLevels > 0u && Style.BreakBeforeBraces != FormatStyle::BS_Whitesmiths) Line->Level += AddLevels; - IfStmtKind IfKind = IfStmtKind::NotIf; + FormatToken *IfLBrace = nullptr; const bool SimpleBlock = - parseLevel(Tok, CanContainBracedList, &IfKind, NextLBracesType); + parseLevel(Tok, CanContainBracedList, NextLBracesType, IfKind, &IfLBrace); if (eof()) - return IfKind; + return IfLBrace; if (MacroBlock ? !FormatTok->is(TT_MacroBlockEnd) : !FormatTok->is(tok::r_brace)) { Line->Level = InitialLevel; FormatTok->setBlockKind(BK_Block); - return IfKind; + return IfLBrace; } auto RemoveBraces = [=]() mutable { - if (KeepBraces || !SimpleBlock) + if (!SimpleBlock) return false; assert(Tok->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace)); assert(FormatTok->is(tok::r_brace)); const bool WrappedOpeningBrace = !Tok->Previous; if (WrappedOpeningBrace && FollowedByComment) return false; - const FormatToken *Previous = Tokens->getPreviousToken(); - assert(Previous); - if (Previous->is(tok::r_brace) && !Previous->Optional) + const bool HasRequiredIfBraces = IfLBrace && !IfLBrace->Optional; + if (KeepBraces && !HasRequiredIfBraces) return false; + if (Tok->isNot(TT_ElseLBrace) || !HasRequiredIfBraces) { + const FormatToken *Previous = Tokens->getPreviousToken(); + assert(Previous); + if (Previous->is(tok::r_brace) && !Previous->Optional) + return false; + } assert(!CurrentLines->empty()); - if (!mightFitOnOneLine(CurrentLines->back())) + auto &LastLine = CurrentLines->back(); + if (LastLine.Level == InitialLevel + 1 && !mightFitOnOneLine(LastLine)) return false; if (Tok->is(TT_ElseLBrace)) return true; @@ -934,7 +956,7 @@ UnwrappedLineParser::IfStmtKind UnwrappedLineParser::parseBlock( } } - return IfKind; + return IfLBrace; } static bool isGoogScope(const UnwrappedLine &Line) { @@ -1008,8 +1030,7 @@ void UnwrappedLineParser::parseChildBlock( ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack, /*MustBeDeclaration=*/false); Line->Level += SkipIndent ? 0 : 1; - parseLevel(OpeningBrace, CanContainBracedList, /*IfKind=*/nullptr, - NextLBracesType); + parseLevel(OpeningBrace, CanContainBracedList, NextLBracesType); flushComments(isOnNewLine(*FormatTok)); Line->Level -= SkipIndent ? 0 : 1; } @@ -1412,10 +1433,9 @@ void UnwrappedLineParser::readTokenWithJavaScriptASI() { } } -void UnwrappedLineParser::parseStructuralElement(IfStmtKind *IfKind, - bool IsTopLevel, - TokenType NextLBracesType, - bool *HasLabel) { +void UnwrappedLineParser::parseStructuralElement( + bool IsTopLevel, TokenType NextLBracesType, IfStmtKind *IfKind, + FormatToken **IfLeftBrace, bool *HasDoWhile, bool *HasLabel) { if (Style.Language == FormatStyle::LK_TableGen && FormatTok->is(tok::pp_include)) { nextToken(); @@ -1455,13 +1475,16 @@ void UnwrappedLineParser::parseStructuralElement(IfStmtKind *IfKind, parseAccessSpecifier(); } return; - case tok::kw_if: + case tok::kw_if: { if (Style.isJavaScript() && Line->MustBeDeclaration) { // field/method declaration. break; } - parseIfThenElse(IfKind); + FormatToken *Tok = parseIfThenElse(IfKind); + if (IfLeftBrace) + *IfLeftBrace = Tok; return; + } case tok::kw_for: case tok::kw_while: if (Style.isJavaScript() && Line->MustBeDeclaration) { @@ -1476,6 +1499,8 @@ void UnwrappedLineParser::parseStructuralElement(IfStmtKind *IfKind, break; } parseDoWhile(); + if (HasDoWhile) + *HasDoWhile = true; return; case tok::kw_switch: if (Style.isJavaScript() && Line->MustBeDeclaration) { @@ -2538,8 +2563,7 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind, if (FormatTok->is(tok::kw_consteval)) { nextToken(); } else { - if (Style.RemoveBracesLLVM) - KeepIfBraces = KeepBraces; + KeepIfBraces = !Style.RemoveBracesLLVM || KeepBraces; if (FormatTok->isOneOf(tok::kw_constexpr, tok::identifier)) nextToken(); if (FormatTok->is(tok::l_paren)) @@ -2557,8 +2581,8 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind, FormatTok->setFinalizedType(TT_ControlStatementLBrace); IfLeftBrace = FormatTok; CompoundStatementIndenter Indenter(this, Style, Line->Level); - IfBlockKind = parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u, - /*MunchSemi=*/true, KeepIfBraces); + parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u, + /*MunchSemi=*/true, KeepIfBraces, &IfBlockKind); if (Style.BraceWrapping.BeforeElse) addUnwrappedLine(); else @@ -2587,16 +2611,22 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind, nextToken(); handleAttributes(); if (FormatTok->is(tok::l_brace)) { + const bool FollowedByIf = Tokens->peekNextToken()->is(tok::kw_if); FormatTok->setFinalizedType(TT_ElseLBrace); ElseLeftBrace = FormatTok; CompoundStatementIndenter Indenter(this, Style, Line->Level); - const IfStmtKind ElseBlockKind = + IfStmtKind ElseBlockKind = IfStmtKind::NotIf; + FormatToken *IfLBrace = parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u, - /*MunchSemi=*/true, KeepElseBraces); - if ((ElseBlockKind == IfStmtKind::IfOnly || - ElseBlockKind == IfStmtKind::IfElseIf) && - FormatTok->is(tok::kw_else)) { + /*MunchSemi=*/true, KeepElseBraces, &ElseBlockKind); + if (FormatTok->is(tok::kw_else)) { + KeepElseBraces = KeepElseBraces || + ElseBlockKind == IfStmtKind::IfOnly || + ElseBlockKind == IfStmtKind::IfElseIf; + } else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) { KeepElseBraces = true; + assert(ElseLeftBrace->MatchingParen); + markOptionalBraces(ElseLeftBrace); } addUnwrappedLine(); } else if (FormatTok->is(tok::kw_if)) { @@ -2621,8 +2651,7 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind, parseUnbracedBody(/*CheckEOF=*/true); } } else { - if (Style.RemoveBracesLLVM) - KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse; + KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse; if (NeedsUnwrappedLine) addUnwrappedLine(); } @@ -2791,7 +2820,8 @@ void UnwrappedLineParser::parseNamespace() { ++Line->Level; parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/true, - /*KeepBraces=*/true, ManageWhitesmithsBraces); + /*KeepBraces=*/true, /*IfKind=*/nullptr, + ManageWhitesmithsBraces); // Munch the semicolon after a namespace. This is more common than one would // think. Putting the semicolon into its own line is very ugly. @@ -2884,6 +2914,7 @@ void UnwrappedLineParser::parseForOrWhileLoop() { if (FormatTok->is(tok::l_paren)) parseParens(); + handleAttributes(); parseLoopBody(KeepBraces, /*WrapRightBrace=*/true); } @@ -3606,7 +3637,7 @@ void UnwrappedLineParser::parseJavaEnumBody() { } // Parse the class body after the enum's ";" if any. - parseLevel(OpeningBrace, /*CanContainBracedList=*/true); + parseLevel(OpeningBrace); nextToken(); --Line->Level; addUnwrappedLine(); diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index ffba36cd01706..8f63870412d00 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -92,16 +92,19 @@ class UnwrappedLineParser { void reset(); void parseFile(); bool precededByCommentOrPPDirective() const; - bool parseLevel(const FormatToken *OpeningBrace, bool CanContainBracedList, + bool parseLevel(const FormatToken *OpeningBrace = nullptr, + bool CanContainBracedList = true, + TokenType NextLBracesType = TT_Unknown, IfStmtKind *IfKind = nullptr, - TokenType NextLBracesType = TT_Unknown); + FormatToken **IfLeftBrace = nullptr); bool mightFitOnOneLine(UnwrappedLine &Line, const FormatToken *OpeningBrace = nullptr) const; - IfStmtKind parseBlock(bool MustBeDeclaration = false, unsigned AddLevels = 1u, - bool MunchSemi = true, bool KeepBraces = true, - bool UnindentWhitesmithsBraces = false, - bool CanContainBracedList = true, - TokenType NextLBracesType = TT_Unknown); + FormatToken *parseBlock(bool MustBeDeclaration = false, + unsigned AddLevels = 1u, bool MunchSemi = true, + bool KeepBraces = true, IfStmtKind *IfKind = nullptr, + bool UnindentWhitesmithsBraces = false, + bool CanContainBracedList = true, + TokenType NextLBracesType = TT_Unknown); void parseChildBlock(bool CanContainBracedList = true, TokenType NextLBracesType = TT_Unknown); void parsePPDirective(); @@ -112,9 +115,11 @@ class UnwrappedLineParser { void parsePPEndIf(); void parsePPUnknown(); void readTokenWithJavaScriptASI(); - void parseStructuralElement(IfStmtKind *IfKind = nullptr, - bool IsTopLevel = false, + void parseStructuralElement(bool IsTopLevel = false, TokenType NextLBracesType = TT_Unknown, + IfStmtKind *IfKind = nullptr, + FormatToken **IfLeftBrace = nullptr, + bool *HasDoWhile = nullptr, bool *HasLabel = nullptr); bool tryToParseBracedList(); bool parseBracedList(bool ContinueOnSemicolons = false, bool IsEnum = false, diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index fe43981e27d00..6ec788ad23c66 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -230,12 +230,10 @@ void WhitespaceManager::calculateLineBreakInformation() { if (Change.Tok->is(tok::comment)) { if (Change.Tok->is(TT_LineComment) || !Change.IsInsideToken) { LastBlockComment = &Change; - } else { - if ((Change.StartOfBlockComment = LastBlockComment)) { - Change.IndentationOffset = - Change.StartOfTokenColumn - - Change.StartOfBlockComment->StartOfTokenColumn; - } + } else if ((Change.StartOfBlockComment = LastBlockComment)) { + Change.IndentationOffset = + Change.StartOfTokenColumn - + Change.StartOfBlockComment->StartOfTokenColumn; } } else { LastBlockComment = nullptr; diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 1cf20a0b662ad..91dde2d86d465 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -759,7 +759,8 @@ std::unique_ptr ASTUnit::LoadFromASTFile( WhatToLoad ToLoad, IntrusiveRefCntPtr Diags, const FileSystemOptions &FileSystemOpts, bool UseDebugInfo, bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics, - bool AllowASTWithCompilerErrors, bool UserFilesAreVolatile) { + bool AllowASTWithCompilerErrors, bool UserFilesAreVolatile, + IntrusiveRefCntPtr VFS) { std::unique_ptr AST(new ASTUnit(true)); // Recover resources if we crash before exiting this method. @@ -775,8 +776,6 @@ std::unique_ptr ASTUnit::LoadFromASTFile( AST->OnlyLocalDecls = OnlyLocalDecls; AST->CaptureDiagnostics = CaptureDiagnostics; AST->Diagnostics = Diags; - IntrusiveRefCntPtr VFS = - llvm::vfs::getRealFileSystem(); AST->FileMgr = new FileManager(FileSystemOpts, VFS); AST->UserFilesAreVolatile = UserFilesAreVolatile; AST->SourceMgr = new SourceManager(AST->getDiagnostics(), diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 32b084dfedecc..5d7916ace87e8 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -816,18 +816,6 @@ static void GenerateAnalyzerArgs(AnalyzerOptions &Opts, #include "clang/Driver/Options.inc" #undef ANALYZER_OPTION_WITH_MARSHALLING - if (Opts.AnalysisStoreOpt != RegionStoreModel) { - switch (Opts.AnalysisStoreOpt) { -#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \ - case NAME##Model: \ - GenerateArg(Args, OPT_analyzer_store, CMDFLAG, SA); \ - break; -#include "clang/StaticAnalyzer/Core/Analyses.def" - default: - llvm_unreachable("Tried to generate unknown analysis store."); - } - } - if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) { switch (Opts.AnalysisConstraintsOpt) { #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \ @@ -915,20 +903,13 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, #include "clang/Driver/Options.inc" #undef ANALYZER_OPTION_WITH_MARSHALLING - if (Arg *A = Args.getLastArg(OPT_analyzer_store)) { - StringRef Name = A->getValue(); - AnalysisStores Value = llvm::StringSwitch(Name) -#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \ - .Case(CMDFLAG, NAME##Model) -#include "clang/StaticAnalyzer/Core/Analyses.def" - .Default(NumStores); - if (Value == NumStores) { - Diags.Report(diag::err_drv_invalid_value) - << A->getAsString(Args) << Name; - } else { - Opts.AnalysisStoreOpt = Value; - } - } + if (Args.hasArg(OPT_analyzer_store)) + Diags.Report(diag::warn_analyzer_deprecated_option) << "-analyzer-store" + << "clang-16"; + if (Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks)) + Diags.Report(diag::warn_analyzer_deprecated_option) + << "-analyzer-opt-analyze-nested-blocks" + << "clang-16"; if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) { StringRef Name = A->getValue(); @@ -1112,25 +1093,22 @@ static void initOption(AnalyzerOptions::ConfigTable &Config, static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts, DiagnosticsEngine *Diags) { // TODO: There's no need to store the entire configtable, it'd be plenty - // enough tostore checker options. + // enough to store checker options. #define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \ initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEFAULT_VAL); +#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(...) +#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" -#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ - SHALLOW_VAL, DEEP_VAL) \ - switch (AnOpts.getUserMode()) { \ - case UMK_Shallow: \ - initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, SHALLOW_VAL); \ - break; \ - case UMK_Deep: \ - initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEEP_VAL); \ - break; \ - } \ + assert(AnOpts.UserMode == "shallow" || AnOpts.UserMode == "deep"); + const bool InShallowMode = AnOpts.UserMode == "shallow"; +#define ANALYZER_OPTION(...) +#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ + SHALLOW_VAL, DEEP_VAL) \ + initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, \ + InShallowMode ? SHALLOW_VAL : DEEP_VAL); #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" -#undef ANALYZER_OPTION -#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE // At this point, AnalyzerOptions is configured. Let's validate some options. @@ -4202,6 +4180,10 @@ static void GeneratePreprocessorArgs(PreprocessorOptions &Opts, ((LangOpts.DeclareOpenCLBuiltins && I == "opencl-c-base.h") || I == "opencl-c.h")) continue; + // Don't generate HLSL includes. They are implied by other flags that are + // generated elsewhere. + if (LangOpts.HLSL && I == "hlsl.h") + continue; GenerateArg(Args, OPT_include, I, SA); } diff --git a/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp b/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp index 49e814b31b439..35b5e2144e6d3 100644 --- a/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp +++ b/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp @@ -54,6 +54,9 @@ clang::createInvocation(ArrayRef ArgList, if (!C) return nullptr; + if (C->getArgs().hasArg(driver::options::OPT_fdriver_only)) + return nullptr; + // Just print the cc1 options if -### was present. if (C->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) { C->getJobs().Print(llvm::errs(), "\n", true); diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index 68c70dda12b9e..6b1f6364b13c3 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -413,11 +413,7 @@ static std::error_code collectModuleHeaderIncludes( // Sort header paths and make the header inclusion order deterministic // across different OSs and filesystems. - llvm::sort(Headers.begin(), Headers.end(), []( - const std::pair &LHS, - const std::pair &RHS) { - return LHS.first < RHS.first; - }); + llvm::sort(Headers.begin(), Headers.end(), llvm::less_first()); for (auto &H : Headers) { // Include this header as part of the umbrella directory. Module->addTopHeader(H.second); diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 3921f7949a0a9..834946411b84b 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -377,6 +377,10 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__HLSL_VERSION", Twine((unsigned)LangOpts.getHLSLVersion())); + if (LangOpts.NativeHalfType) + Builder.defineMacro("__HLSL_ENABLE_16_BIT", + Twine((unsigned)LangOpts.getHLSLVersion())); + // Shader target information // "enums" for shader stages Builder.defineMacro("__SHADER_STAGE_VERTEX", @@ -406,7 +410,7 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, if (TI.getTriple().getOS() == llvm::Triple::ShaderModel) { VersionTuple Version = TI.getTriple().getOSVersion(); Builder.defineMacro("__SHADER_TARGET_MAJOR", Twine(Version.getMajor())); - unsigned Minor = Version.getMinor() ? *Version.getMinor() : 0; + unsigned Minor = Version.getMinor().getValueOr(0); Builder.defineMacro("__SHADER_TARGET_MINOR", Twine(Minor)); } return; @@ -686,7 +690,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, Builder.defineMacro("__cpp_implicit_move", "202011L"); Builder.defineMacro("__cpp_size_t_suffix", "202011L"); Builder.defineMacro("__cpp_if_consteval", "202106L"); - Builder.defineMacro("__cpp_­multidimensional_­subscript", "202110L"); + Builder.defineMacro("__cpp_multidimensional_subscript", "202110L"); } if (LangOpts.Char8) Builder.defineMacro("__cpp_char8_t", "201811L"); diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index 8bf7dd570384f..dfa3602b557b1 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -62,6 +62,11 @@ set(hip_files __clang_hip_runtime_wrapper.h ) +set(hlsl_files + hlsl.h + hlsl/hlsl_basic_types.h + ) + set(mips_msa_files msa.h ) @@ -212,6 +217,7 @@ set(files ${cuda_files} ${hexagon_files} ${hip_files} + ${hlsl_files} ${mips_msa_files} ${opencl_files} ${ppc_files} @@ -372,6 +378,7 @@ add_dependencies("clang-resource-headers" "cuda-resource-headers" "hexagon-resource-headers" "hip-resource-headers" + "hlsl-resource-headers" "mips-resource-headers" "ppc-resource-headers" "ppc-htm-resource-headers" @@ -405,6 +412,7 @@ add_header_target("webassembly-resource-headers" "${webassembly_files}") add_header_target("x86-resource-headers" "${x86_files}") # Other header groupings +add_header_target("hlsl-resource-headers" ${hlsl_files}) add_header_target("opencl-resource-headers" ${opencl_files}) add_header_target("openmp-resource-headers" ${openmp_wrapper_files}) add_header_target("windows-resource-headers" ${windows_only_files}) @@ -538,6 +546,12 @@ install( EXCLUDE_FROM_ALL COMPONENT x86-resource-headers) +install( + FILES ${hlsl_files} + DESTINATION ${header_install_dir} + EXCLUDE_FROM_ALL + COMPONENT hlsl-resource-headers) + install( FILES ${opencl_files} DESTINATION ${header_install_dir} @@ -614,6 +628,9 @@ if (NOT LLVM_ENABLE_IDE) DEPENDS webassembly-resource-headers COMPONENT webassembly-resource-headers) + add_llvm_install_targets(install-hlsl-resource-headers + DEPENDS hlsl-resource-headers + COMPONENT hlsl-resource-headers) add_llvm_install_targets(install-opencl-resource-headers DEPENDS opencl-resource-headers COMPONENT opencl-resource-headers) diff --git a/clang/lib/Headers/f16cintrin.h b/clang/lib/Headers/f16cintrin.h index 13905e6fb0ec8..94a662c1d93a8 100644 --- a/clang/lib/Headers/f16cintrin.h +++ b/clang/lib/Headers/f16cintrin.h @@ -65,9 +65,9 @@ _cvtsh_ss(unsigned short __a) /// 011: Truncate \n /// 1XX: Use MXCSR.RC for rounding /// \returns The converted 16-bit half-precision float value. -#define _cvtss_sh(a, imm) \ - ((unsigned short)(((__v8hi)__builtin_ia32_vcvtps2ph((__v4sf){a, 0, 0, 0}, \ - (imm)))[0])) +#define _cvtss_sh(a, imm) __extension__ ({ \ + (unsigned short)(((__v8hi)__builtin_ia32_vcvtps2ph((__v4sf){a, 0, 0, 0}, \ + (imm)))[0]); }) /// Converts a 128-bit vector containing 32-bit float values into a /// 128-bit vector containing 16-bit half-precision float values. diff --git a/clang/lib/Headers/hlsl.h b/clang/lib/Headers/hlsl.h new file mode 100644 index 0000000000000..0db8a4ed1fe40 --- /dev/null +++ b/clang/lib/Headers/hlsl.h @@ -0,0 +1,14 @@ +//===----- hlsl.h - HLSL definitions --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _HLSL_H_ +#define _HLSL_H_ + +#include "hlsl/hlsl_basic_types.h" + +#endif //_HLSL_H_ diff --git a/clang/lib/Headers/hlsl/hlsl_basic_types.h b/clang/lib/Headers/hlsl/hlsl_basic_types.h new file mode 100644 index 0000000000000..2069990f5c06c --- /dev/null +++ b/clang/lib/Headers/hlsl/hlsl_basic_types.h @@ -0,0 +1,64 @@ +//===----- hlsl_basic_types.h - HLSL definitions for basic types ----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _HLSL_HLSL_BASIC_TYPES_H_ +#define _HLSL_HLSL_BASIC_TYPES_H_ + +// built-in scalar data types: + +#ifdef __HLSL_ENABLE_16_BIT +// 16-bit integer. +typedef unsigned short uint16_t; +typedef short int16_t; +#endif + +// unsigned 32-bit integer. +typedef unsigned int uint; + +// 64-bit integer. +typedef unsigned long uint64_t; +typedef long int64_t; + +// built-in vector data types: + +#ifdef __HLSL_ENABLE_16_BIT +typedef int16_t int16_t2 __attribute__((ext_vector_type(2))); +typedef int16_t int16_t3 __attribute__((ext_vector_type(3))); +typedef int16_t int16_t4 __attribute__((ext_vector_type(4))); +typedef uint16_t uint16_t2 __attribute__((ext_vector_type(2))); +typedef uint16_t uint16_t3 __attribute__((ext_vector_type(3))); +typedef uint16_t uint16_t4 __attribute__((ext_vector_type(4))); +#endif + +typedef int int2 __attribute__((ext_vector_type(2))); +typedef int int3 __attribute__((ext_vector_type(3))); +typedef int int4 __attribute__((ext_vector_type(4))); +typedef uint uint2 __attribute__((ext_vector_type(2))); +typedef uint uint3 __attribute__((ext_vector_type(3))); +typedef uint uint4 __attribute__((ext_vector_type(4))); +typedef int64_t int64_t2 __attribute__((ext_vector_type(2))); +typedef int64_t int64_t3 __attribute__((ext_vector_type(3))); +typedef int64_t int64_t4 __attribute__((ext_vector_type(4))); +typedef uint64_t uint64_t2 __attribute__((ext_vector_type(2))); +typedef uint64_t uint64_t3 __attribute__((ext_vector_type(3))); +typedef uint64_t uint64_t4 __attribute__((ext_vector_type(4))); + +#ifdef __HLSL_ENABLE_16_BIT +typedef half half2 __attribute__((ext_vector_type(2))); +typedef half half3 __attribute__((ext_vector_type(3))); +typedef half half4 __attribute__((ext_vector_type(4))); +#endif + +typedef float float2 __attribute__((ext_vector_type(2))); +typedef float float3 __attribute__((ext_vector_type(3))); +typedef float float4 __attribute__((ext_vector_type(4))); +typedef double double2 __attribute__((ext_vector_type(2))); +typedef double double3 __attribute__((ext_vector_type(3))); +typedef double double4 __attribute__((ext_vector_type(4))); + +#endif //_HLSL_HLSL_BASIC_TYPES_H_ diff --git a/clang/lib/Headers/unwind.h b/clang/lib/Headers/unwind.h index 6e069798f02d6..971a62da0d212 100644 --- a/clang/lib/Headers/unwind.h +++ b/clang/lib/Headers/unwind.h @@ -62,7 +62,8 @@ typedef intptr_t _sleb128_t; typedef uintptr_t _uleb128_t; struct _Unwind_Context; -#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || defined(__ARM_DWARF_EH__)) +#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || \ + defined(__ARM_DWARF_EH__) || defined(__SEH__)) struct _Unwind_Control_Block; typedef struct _Unwind_Control_Block _Unwind_Exception; /* Alias */ #else @@ -72,7 +73,7 @@ typedef struct _Unwind_Exception _Unwind_Exception; typedef enum { _URC_NO_REASON = 0, #if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ - !defined(__ARM_DWARF_EH__) + !defined(__ARM_DWARF_EH__) && !defined(__SEH__) _URC_OK = 0, /* used by ARM EHABI */ #endif _URC_FOREIGN_EXCEPTION_CAUGHT = 1, @@ -86,7 +87,7 @@ typedef enum { _URC_INSTALL_CONTEXT = 7, _URC_CONTINUE_UNWIND = 8, #if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ - !defined(__ARM_DWARF_EH__) + !defined(__ARM_DWARF_EH__) && !defined(__SEH__) _URC_FAILURE = 9 /* used by ARM EHABI */ #endif } _Unwind_Reason_Code; @@ -103,7 +104,8 @@ typedef enum { typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code, _Unwind_Exception *); -#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || defined(__ARM_DWARF_EH__)) +#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || \ + defined(__ARM_DWARF_EH__) || defined(__SEH__)) typedef struct _Unwind_Control_Block _Unwind_Control_Block; typedef uint32_t _Unwind_EHT_Header; @@ -167,7 +169,8 @@ typedef _Unwind_Personality_Fn __personality_routine; typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *, void *); -#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || defined(__ARM_DWARF_EH__)) +#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || \ + defined(__ARM_DWARF_EH__) || defined(__SEH__)) typedef enum { _UVRSC_CORE = 0, /* integer register */ _UVRSC_VFP = 1, /* vfp */ diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 5fd853541b6a2..85804bc83eb74 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -319,7 +319,8 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName, SmallString<128> FrameworkDirName; FrameworkDirName += Dir.getFrameworkDir()->getName(); llvm::sys::path::append(FrameworkDirName, SearchName + ".framework"); - if (auto FrameworkDir = FileMgr.getDirectory(FrameworkDirName)) { + if (auto FrameworkDir = + FileMgr.getOptionalDirectoryRef(FrameworkDirName)) { bool IsSystem = Dir.getDirCharacteristic() != SrcMgr::C_User; Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem); if (Module) @@ -334,8 +335,10 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName, continue; bool IsSystem = Dir.isSystemHeaderDirectory(); + // Only returns None if not a normal directory, which we just checked + DirectoryEntryRef NormalDir = *Dir.getDirRef(); // Search for a module map file in this directory. - if (loadModuleMapFile(Dir.getDir(), IsSystem, + if (loadModuleMapFile(NormalDir, IsSystem, /*IsFramework*/false) == LMM_NewlyLoaded) { // We just loaded a module map file; check whether the module is // available now. @@ -507,7 +510,7 @@ Optional DirectoryLookup::LookupFile( /// \param DirName The name of the framework directory. /// \param SubmodulePath Will be populated with the submodule path from the /// returned top-level module to the originally named framework. -static const DirectoryEntry * +static Optional getTopFrameworkDir(FileManager &FileMgr, StringRef DirName, SmallVectorImpl &SubmodulePath) { assert(llvm::sys::path::extension(DirName) == ".framework" && @@ -527,12 +530,10 @@ getTopFrameworkDir(FileManager &FileMgr, StringRef DirName, // // Similar issues occur when a top-level framework has moved into an // embedded framework. - const DirectoryEntry *TopFrameworkDir = nullptr; - if (auto TopFrameworkDirOrErr = FileMgr.getDirectory(DirName)) - TopFrameworkDir = *TopFrameworkDirOrErr; + auto TopFrameworkDir = FileMgr.getOptionalDirectoryRef(DirName); if (TopFrameworkDir) - DirName = FileMgr.getCanonicalName(TopFrameworkDir); + DirName = FileMgr.getCanonicalName(*TopFrameworkDir); do { // Get the parent directory name. DirName = llvm::sys::path::parent_path(DirName); @@ -540,7 +541,7 @@ getTopFrameworkDir(FileManager &FileMgr, StringRef DirName, break; // Determine whether this directory exists. - auto Dir = FileMgr.getDirectory(DirName); + auto Dir = FileMgr.getOptionalDirectoryRef(DirName); if (!Dir) break; @@ -1486,13 +1487,13 @@ bool HeaderSearch::hasModuleMap(StringRef FileName, return false; // Determine whether this directory exists. - auto Dir = FileMgr.getDirectory(DirName); + auto Dir = FileMgr.getOptionalDirectoryRef(DirName); if (!Dir) return false; // Try to load the module map file in this directory. switch (loadModuleMapFile(*Dir, IsSystem, - llvm::sys::path::extension((*Dir)->getName()) == + llvm::sys::path::extension(Dir->getName()) == ".framework")) { case LMM_NewlyLoaded: case LMM_AlreadyLoaded: @@ -1589,15 +1590,16 @@ bool HeaderSearch::findUsableModuleForFrameworkHeader( if (needModuleLookup(RequestingModule, SuggestedModule)) { // Find the top-level framework based on this framework. SmallVector SubmodulePath; - const DirectoryEntry *TopFrameworkDir - = ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath); + Optional TopFrameworkDir = + ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath); + assert(TopFrameworkDir && "Could not find the top-most framework dir"); // Determine the name of the top-level framework. StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName()); // Load this framework module. If that succeeds, find the suggested module // for this header, if any. - loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystemFramework); + loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework); // FIXME: This can find a module not part of ModuleName, which is // important so that we're consistent about whether this header @@ -1628,39 +1630,40 @@ bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem, StringRef OriginalModuleMapFile) { // Find the directory for the module. For frameworks, that may require going // up from the 'Modules' directory. - const DirectoryEntry *Dir = nullptr; + Optional Dir; if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) { - if (auto DirOrErr = FileMgr.getDirectory(".")) - Dir = *DirOrErr; + Dir = FileMgr.getOptionalDirectoryRef("."); } else { if (!OriginalModuleMapFile.empty()) { // We're building a preprocessed module map. Find or invent the directory // that it originally occupied. - auto DirOrErr = FileMgr.getDirectory( + Dir = FileMgr.getOptionalDirectoryRef( llvm::sys::path::parent_path(OriginalModuleMapFile)); - if (DirOrErr) { - Dir = *DirOrErr; - } else { - auto *FakeFile = FileMgr.getVirtualFile(OriginalModuleMapFile, 0, 0); - Dir = FakeFile->getDir(); + if (!Dir) { + auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0); + Dir = FakeFile.getDir(); } } else { - Dir = File->getDir(); + // TODO: Replace with `Dir = File.getDir()` when `File` is switched to + // `FileEntryRef`. + Dir = FileMgr.getOptionalDirectoryRef(File->getDir()->getName()); } + assert(Dir && "parent must exist"); StringRef DirName(Dir->getName()); if (llvm::sys::path::filename(DirName) == "Modules") { DirName = llvm::sys::path::parent_path(DirName); if (DirName.endswith(".framework")) - if (auto DirOrErr = FileMgr.getDirectory(DirName)) - Dir = *DirOrErr; + if (auto MaybeDir = FileMgr.getOptionalDirectoryRef(DirName)) + Dir = *MaybeDir; // FIXME: This assert can fail if there's a race between the above check // and the removal of the directory. assert(Dir && "parent must exist"); } } - switch (loadModuleMapFileImpl(File, IsSystem, Dir, ID, Offset)) { + assert(Dir && "module map home directory must exist"); + switch (loadModuleMapFileImpl(File, IsSystem, *Dir, ID, Offset)) { case LMM_AlreadyLoaded: case LMM_NewlyLoaded: return false; @@ -1673,7 +1676,7 @@ bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem, HeaderSearch::LoadModuleMapResult HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem, - const DirectoryEntry *Dir, FileID ID, + DirectoryEntryRef Dir, FileID ID, unsigned *Offset) { assert(File && "expected FileEntry"); @@ -1731,8 +1734,7 @@ HeaderSearch::lookupModuleMapFile(const DirectoryEntry *Dir, bool IsFramework) { return nullptr; } -Module *HeaderSearch::loadFrameworkModule(StringRef Name, - const DirectoryEntry *Dir, +Module *HeaderSearch::loadFrameworkModule(StringRef Name, DirectoryEntryRef Dir, bool IsSystem) { if (Module *Module = ModMap.findModule(Name)) return Module; @@ -1759,14 +1761,14 @@ Module *HeaderSearch::loadFrameworkModule(StringRef Name, HeaderSearch::LoadModuleMapResult HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem, bool IsFramework) { - if (auto Dir = FileMgr.getDirectory(DirName)) + if (auto Dir = FileMgr.getOptionalDirectoryRef(DirName)) return loadModuleMapFile(*Dir, IsSystem, IsFramework); return LMM_NoDirectory; } HeaderSearch::LoadModuleMapResult -HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem, +HeaderSearch::loadModuleMapFile(DirectoryEntryRef Dir, bool IsSystem, bool IsFramework) { auto KnownDir = DirectoryHasModuleMap.find(Dir); if (KnownDir != DirectoryHasModuleMap.end()) @@ -1807,8 +1809,7 @@ void HeaderSearch::collectAllModules(SmallVectorImpl &Modules) { if (llvm::sys::path::extension(Dir->path()) != ".framework") continue; - auto FrameworkDir = - FileMgr.getDirectory(Dir->path()); + auto FrameworkDir = FileMgr.getOptionalDirectoryRef(Dir->path()); if (!FrameworkDir) continue; @@ -1824,7 +1825,7 @@ void HeaderSearch::collectAllModules(SmallVectorImpl &Modules) { continue; // Try to load a module map file for the search directory. - loadModuleMapFile(DL.getDir(), IsSystem, /*IsFramework*/ false); + loadModuleMapFile(*DL.getDirRef(), IsSystem, /*IsFramework*/ false); // Try to load module map files for immediate subdirectories of this // search directory. @@ -1848,7 +1849,7 @@ void HeaderSearch::loadTopLevelSystemModules() { continue; // Try to load a module map file for the search directory. - loadModuleMapFile(DL.getDir(), DL.isSystemHeaderDirectory(), + loadModuleMapFile(*DL.getDirRef(), DL.isSystemHeaderDirectory(), DL.isFramework()); } } @@ -1973,7 +1974,7 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics( } // Try resolving resulting filename via reverse search in header maps, - // key from header name is user prefered name for the include file. + // key from header name is user preferred name for the include file. StringRef Filename = File.drop_front(BestPrefixLength); for (const DirectoryLookup &DL : search_dir_range()) { if (!DL.isHeaderMap()) diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 97d7466d79a19..70d001fbaec77 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -33,15 +33,16 @@ #include "clang/Lex/Token.h" #include "clang/Lex/VariadicMacroSupport.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Path.h" +#include "llvm/Support/SaveAndRestore.h" #include #include #include @@ -444,8 +445,7 @@ SourceLocation Preprocessor::CheckEndOfDirective(const char *DirType, } void Preprocessor::SuggestTypoedDirective(const Token &Tok, - StringRef Directive, - const SourceLocation &EndLoc) const { + StringRef Directive) const { // If this is a `.S` file, treat unknown # directives as non-preprocessor // directives. if (getLangOpts().AsmPreprocessor) return; @@ -457,11 +457,14 @@ void Preprocessor::SuggestTypoedDirective(const Token &Tok, Candidates.insert(Candidates.end(), {"elifdef", "elifndef"}); if (Optional Sugg = findSimilarStr(Directive, Candidates)) { - CharSourceRange DirectiveRange = - CharSourceRange::getCharRange(Tok.getLocation(), EndLoc); - std::string SuggValue = Sugg.getValue().str(); - - auto Hint = FixItHint::CreateReplacement(DirectiveRange, "#" + SuggValue); + // Directive cannot be coming from macro. + assert(Tok.getLocation().isFileID()); + CharSourceRange DirectiveRange = CharSourceRange::getCharRange( + Tok.getLocation(), + Tok.getLocation().getLocWithOffset(Directive.size())); + StringRef SuggValue = Sugg.getValue(); + + auto Hint = FixItHint::CreateReplacement(DirectiveRange, SuggValue); Diag(Tok, diag::warn_pp_invalid_directive) << 1 << SuggValue << Hint; } } @@ -479,6 +482,19 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, bool FoundNonSkipPortion, bool FoundElse, SourceLocation ElseLoc) { + // In SkippingRangeStateTy we are depending on SkipExcludedConditionalBlock() + // not getting called recursively by storing the RecordedSkippedRanges + // DenseMap lookup pointer (field SkipRangePtr). SkippingRangeStateTy expects + // that RecordedSkippedRanges won't get modified and SkipRangePtr won't be + // invalidated. If this changes and there is a need to call + // SkipExcludedConditionalBlock() recursively, SkippingRangeStateTy should + // change to do a second lookup in endLexPass function instead of reusing the + // lookup pointer. + assert(!SkippingExcludedConditionalBlock && + "calling SkipExcludedConditionalBlock recursively"); + llvm::SaveAndRestore SARSkipping(SkippingExcludedConditionalBlock, + true); + ++NumSkipped; assert(!CurTokenLexer && CurPPLexer && "Lexing a macro, not a file?"); @@ -493,10 +509,53 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, CurPPLexer->LexingRawMode = true; Token Tok; SourceLocation endLoc; + + /// Keeps track and caches skipped ranges and also retrieves a prior skipped + /// range if the same block is re-visited. + struct SkippingRangeStateTy { + Preprocessor &PP; + + const char *BeginPtr = nullptr; + unsigned *SkipRangePtr = nullptr; + + SkippingRangeStateTy(Preprocessor &PP) : PP(PP) {} + + void beginLexPass() { + if (BeginPtr) + return; // continue skipping a block. + + // Initiate a skipping block and adjust the lexer if we already skipped it + // before. + BeginPtr = PP.CurLexer->getBufferLocation(); + SkipRangePtr = &PP.RecordedSkippedRanges[BeginPtr]; + if (*SkipRangePtr) { + PP.CurLexer->seek(PP.CurLexer->getCurrentBufferOffset() + *SkipRangePtr, + /*IsAtStartOfLine*/ true); + } + } + + void endLexPass(const char *Hashptr) { + if (!BeginPtr) { + // Not doing normal lexing. + assert(PP.CurLexer->isDependencyDirectivesLexer()); + return; + } + + // Finished skipping a block, record the range if it's first time visited. + if (!*SkipRangePtr) { + *SkipRangePtr = Hashptr - BeginPtr; + } + assert(*SkipRangePtr == Hashptr - BeginPtr); + BeginPtr = nullptr; + SkipRangePtr = nullptr; + } + } SkippingRangeState(*this); + while (true) { if (CurLexer->isDependencyDirectivesLexer()) { CurLexer->LexDependencyDirectiveTokenWhileSkipping(Tok); } else { + SkippingRangeState.beginLexPass(); while (true) { CurLexer->Lex(Tok); @@ -535,6 +594,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, CurPPLexer->ParsingPreprocessorDirective = true; if (CurLexer) CurLexer->SetKeepWhitespaceMode(false); + assert(Tok.is(tok::hash)); + const char *Hashptr = CurLexer->getBufferLocation() - Tok.getLength(); + assert(CurLexer->getSourceLocation(Hashptr) == Tok.getLocation()); // Read the next token, the directive flavor. LexUnexpandedToken(Tok); @@ -596,7 +658,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, /*foundnonskip*/false, /*foundelse*/false); } else { - SuggestTypoedDirective(Tok, Directive, endLoc); + SuggestTypoedDirective(Tok, Directive); } } else if (Directive[0] == 'e') { StringRef Sub = Directive.substr(1); @@ -609,6 +671,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, // If we popped the outermost skipping block, we're done skipping! if (!CondInfo.WasSkipping) { + SkippingRangeState.endLexPass(Hashptr); // Restore the value of LexingRawMode so that trailing comments // are handled correctly, if we've reached the outermost block. CurPPLexer->LexingRawMode = false; @@ -626,6 +689,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, // as a non-skipping conditional. PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel(); + if (!CondInfo.WasSkipping) + SkippingRangeState.endLexPass(Hashptr); + // If this is a #else with a #else before it, report the error. if (CondInfo.FoundElse) Diag(Tok, diag::pp_err_else_after_else); @@ -651,6 +717,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, } else if (Sub == "lif") { // "elif". PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel(); + if (!CondInfo.WasSkipping) + SkippingRangeState.endLexPass(Hashptr); + // If this is a #elif with a #else before it, report the error. if (CondInfo.FoundElse) Diag(Tok, diag::pp_err_elif_after_else) << PED_Elif; @@ -693,6 +762,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel(); Token DirectiveToken = Tok; + if (!CondInfo.WasSkipping) + SkippingRangeState.endLexPass(Hashptr); + // Warn if using `#elifdef` & `#elifndef` in not C2x & C++2b mode even // if this branch is in a skipping block. unsigned DiagID; @@ -758,10 +830,10 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, } } } else { - SuggestTypoedDirective(Tok, Directive, endLoc); + SuggestTypoedDirective(Tok, Directive); } } else { - SuggestTypoedDirective(Tok, Directive, endLoc); + SuggestTypoedDirective(Tok, Directive); } CurPPLexer->ParsingPreprocessorDirective = false; diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 9d1090be8e096..063199b0e6ce5 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/FileManager.h" @@ -1689,8 +1690,9 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { [this](Token &Tok, bool &HasLexedNextToken) -> int { IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this, diag::err_feature_check_malformed); - return II ? hasAttribute(AttrSyntax::GNU, nullptr, II, - getTargetInfo(), getLangOpts()) : 0; + return II ? hasAttribute(AttributeCommonInfo::Syntax::AS_GNU, nullptr, + II, getTargetInfo(), getLangOpts()) + : 0; }); } else if (II == Ident__has_declspec) { EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, true, @@ -1700,8 +1702,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { if (II) { const LangOptions &LangOpts = getLangOpts(); return LangOpts.DeclSpecKeyword && - hasAttribute(AttrSyntax::Declspec, nullptr, II, - getTargetInfo(), LangOpts); + hasAttribute(AttributeCommonInfo::Syntax::AS_Declspec, nullptr, + II, getTargetInfo(), LangOpts); } return false; @@ -1730,7 +1732,9 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { diag::err_feature_check_malformed); } - AttrSyntax Syntax = IsCXX ? AttrSyntax::CXX : AttrSyntax::C; + AttributeCommonInfo::Syntax Syntax = + IsCXX ? AttributeCommonInfo::Syntax::AS_CXX11 + : AttributeCommonInfo::Syntax::AS_C2x; return II ? hasAttribute(Syntax, ScopeII, II, getTargetInfo(), getLangOpts()) : 0; @@ -1895,9 +1899,9 @@ void Preprocessor::processPathForFileMacro(SmallVectorImpl &Path, LangOpts.remapPathPrefix(Path); if (LangOpts.UseTargetPathSeparator) { if (TI.getTriple().isOSWindows()) - llvm::sys::path::make_preferred( - Path, llvm::sys::path::Style::windows_backslash); + llvm::sys::path::remove_dots(Path, false, + llvm::sys::path::Style::windows_backslash); else - llvm::sys::path::make_preferred(Path, llvm::sys::path::Style::posix); + llvm::sys::path::remove_dots(Path, false, llvm::sys::path::Style::posix); } } diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 306644fc4b21d..a90d5d9cc4856 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -10,16 +10,17 @@ // //===----------------------------------------------------------------------===// -#include "clang/Parse/Parser.h" -#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/TargetInfo.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/Parser.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" @@ -56,7 +57,7 @@ TypeResult Parser::ParseTypeName(SourceRange *Range, DeclaratorContext Context, *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr; // Parse the abstract-declarator, if present. - Declarator DeclaratorInfo(DS, Context); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context); ParseDeclarator(DeclaratorInfo); if (Range) *Range = DeclaratorInfo.getSourceRange(); @@ -596,7 +597,7 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, // If the attribute isn't known, we will not attempt to parse any // arguments. - if (!hasAttribute(AttrSyntax::Declspec, nullptr, AttrName, + if (!hasAttribute(AttributeCommonInfo::Syntax::AS_Declspec, nullptr, AttrName, getTargetInfo(), getLangOpts())) { // Eat the left paren, then skip to the ending right paren. ConsumeParen(); @@ -1759,7 +1760,8 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributes &Attrs, /// Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd, - ParsedAttributes &Attrs, + ParsedAttributes &DeclAttrs, + ParsedAttributes &DeclSpecAttrs, SourceLocation *DeclSpecStart) { ParenBraceBracketBalancer BalancerRAIIObj(*this); // Must temporarily exit the objective-c container scope for @@ -1770,32 +1772,40 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, switch (Tok.getKind()) { case tok::kw_template: case tok::kw_export: - ProhibitAttributes(Attrs); - SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd, Attrs); + ProhibitAttributes(DeclAttrs); + ProhibitAttributes(DeclSpecAttrs); + SingleDecl = + ParseDeclarationStartingWithTemplate(Context, DeclEnd, DeclAttrs); break; case tok::kw_inline: // Could be the start of an inline namespace. Allowed as an ext in C++03. if (getLangOpts().CPlusPlus && NextToken().is(tok::kw_namespace)) { - ProhibitAttributes(Attrs); + ProhibitAttributes(DeclAttrs); + ProhibitAttributes(DeclSpecAttrs); SourceLocation InlineLoc = ConsumeToken(); return ParseNamespace(Context, DeclEnd, InlineLoc); } - return ParseSimpleDeclaration(Context, DeclEnd, Attrs, true, nullptr, - DeclSpecStart); + return ParseSimpleDeclaration(Context, DeclEnd, DeclAttrs, DeclSpecAttrs, + true, nullptr, DeclSpecStart); case tok::kw_namespace: - ProhibitAttributes(Attrs); + ProhibitAttributes(DeclAttrs); + ProhibitAttributes(DeclSpecAttrs); return ParseNamespace(Context, DeclEnd); - case tok::kw_using: + case tok::kw_using: { + ParsedAttributes Attrs(AttrFactory); + takeAndConcatenateAttrs(DeclAttrs, DeclSpecAttrs, Attrs); return ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), DeclEnd, Attrs); + } case tok::kw_static_assert: case tok::kw__Static_assert: - ProhibitAttributes(Attrs); + ProhibitAttributes(DeclAttrs); + ProhibitAttributes(DeclSpecAttrs); SingleDecl = ParseStaticAssertDeclaration(DeclEnd); break; default: - return ParseSimpleDeclaration(Context, DeclEnd, Attrs, true, nullptr, - DeclSpecStart); + return ParseSimpleDeclaration(Context, DeclEnd, DeclAttrs, DeclSpecAttrs, + true, nullptr, DeclSpecStart); } // This routine returns a DeclGroup, if the thing we parsed only contains a @@ -1825,10 +1835,17 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, /// the Declaration. The SourceLocation for this Decl is set to /// DeclSpecStart if DeclSpecStart is non-null. Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration( - DeclaratorContext Context, SourceLocation &DeclEnd, ParsedAttributes &Attrs, + DeclaratorContext Context, SourceLocation &DeclEnd, + ParsedAttributes &DeclAttrs, ParsedAttributes &DeclSpecAttrs, bool RequireSemi, ForRangeInit *FRI, SourceLocation *DeclSpecStart) { + // Need to retain these for diagnostics before we add them to the DeclSepc. + ParsedAttributesView OriginalDeclSpecAttrs; + OriginalDeclSpecAttrs.addAll(DeclSpecAttrs.begin(), DeclSpecAttrs.end()); + OriginalDeclSpecAttrs.Range = DeclSpecAttrs.Range; + // Parse the common declaration-specifiers piece. ParsingDeclSpec DS(*this); + DS.takeAttributesFrom(DeclSpecAttrs); DeclSpecContext DSContext = getDeclSpecContextFromDeclaratorContext(Context); ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, DSContext); @@ -1842,7 +1859,7 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration( // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { - ProhibitAttributes(Attrs); + ProhibitAttributes(DeclAttrs); DeclEnd = Tok.getLocation(); if (RequireSemi) ConsumeToken(); RecordDecl *AnonRecord = nullptr; @@ -1859,8 +1876,7 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration( if (DeclSpecStart) DS.SetRangeStart(*DeclSpecStart); - DS.takeAttributesFrom(Attrs); - return ParseDeclGroup(DS, Context, &DeclEnd, FRI); + return ParseDeclGroup(DS, Context, DeclAttrs, &DeclEnd, FRI); } /// Returns true if this might be the start of a declarator, or a common typo @@ -2015,10 +2031,16 @@ void Parser::SkipMalformedDecl() { /// result. Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, DeclaratorContext Context, + ParsedAttributes &Attrs, SourceLocation *DeclEnd, ForRangeInit *FRI) { // Parse the first declarator. - ParsingDeclarator D(*this, DS, Context); + // Consume all of the attributes from `Attrs` by moving them to our own local + // list. This ensures that we will not attempt to interpret them as statement + // attributes higher up the callchain. + ParsedAttributes LocalAttrs(AttrFactory); + LocalAttrs.takeAllFrom(Attrs); + ParsingDeclarator D(*this, DS, LocalAttrs, Context); ParseDeclarator(D); // Bail out if the first declarator didn't seem well-formed. @@ -2869,6 +2891,8 @@ Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) { if (Context == DeclaratorContext::AliasDecl || Context == DeclaratorContext::AliasTemplate) return DeclSpecContext::DSC_alias_declaration; + if (Context == DeclaratorContext::Association) + return DeclSpecContext::DSC_association; return DeclSpecContext::DSC_normal; } @@ -3173,10 +3197,30 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (!AttrsLastTime) ProhibitAttributes(attrs); else { - // Reject C++11 attributes that appertain to decl specifiers as - // we don't support any C++11 attributes that appertain to decl - // specifiers. This also conforms to what g++ 4.8 is doing. - ProhibitCXX11Attributes(attrs, diag::err_attribute_not_type_attr); + // Reject C++11 / C2x attributes that aren't type attributes. + for (const ParsedAttr &PA : attrs) { + if (!PA.isCXX11Attribute() && !PA.isC2xAttribute()) + continue; + if (PA.getKind() == ParsedAttr::UnknownAttribute) + // We will warn about the unknown attribute elsewhere (in + // SemaDeclAttr.cpp) + continue; + // GCC ignores this attribute when placed on the DeclSpec in [[]] + // syntax, so we do the same. + if (PA.getKind() == ParsedAttr::AT_VectorSize) { + Diag(PA.getLoc(), diag::warn_attribute_ignored) << PA; + PA.setInvalid(); + continue; + } + // We reject AT_LifetimeBound and AT_AnyX86NoCfCheck, even though they + // are type attributes, because we historically haven't allowed these + // to be used as type attributes in C++11 / C2x syntax. + if (PA.isTypeAttr() && PA.getKind() != ParsedAttr::AT_LifetimeBound && + PA.getKind() != ParsedAttr::AT_AnyX86NoCfCheck) + continue; + Diag(PA.getLoc(), diag::err_attribute_not_type_attr) << PA; + PA.setInvalid(); + } DS.takeAttributesFrom(attrs); } @@ -4301,7 +4345,6 @@ void Parser::ParseStructDeclaration( // Parse leading attributes. ParsedAttributes Attrs(AttrFactory); MaybeParseCXX11Attributes(Attrs); - DS.takeAttributesFrom(Attrs); // Parse the common specifier-qualifiers-list piece. ParseSpecifierQualifierList(DS); @@ -4309,6 +4352,11 @@ void Parser::ParseStructDeclaration( // If there are no declarators, this is a free-standing declaration // specifier. Let the actions module cope with it. if (Tok.is(tok::semi)) { + // C2x 6.7.2.1p9 : "The optional attribute specifier sequence in a + // member declaration appertains to each of the members declared by the + // member declarator list; it shall not appear if the optional member + // declarator list is omitted." + ProhibitAttributes(Attrs); RecordDecl *AnonRecord = nullptr; Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none, DS, AnonRecord); @@ -4321,7 +4369,7 @@ void Parser::ParseStructDeclaration( bool FirstDeclarator = true; SourceLocation CommaLoc; while (true) { - ParsingFieldDeclarator DeclaratorInfo(*this, DS); + ParsingFieldDeclarator DeclaratorInfo(*this, DS, Attrs); DeclaratorInfo.D.setCommaLoc(CommaLoc); // Attributes are only allowed here on successive declarators. @@ -4487,8 +4535,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, // If attributes exist after struct contents, parse them. MaybeParseGNUAttributes(attrs); - SmallVector FieldDecls(TagDecl->field_begin(), - TagDecl->field_end()); + SmallVector FieldDecls(TagDecl->fields()); Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls, T.getOpenLocation(), T.getCloseLocation(), attrs); @@ -4572,7 +4619,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // Determine whether this declaration is permitted to have an enum-base. AllowDefiningTypeSpec AllowEnumSpecifier = - isDefiningTypeSpecifierContext(DSC); + isDefiningTypeSpecifierContext(DSC, getLangOpts().CPlusPlus); bool CanBeOpaqueEnumDeclaration = DS.isEmpty() && isOpaqueEnumDeclarationContext(DSC); bool CanHaveEnumBase = (getLangOpts().CPlusPlus11 || getLangOpts().ObjC || @@ -4681,7 +4728,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // declares 'enum E : int; E *p;' not 'enum E : int*; E p;'. DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS, AS, DeclSpecContext::DSC_type_specifier); - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); BaseType = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); BaseRange = SourceRange(ColonLoc, DeclaratorInfo.getSourceRange().getEnd()); @@ -6603,9 +6651,9 @@ void Parser::InitCXXThisScopeForDeclaratorIfRelevant( /// declarator D up to a paren, which indicates that we are parsing function /// arguments. /// -/// If FirstArgAttrs is non-null, then the caller parsed those arguments -/// immediately after the open paren - they should be considered to be the -/// first argument of a parameter. +/// If FirstArgAttrs is non-null, then the caller parsed those attributes +/// immediately after the open paren - they will be applied to the DeclSpec +/// of the first parameter. /// /// If RequiresArg is true, then the first argument of the function is required /// to be present and required to not be an identifier list. @@ -6907,7 +6955,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList( /// /// DeclContext is the context of the declarator being parsed. If FirstArgAttrs /// is non-null, then the caller parsed those attributes immediately after the -/// open paren - they should be considered to be part of the first parameter. +/// open paren - they will be applied to the DeclSpec of the first parameter. /// /// After returning, ParamInfo will hold the parsed parameters. EllipsisLoc will /// be the location of the ellipsis, if any was parsed. @@ -6959,33 +7007,37 @@ void Parser::ParseParameterDeclarationClause( // Just use the ParsingDeclaration "scope" of the declarator. DeclSpec DS(AttrFactory); - // Parse any C++11 attributes. - MaybeParseCXX11Attributes(DS.getAttributes()); + ParsedAttributes ArgDeclAttrs(AttrFactory); + ParsedAttributes ArgDeclSpecAttrs(AttrFactory); - // Skip any Microsoft attributes before a param. - MaybeParseMicrosoftAttributes(DS.getAttributes()); + if (FirstArgAttrs.Range.isValid()) { + // If the caller parsed attributes for the first argument, add them now. + // Take them so that we only apply the attributes to the first parameter. + // We have already started parsing the decl-specifier sequence, so don't + // parse any parameter-declaration pieces that precede it. + ArgDeclSpecAttrs.takeAllFrom(FirstArgAttrs); + } else { + // Parse any C++11 attributes. + MaybeParseCXX11Attributes(ArgDeclAttrs); - SourceLocation DSStart = Tok.getLocation(); + // Skip any Microsoft attributes before a param. + MaybeParseMicrosoftAttributes(ArgDeclSpecAttrs); + } - // If the caller parsed attributes for the first argument, add them now. - // Take them so that we only apply the attributes to the first parameter. - // FIXME: If we can leave the attributes in the token stream somehow, we can - // get rid of a parameter (FirstArgAttrs) and this statement. It might be - // too much hassle. - DS.takeAttributesFrom(FirstArgAttrs); + SourceLocation DSStart = Tok.getLocation(); ParseDeclarationSpecifiers(DS); - + DS.takeAttributesFrom(ArgDeclSpecAttrs); // Parse the declarator. This is "PrototypeContext" or // "LambdaExprParameterContext", because we must accept either // 'declarator' or 'abstract-declarator' here. - Declarator ParmDeclarator( - DS, DeclaratorCtx == DeclaratorContext::RequiresExpr - ? DeclaratorContext::RequiresExpr - : DeclaratorCtx == DeclaratorContext::LambdaExpr - ? DeclaratorContext::LambdaExprParameter - : DeclaratorContext::Prototype); + Declarator ParmDeclarator(DS, ArgDeclAttrs, + DeclaratorCtx == DeclaratorContext::RequiresExpr + ? DeclaratorContext::RequiresExpr + : DeclaratorCtx == DeclaratorContext::LambdaExpr + ? DeclaratorContext::LambdaExprParameter + : DeclaratorContext::Prototype); ParseDeclarator(ParmDeclarator); // Parse GNU attributes, if present. @@ -7284,7 +7336,8 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) { assert(!D.mayOmitIdentifier() && "Declarator cannot omit identifier"); SourceLocation StartBracketLoc = Tok.getLocation(); - Declarator TempDeclarator(D.getDeclSpec(), D.getContext()); + Declarator TempDeclarator(D.getDeclSpec(), ParsedAttributesView::none(), + D.getContext()); while (Tok.is(tok::l_square)) { ParseBracketDeclarator(TempDeclarator); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 5ed989f17c1bc..8b55b4c57aa65 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -10,15 +10,16 @@ // //===----------------------------------------------------------------------===// -#include "clang/Parse/Parser.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/PrettyDeclStackTrace.h" +#include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/TargetInfo.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" @@ -354,8 +355,8 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { getCurScope(), DS.getSourceRange().getBegin(), Lang.get(), Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation()); - ParsedAttributes attrs(AttrFactory); - MaybeParseCXX11Attributes(attrs); + ParsedAttributes DeclAttrs(AttrFactory); + MaybeParseCXX11Attributes(DeclAttrs); if (Tok.isNot(tok::l_brace)) { // Reset the source range in DS, as the leading "extern" @@ -364,7 +365,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { DS.SetRangeEnd(SourceLocation()); // ... but anyway remember that such an "extern" was seen. DS.setExternInLinkageSpec(true); - ParseExternalDeclaration(attrs, &DS); + ParseExternalDeclaration(DeclAttrs, &DS); return LinkageSpec ? Actions.ActOnFinishLinkageSpecification( getCurScope(), LinkageSpec, SourceLocation()) : nullptr; @@ -372,7 +373,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { DS.abort(); - ProhibitAttributes(attrs); + ProhibitAttributes(DeclAttrs); BalancedDelimiterTracker T(*this, tok::l_brace); T.consumeOpen(); @@ -1216,7 +1217,8 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, EndLocation = ParseDecltypeSpecifier(DS); - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); } @@ -1308,7 +1310,8 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type, Actions.getASTContext().getPrintingPolicy()); - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); } @@ -1751,11 +1754,13 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); Sema::TagUseKind TUK; - if (isDefiningTypeSpecifierContext(DSC) == AllowDefiningTypeSpec::No || + if (isDefiningTypeSpecifierContext(DSC, getLangOpts().CPlusPlus) == + AllowDefiningTypeSpec::No || (getLangOpts().OpenMP && OpenMPDirectiveParsing)) TUK = Sema::TUK_Reference; else if (Tok.is(tok::l_brace) || - (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || + (DSC != DeclSpecContext::DSC_association && + getLangOpts().CPlusPlus && Tok.is(tok::colon)) || (isClassCompatibleKeyword() && (NextToken().is(tok::l_brace) || NextToken().is(tok::colon)))) { if (DS.isFriendSpecified()) { @@ -2677,23 +2682,15 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, TemplateInfo, TemplateDiags); } - ParsedAttributes attrs(AttrFactory); - ParsedAttributesView FnAttrs; + ParsedAttributes DeclAttrs(AttrFactory); // Optional C++11 attribute-specifier - MaybeParseCXX11Attributes(attrs); + MaybeParseCXX11Attributes(DeclAttrs); // The next token may be an OpenMP pragma annotation token. That would // normally be handled from ParseCXXClassMemberDeclarationWithPragmas, but in // this case, it came from an *attribute* rather than a pragma. Handle it now. if (Tok.is(tok::annot_attr_openmp)) - return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, attrs); - - // We need to keep these attributes for future diagnostic - // before they are taken over by declaration specifier. - FnAttrs.addAll(attrs.begin(), attrs.end()); - FnAttrs.Range = attrs.Range; - - MaybeParseMicrosoftAttributes(attrs); + return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, DeclAttrs); if (Tok.is(tok::kw_using)) { // Eat 'using'. @@ -2714,16 +2711,20 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SourceLocation DeclEnd; // Otherwise, it must be a using-declaration or an alias-declaration. return ParseUsingDeclaration(DeclaratorContext::Member, TemplateInfo, - UsingLoc, DeclEnd, attrs, AS); + UsingLoc, DeclEnd, DeclAttrs, AS); } + ParsedAttributes DeclSpecAttrs(AttrFactory); + MaybeParseMicrosoftAttributes(DeclSpecAttrs); + // Hold late-parsed attributes so we can attach a Decl to them later. LateParsedAttrList CommonLateParsedAttrs; // decl-specifier-seq: // Parse the common declaration-specifiers piece. ParsingDeclSpec DS(*this, TemplateDiags); - DS.takeAttributesFrom(attrs); + DS.takeAttributesFrom(DeclSpecAttrs); + if (MalformedTypeSpec) DS.SetTypeSpecError(); @@ -2761,7 +2762,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (TryConsumeToken(tok::semi)) { if (DS.isFriendSpecified()) - ProhibitAttributes(FnAttrs); + ProhibitAttributes(DeclAttrs); RecordDecl *AnonRecord = nullptr; Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec( @@ -2774,7 +2775,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, return Actions.ConvertDeclToDeclGroup(TheDecl); } - ParsingDeclarator DeclaratorInfo(*this, DS, DeclaratorContext::Member); + ParsingDeclarator DeclaratorInfo(*this, DS, DeclAttrs, + DeclaratorContext::Member); if (TemplateInfo.TemplateParams) DeclaratorInfo.setTemplateParameterLists(TemplateParams); VirtSpecifiers VS; @@ -2866,7 +2868,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DS.isFriendSpecified()) { // Diagnose attributes that appear before decl specifier: // [[]] friend int foo(); - ProhibitAttributes(FnAttrs); + ProhibitAttributes(DeclAttrs); } if (DefinitionKind != FunctionDefinitionKind::Declaration) { @@ -4308,16 +4310,17 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, // Try parsing microsoft attributes if (getLangOpts().MicrosoftExt || getLangOpts().HLSL) { - if (hasAttribute(AttrSyntax::Microsoft, ScopeName, AttrName, - getTargetInfo(), getLangOpts())) + if (hasAttribute(AttributeCommonInfo::Syntax::AS_Microsoft, ScopeName, + AttrName, getTargetInfo(), getLangOpts())) Syntax = ParsedAttr::AS_Microsoft; } // If the attribute isn't known, we will not attempt to parse any // arguments. if (Syntax != ParsedAttr::AS_Microsoft && - !hasAttribute(LO.CPlusPlus ? AttrSyntax::CXX : AttrSyntax::C, ScopeName, - AttrName, getTargetInfo(), getLangOpts())) { + !hasAttribute(LO.CPlusPlus ? AttributeCommonInfo::Syntax::AS_CXX11 + : AttributeCommonInfo::Syntax::AS_C2x, + ScopeName, AttrName, getTargetInfo(), getLangOpts())) { if (getLangOpts().MicrosoftExt || getLangOpts().HLSL) {} // Eat the left paren, then skip to the ending right paren. ConsumeParen(); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 54ba115a65f98..a6a946d7f31b1 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1212,7 +1212,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ, Actions.getASTContext().getPrintingPolicy()); - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); if (Ty.isInvalid()) @@ -1490,7 +1491,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, PrevSpec, DiagID, Type, Actions.getASTContext().getPrintingPolicy()); - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); if (Ty.isInvalid()) break; @@ -2296,7 +2298,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, if (isTypeIdUnambiguously()) { DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); ParseDeclarator(DeclaratorInfo); SourceLocation LParenLoc = PP.getLocForEndOfToken(OpTok.getLocation()); @@ -2870,7 +2873,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // None of these cases should fall through with an invalid Result // unless they've already reported an error. if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) { - Diag(Tok, diag::ext_gnu_statement_expr); + Diag(Tok, OpenLoc.isMacroID() ? diag::ext_gnu_statement_expr_macro + : diag::ext_gnu_statement_expr); checkCompoundToken(OpenLoc, tok::l_paren, CompoundToken::StmtExprBegin); @@ -2958,7 +2962,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // Parse the type declarator. DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); ParseDeclarator(DeclaratorInfo); // If our type is followed by an identifier and either ':' or ']', then @@ -3275,7 +3280,7 @@ ExprResult Parser::ParseGenericSelectionExpression() { Ty = nullptr; } else { ColonProtectionRAIIObject X(*this); - TypeResult TR = ParseTypeName(); + TypeResult TR = ParseTypeName(nullptr, DeclaratorContext::Association); if (TR.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); @@ -3493,7 +3498,8 @@ void Parser::ParseBlockId(SourceLocation CaretLoc) { ParseSpecifierQualifierList(DS); // Parse the block-declarator. - Declarator DeclaratorInfo(DS, DeclaratorContext::BlockLiteral); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::BlockLiteral); DeclaratorInfo.setFunctionDefinitionKind(FunctionDefinitionKind::Definition); ParseDeclarator(DeclaratorInfo); @@ -3532,7 +3538,8 @@ ExprResult Parser::ParseBlockLiteralExpression() { // Parse the return type if present. DeclSpec DS(AttrFactory); - Declarator ParamInfo(DS, DeclaratorContext::BlockLiteral); + Declarator ParamInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::BlockLiteral); ParamInfo.setFunctionDefinitionKind(FunctionDefinitionKind::Definition); // FIXME: Since the return type isn't actually parsed, it can't be used to // fill ParamInfo with an initial valid range, so do it manually. diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 7b66f6c46339a..9bd89eddb4551 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -453,8 +453,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier( bool IsCorrectedToColon = false; bool *CorrectionFlagPtr = ColonIsSacred ? &IsCorrectedToColon : nullptr; if (Actions.ActOnCXXNestedNameSpecifier( - getCurScope(), IdInfo, EnteringContext, SS, false, - CorrectionFlagPtr, OnlyNamespace)) { + getCurScope(), IdInfo, EnteringContext, SS, CorrectionFlagPtr, + OnlyNamespace)) { // Identifier is not recognized as a nested name, but we can have // mistyped '::' instead of ':'. if (CorrectionFlagPtr && IsCorrectedToColon) { @@ -1248,7 +1248,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // Parse lambda-declarator[opt]. DeclSpec DS(AttrFactory); - Declarator D(DS, DeclaratorContext::LambdaExpr); + Declarator D(DS, ParsedAttributesView::none(), DeclaratorContext::LambdaExpr); TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); Actions.PushLambdaScope(); @@ -1523,7 +1523,8 @@ ExprResult Parser::ParseCXXCasts() { ParseSpecifierQualifierList(DS); // Parse the abstract-declarator, if present. - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); ParseDeclarator(DeclaratorInfo); SourceLocation RAngleBracketLoc = Tok.getLocation(); @@ -1849,7 +1850,8 @@ ExprResult Parser::ParseCXXThis() { /// In C++1z onwards, the type specifier can also be a template-name. ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { - Declarator DeclaratorInfo(DS, DeclaratorContext::FunctionalCast); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::FunctionalCast); ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); assert((Tok.is(tok::l_paren) || @@ -2048,9 +2050,11 @@ Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc, if (Tok.is(tok::kw_using)) DG = ParseAliasDeclarationInInitStatement( DeclaratorContext::SelectionInit, attrs); - else + else { + ParsedAttributes DeclSpecAttrs(AttrFactory); DG = ParseSimpleDeclaration(DeclaratorContext::SelectionInit, DeclEnd, - attrs, /*RequireSemi=*/true); + attrs, DeclSpecAttrs, /*RequireSemi=*/true); + } *InitStmt = Actions.ActOnDeclStmt(DG, DeclStart, DeclEnd); return ParseCXXCondition(nullptr, Loc, CK, MissingOK); } @@ -2061,8 +2065,9 @@ Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc, // permitted here. assert(FRI && "should not parse a for range declaration here"); SourceLocation DeclStart = Tok.getLocation(), DeclEnd; - DeclGroupPtrTy DG = ParseSimpleDeclaration(DeclaratorContext::ForInit, - DeclEnd, attrs, false, FRI); + ParsedAttributes DeclSpecAttrs(AttrFactory); + DeclGroupPtrTy DG = ParseSimpleDeclaration( + DeclaratorContext::ForInit, DeclEnd, attrs, DeclSpecAttrs, false, FRI); FRI->LoopVar = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); assert((FRI->ColonLoc.isValid() || !DG) && "cannot find for range declaration"); @@ -2079,11 +2084,10 @@ Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc, // type-specifier-seq DeclSpec DS(AttrFactory); - DS.takeAttributesFrom(attrs); ParseSpecifierQualifierList(DS, AS_none, DeclSpecContext::DSC_condition); // declarator - Declarator DeclaratorInfo(DS, DeclaratorContext::Condition); + Declarator DeclaratorInfo(DS, attrs, DeclaratorContext::Condition); ParseDeclarator(DeclaratorInfo); // simple-asm-expr[opt] @@ -2736,7 +2740,8 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // Parse the conversion-declarator, which is merely a sequence of // ptr-operators. - Declarator D(DS, DeclaratorContext::ConversionId); + Declarator D(DS, ParsedAttributesView::none(), + DeclaratorContext::ConversionId); ParseDeclaratorInternal(D, /*DirectDeclParser=*/nullptr); // Finish up the type. @@ -3094,7 +3099,8 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { SourceRange TypeIdParens; DeclSpec DS(AttrFactory); - Declarator DeclaratorInfo(DS, DeclaratorContext::CXXNew); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::CXXNew); if (Tok.is(tok::l_paren)) { // If it turns out to be a placement, we change the type location. BalancedDelimiterTracker T(*this, tok::l_paren); @@ -3945,7 +3951,8 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, if (ParseAs >= CompoundLiteral) { // Parse the type declarator. DeclSpec DS(AttrFactory); - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); { ColonProtectionRAIIObject InnerColonProtection(*this); ParseSpecifierQualifierList(DS); @@ -4023,7 +4030,8 @@ ExprResult Parser::ParseBuiltinBitCast() { ParseSpecifierQualifierList(DS); // Parse the abstract-declarator, if present. - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); ParseDeclarator(DeclaratorInfo); if (ExpectAndConsume(tok::comma)) { diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 15cec81ef1b3f..734c66f65dc29 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -650,19 +650,21 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, if (Tok.is(tok::r_brace)) break; - ParsedAttributes attrs(AttrFactory); + ParsedAttributes EmptyAttrs(AttrFactory); // Since we call ParseDeclarationOrFunctionDefinition() instead of // ParseExternalDeclaration() below (so that this doesn't parse nested // @interfaces), this needs to duplicate some code from the latter. if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) { SourceLocation DeclEnd; - allTUVariables.push_back( - ParseDeclaration(DeclaratorContext::File, DeclEnd, attrs)); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); + allTUVariables.push_back(ParseDeclaration( + DeclaratorContext::File, DeclEnd, EmptyAttrs, EmptyDeclSpecAttrs)); continue; } - allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs)); + allTUVariables.push_back( + ParseDeclarationOrFunctionDefinition(EmptyAttrs)); continue; } @@ -1225,6 +1227,10 @@ static void takeDeclAttributes(ParsedAttributesView &attrs, /// declarator and add them to the given list. static void takeDeclAttributes(ParsedAttributes &attrs, Declarator &D) { + // This gets called only from Parser::ParseObjCTypeName(), and that should + // never add declaration attributes to the Declarator. + assert(D.getDeclarationAttributes().empty()); + // First, take ownership of all attributes. attrs.getPool().takeAllFrom(D.getAttributePool()); attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool()); @@ -1268,7 +1274,7 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, if (context == DeclaratorContext::ObjCResult) dsContext = DeclSpecContext::DSC_objc_method_result; ParseSpecifierQualifierList(declSpec, AS_none, dsContext); - Declarator declarator(declSpec, context); + Declarator declarator(declSpec, ParsedAttributesView::none(), context); ParseDeclarator(declarator); // If that's not invalid, extract a type. @@ -1487,7 +1493,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, DeclSpec DS(AttrFactory); ParseDeclarationSpecifiers(DS); // Parse the declarator. - Declarator ParmDecl(DS, DeclaratorContext::Prototype); + Declarator ParmDecl(DS, ParsedAttributesView::none(), + DeclaratorContext::Prototype); ParseDeclarator(ParmDecl); IdentifierInfo *ParmII = ParmDecl.getIdentifier(); Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl); @@ -1693,7 +1700,8 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers( typeArg, Actions.getASTContext().getPrintingPolicy()); // Form a declarator to turn this into a type. - Declarator D(DS, DeclaratorContext::TypeName); + Declarator D(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); TypeResult fullTypeArg = Actions.ActOnTypeName(getCurScope(), D); if (fullTypeArg.isUsable()) { typeArgs.push_back(fullTypeArg.get()); @@ -2538,7 +2546,8 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { if (Tok.isNot(tok::ellipsis)) { DeclSpec DS(AttrFactory); ParseDeclarationSpecifiers(DS); - Declarator ParmDecl(DS, DeclaratorContext::ObjCCatch); + Declarator ParmDecl(DS, ParsedAttributesView::none(), + DeclaratorContext::ObjCCatch); ParseDeclarator(ParmDecl); // Inform the actions module about the declarator, so it @@ -2954,7 +2963,8 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { // We have a class message. Turn the simple-type-specifier or // typename-specifier we parsed into a type and parse the // remainder of the class message. - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); TypeResult Type = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); if (Type.isInvalid()) return true; diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 0385d5f1586e9..e8d0c1528b526 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -639,7 +639,7 @@ TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range, // Parse the declarator. DeclaratorContext Context = DeclaratorContext::Prototype; - Declarator DeclaratorInfo(DS, Context); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context); ParseDeclarator(DeclaratorInfo); Range = DeclaratorInfo.getSourceRange(); if (DeclaratorInfo.getIdentifier() == nullptr) { diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index f8e311c7c35ad..c94640c31c500 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -3027,14 +3027,6 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP, return; } - // On PS4, issue a warning about any pragma comments other than - // #pragma comment lib. - if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) { - PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored) - << II->getName(); - return; - } - // Read the optional string if present. PP.Lex(Tok); std::string ArgumentString; diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index ce5541a966d17..f43e5b4c8922a 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -105,15 +105,21 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, // statement are different from [[]] attributes that follow an __attribute__ // at the start of the statement. Thus, we're not using MaybeParseAttributes // here because we don't want to allow arbitrary orderings. - ParsedAttributes Attrs(AttrFactory); - MaybeParseCXX11Attributes(Attrs, /*MightBeObjCMessageSend*/ true); + ParsedAttributes CXX11Attrs(AttrFactory); + MaybeParseCXX11Attributes(CXX11Attrs, /*MightBeObjCMessageSend*/ true); + ParsedAttributes GNUAttrs(AttrFactory); if (getLangOpts().OpenCL) - MaybeParseGNUAttributes(Attrs); + MaybeParseGNUAttributes(GNUAttrs); StmtResult Res = ParseStatementOrDeclarationAfterAttributes( - Stmts, StmtCtx, TrailingElseLoc, Attrs); + Stmts, StmtCtx, TrailingElseLoc, CXX11Attrs, GNUAttrs); MaybeDestroyTemplateIds(); + // Attributes that are left should all go on the statement, so concatenate the + // two lists. + ParsedAttributes Attrs(AttrFactory); + takeAndConcatenateAttrs(CXX11Attrs, GNUAttrs, Attrs); + assert((Attrs.empty() || Res.isInvalid() || Res.isUsable()) && "attributes on empty statement"); @@ -158,7 +164,8 @@ class StatementFilterCCC final : public CorrectionCandidateCallback { StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( StmtVector &Stmts, ParsedStmtContext StmtCtx, - SourceLocation *TrailingElseLoc, ParsedAttributes &Attrs) { + SourceLocation *TrailingElseLoc, ParsedAttributes &CXX11Attrs, + ParsedAttributes &GNUAttrs) { const char *SemiError = nullptr; StmtResult Res; SourceLocation GNUAttributeLoc; @@ -184,6 +191,12 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( case tok::identifier: { Token Next = NextToken(); if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement + // Both C++11 and GNU attributes preceding the label appertain to the + // label, so put them in a single list to pass on to + // ParseLabeledStatement(). + ParsedAttributes Attrs(AttrFactory); + takeAndConcatenateAttrs(CXX11Attrs, GNUAttrs, Attrs); + // identifier ':' statement return ParseLabeledStatement(Attrs, StmtCtx); } @@ -213,25 +226,33 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( } default: { + bool HaveAttrs = !CXX11Attrs.empty() || !GNUAttrs.empty(); + auto IsStmtAttr = [](ParsedAttr &Attr) { return Attr.isStmtAttr(); }; + bool AllAttrsAreStmtAttrs = llvm::all_of(CXX11Attrs, IsStmtAttr) && + llvm::all_of(GNUAttrs, IsStmtAttr); if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt || (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) != ParsedStmtContext()) && - ((GNUAttributeLoc.isValid() && - !(!Attrs.empty() && - llvm::all_of( - Attrs, [](ParsedAttr &Attr) { return Attr.isStmtAttr(); }))) || + ((GNUAttributeLoc.isValid() && !(HaveAttrs && AllAttrsAreStmtAttrs)) || isDeclarationStatement())) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; DeclGroupPtrTy Decl; if (GNUAttributeLoc.isValid()) { DeclStart = GNUAttributeLoc; - Decl = ParseDeclaration(DeclaratorContext::Block, DeclEnd, Attrs, - &GNUAttributeLoc); + Decl = ParseDeclaration(DeclaratorContext::Block, DeclEnd, CXX11Attrs, + GNUAttrs, &GNUAttributeLoc); } else { - Decl = ParseDeclaration(DeclaratorContext::Block, DeclEnd, Attrs); + Decl = ParseDeclaration(DeclaratorContext::Block, DeclEnd, CXX11Attrs, + GNUAttrs); } - if (Attrs.Range.getBegin().isValid()) - DeclStart = Attrs.Range.getBegin(); + if (CXX11Attrs.Range.getBegin().isValid()) { + // The caller must guarantee that the CXX11Attrs appear before the + // GNUAttrs, and we rely on that here. + assert(GNUAttrs.Range.getBegin().isInvalid() || + GNUAttrs.Range.getBegin() > CXX11Attrs.Range.getBegin()); + DeclStart = CXX11Attrs.Range.getBegin(); + } else if (GNUAttrs.Range.getBegin().isValid()) + DeclStart = GNUAttrs.Range.getBegin(); return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd); } @@ -245,7 +266,7 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( case tok::kw___attribute: { GNUAttributeLoc = Tok.getLocation(); - ParseGNUAttributes(Attrs); + ParseGNUAttributes(GNUAttrs); goto Retry; } @@ -297,7 +318,11 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( break; case tok::kw_asm: { - ProhibitAttributes(Attrs); + for (const ParsedAttr &AL : CXX11Attrs) + Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored) << AL; + // Prevent these from being interpreted as statement attributes later on. + CXX11Attrs.clear(); + ProhibitAttributes(GNUAttrs); bool msAsm = false; Res = ParseAsmStatement(msAsm); Res = Actions.ActOnFinishFullStmt(Res.get()); @@ -308,7 +333,8 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( case tok::kw___if_exists: case tok::kw___if_not_exists: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); ParseMicrosoftIfExistsStatement(Stmts); // An __if_exists block is like a compound statement, but it doesn't create // a new scope. @@ -318,7 +344,8 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( return ParseCXXTryBlock(); case tok::kw___try: - ProhibitAttributes(Attrs); // TODO: is it correct? + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); return ParseSEHTryBlock(); case tok::kw___leave: @@ -327,55 +354,65 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( break; case tok::annot_pragma_vis: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); HandlePragmaVisibility(); return StmtEmpty(); case tok::annot_pragma_pack: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); HandlePragmaPack(); return StmtEmpty(); case tok::annot_pragma_msstruct: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); HandlePragmaMSStruct(); return StmtEmpty(); case tok::annot_pragma_align: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); HandlePragmaAlign(); return StmtEmpty(); case tok::annot_pragma_weak: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); HandlePragmaWeak(); return StmtEmpty(); case tok::annot_pragma_weakalias: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); HandlePragmaWeakAlias(); return StmtEmpty(); case tok::annot_pragma_redefine_extname: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); HandlePragmaRedefineExtname(); return StmtEmpty(); case tok::annot_pragma_fp_contract: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); Diag(Tok, diag::err_pragma_file_or_compound_scope) << "fp_contract"; ConsumeAnnotationToken(); return StmtError(); case tok::annot_pragma_fp: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); Diag(Tok, diag::err_pragma_file_or_compound_scope) << "clang fp"; ConsumeAnnotationToken(); return StmtError(); case tok::annot_pragma_fenv_access: case tok::annot_pragma_fenv_access_ms: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); Diag(Tok, diag::err_pragma_file_or_compound_scope) << (Kind == tok::annot_pragma_fenv_access ? "STDC FENV_ACCESS" : "fenv_access"); @@ -383,53 +420,62 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( return StmtEmpty(); case tok::annot_pragma_fenv_round: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); Diag(Tok, diag::err_pragma_file_or_compound_scope) << "STDC FENV_ROUND"; ConsumeAnnotationToken(); return StmtError(); case tok::annot_pragma_float_control: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); Diag(Tok, diag::err_pragma_file_or_compound_scope) << "float_control"; ConsumeAnnotationToken(); return StmtError(); case tok::annot_pragma_opencl_extension: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); HandlePragmaOpenCLExtension(); return StmtEmpty(); case tok::annot_pragma_captured: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); return HandlePragmaCaptured(); case tok::annot_pragma_openmp: // Prohibit attributes that are not OpenMP attributes, but only before // processing a #pragma omp clause. - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); LLVM_FALLTHROUGH; case tok::annot_attr_openmp: // Do not prohibit attributes if they were OpenMP attributes. return ParseOpenMPDeclarativeOrExecutableDirective(StmtCtx); case tok::annot_pragma_ms_pointers_to_members: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); HandlePragmaMSPointersToMembers(); return StmtEmpty(); case tok::annot_pragma_ms_pragma: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); HandlePragmaMSPragma(); return StmtEmpty(); case tok::annot_pragma_ms_vtordisp: - ProhibitAttributes(Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); HandlePragmaMSVtorDisp(); return StmtEmpty(); case tok::annot_pragma_loop_hint: - ProhibitAttributes(Attrs); - return ParsePragmaLoopHint(Stmts, StmtCtx, TrailingElseLoc, Attrs); + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); + return ParsePragmaLoopHint(Stmts, StmtCtx, TrailingElseLoc, CXX11Attrs); case tok::annot_pragma_dump: HandlePragmaDump(); @@ -658,8 +704,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs, Attrs.takeAllFrom(TempAttrs); else { StmtVector Stmts; - SubStmt = ParseStatementOrDeclarationAfterAttributes(Stmts, StmtCtx, - nullptr, TempAttrs); + ParsedAttributes EmptyCXX11Attrs(AttrFactory); + SubStmt = ParseStatementOrDeclarationAfterAttributes( + Stmts, StmtCtx, nullptr, EmptyCXX11Attrs, TempAttrs); if (!TempAttrs.empty() && !SubStmt.isInvalid()) SubStmt = Actions.ActOnAttributedStmt(TempAttrs, SubStmt.get()); } @@ -1128,8 +1175,9 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { ExtensionRAIIObject O(Diags); SourceLocation DeclStart = Tok.getLocation(), DeclEnd; - DeclGroupPtrTy Res = - ParseDeclaration(DeclaratorContext::Block, DeclEnd, attrs); + ParsedAttributes DeclSpecAttrs(AttrFactory); + DeclGroupPtrTy Res = ParseDeclaration(DeclaratorContext::Block, DeclEnd, + attrs, DeclSpecAttrs); R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd); } else { // Otherwise this was a unary __extension__ marker. @@ -1975,8 +2023,9 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt); SourceLocation DeclStart = Tok.getLocation(), DeclEnd; + ParsedAttributes DeclSpecAttrs(AttrFactory); DG = ParseSimpleDeclaration( - DeclaratorContext::ForInit, DeclEnd, attrs, false, + DeclaratorContext::ForInit, DeclEnd, attrs, DeclSpecAttrs, false, MightBeForRangeStmt ? &ForRangeInfo : nullptr); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); if (ForRangeInfo.ParsedForRangeDecl()) { @@ -2347,8 +2396,9 @@ StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, // Get the next statement. MaybeParseCXX11Attributes(Attrs); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); StmtResult S = ParseStatementOrDeclarationAfterAttributes( - Stmts, StmtCtx, TrailingElseLoc, Attrs); + Stmts, StmtCtx, TrailingElseLoc, Attrs, EmptyDeclSpecAttrs); Attrs.takeAllFrom(TempAttrs); @@ -2584,12 +2634,11 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) { MaybeParseCXX11Attributes(Attributes); DeclSpec DS(AttrFactory); - DS.takeAttributesFrom(Attributes); if (ParseCXXTypeSpecifierSeq(DS)) return StmtError(); - Declarator ExDecl(DS, DeclaratorContext::CXXCatch); + Declarator ExDecl(DS, Attributes, DeclaratorContext::CXXCatch); ParseDeclarator(ExDecl); ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl); } else diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index e66329e3bfc7e..97be8115989e2 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -245,11 +245,10 @@ Decl *Parser::ParseSingleDeclarationAfterTemplate( // Move the attributes from the prefix into the DS. if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) ProhibitAttributes(prefixAttrs); - else - DS.takeAttributesFrom(prefixAttrs); // Parse the declarator. - ParsingDeclarator DeclaratorInfo(*this, DS, (DeclaratorContext)Context); + ParsingDeclarator DeclaratorInfo(*this, DS, prefixAttrs, + (DeclaratorContext)Context); if (TemplateInfo.TemplateParams) DeclaratorInfo.setTemplateParameterLists(*TemplateInfo.TemplateParams); @@ -669,7 +668,8 @@ NamedDecl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) { // probably meant to write the type of a NTTP. DeclSpec DS(getAttrFactory()); DS.SetTypeSpecError(); - Declarator D(DS, DeclaratorContext::TemplateParam); + Declarator D(DS, ParsedAttributesView::none(), + DeclaratorContext::TemplateParam); D.SetIdentifier(nullptr, Tok.getLocation()); D.setInvalidType(true); NamedDecl *ErrorParam = Actions.ActOnNonTypeTemplateParameter( @@ -993,7 +993,8 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { DeclSpecContext::DSC_template_param); // Parse this as a typename. - Declarator ParamDecl(DS, DeclaratorContext::TemplateParam); + Declarator ParamDecl(DS, ParsedAttributesView::none(), + DeclaratorContext::TemplateParam); ParseDeclarator(ParamDecl); if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) { Diag(Tok.getLocation(), diag::err_expected_template_parameter); diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 7ffaf057623f6..7fad3b2388ce3 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -740,6 +740,9 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result, /// ParseExternalDeclaration: /// +/// The `Attrs` that are passed in are C++11 attributes and appertain to the +/// declaration. +/// /// external-declaration: [C99 6.9], declaration: [C++ dcl.dcl] /// function-definition /// declaration @@ -929,7 +932,9 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, // A function definition cannot start with any of these keywords. { SourceLocation DeclEnd; - return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); + return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs, + EmptyDeclSpecAttrs); } case tok::kw_static: @@ -939,7 +944,9 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored) << 0; SourceLocation DeclEnd; - return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); + return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs, + EmptyDeclSpecAttrs); } goto dont_know; @@ -950,7 +957,9 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, // Inline namespaces. Allowed as an extension even in C++03. if (NextKind == tok::kw_namespace) { SourceLocation DeclEnd; - return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); + return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs, + EmptyDeclSpecAttrs); } // Parse (then ignore) 'inline' prior to a template instantiation. This is @@ -959,7 +968,9 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored) << 1; SourceLocation DeclEnd; - return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); + return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs, + EmptyDeclSpecAttrs); } } goto dont_know; @@ -1112,8 +1123,6 @@ Parser::DeclGroupPtrTy Parser::ParseDeclOrFunctionDefInternal( return Actions.ConvertDeclToDeclGroup(TheDecl); } - DS.takeAttributesFrom(Attrs); - // ObjC2 allows prefix attributes on class interfaces and protocols. // FIXME: This still needs better diagnostics. We should only accept // attributes here, no types, etc. @@ -1128,6 +1137,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclOrFunctionDefInternal( } DS.abort(); + DS.takeAttributesFrom(Attrs); const char *PrevSpec = nullptr; unsigned DiagID; @@ -1151,11 +1161,12 @@ Parser::DeclGroupPtrTy Parser::ParseDeclOrFunctionDefInternal( if (getLangOpts().CPlusPlus && isTokenStringLiteral() && DS.getStorageClassSpec() == DeclSpec::SCS_extern && DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) { + ProhibitAttributes(Attrs); Decl *TheDecl = ParseLinkage(DS, DeclaratorContext::File); return Actions.ConvertDeclToDeclGroup(TheDecl); } - return ParseDeclGroup(DS, DeclaratorContext::File); + return ParseDeclGroup(DS, DeclaratorContext::File, Attrs); } Parser::DeclGroupPtrTy Parser::ParseDeclarationOrFunctionDefinition( @@ -1473,7 +1484,8 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { } // Parse the first declarator attached to this declspec. - Declarator ParmDeclarator(DS, DeclaratorContext::KNRTypeList); + Declarator ParmDeclarator(DS, ParsedAttributesView::none(), + DeclaratorContext::KNRTypeList); ParseDeclarator(ParmDeclarator); // Handle the full declarator list. diff --git a/clang/lib/Sema/ParsedAttr.cpp b/clang/lib/Sema/ParsedAttr.cpp index c2742c7db0dca..4b9a694270c59 100644 --- a/clang/lib/Sema/ParsedAttr.cpp +++ b/clang/lib/Sema/ParsedAttr.cpp @@ -212,6 +212,39 @@ bool ParsedAttr::isSupportedByPragmaAttribute() const { return getInfo().IsSupportedByPragmaAttribute; } +bool ParsedAttr::slidesFromDeclToDeclSpecLegacyBehavior() const { + assert(isStandardAttributeSyntax()); + + // We have historically allowed some type attributes with standard attribute + // syntax to slide to the decl-specifier-seq, so we have to keep supporting + // it. This property is consciously not defined as a flag in Attr.td because + // we don't want new attributes to specify it. + // + // Note: No new entries should be added to this list. Entries should be + // removed from this list after a suitable deprecation period, provided that + // there are no compatibility considerations with other compilers. If + // possible, we would like this list to go away entirely. + switch (getParsedKind()) { + case AT_AddressSpace: + case AT_OpenCLPrivateAddressSpace: + case AT_OpenCLGlobalAddressSpace: + case AT_OpenCLGlobalDeviceAddressSpace: + case AT_OpenCLGlobalHostAddressSpace: + case AT_OpenCLLocalAddressSpace: + case AT_OpenCLConstantAddressSpace: + case AT_OpenCLGenericAddressSpace: + case AT_NeonPolyVectorType: + case AT_NeonVectorType: + case AT_ArmMveStrictPolymorphism: + case AT_BTFTypeTag: + case AT_ObjCGC: + case AT_MatrixType: + return true; + default: + return false; + } +} + bool ParsedAttr::acceptsExprPack() const { return getInfo().AcceptsExprPack; } unsigned ParsedAttr::getSemanticSpelling() const { @@ -265,3 +298,20 @@ bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const { diag::err_attribute_too_many_arguments, std::greater()); } + +void clang::takeAndConcatenateAttrs(ParsedAttributes &First, + ParsedAttributes &Second, + ParsedAttributes &Result) { + // Note that takeAllFrom() puts the attributes at the beginning of the list, + // so to obtain the correct ordering, we add `Second`, then `First`. + Result.takeAllFrom(Second); + Result.takeAllFrom(First); + if (First.Range.getBegin().isValid()) + Result.Range.setBegin(First.Range.getBegin()); + else + Result.Range.setBegin(Second.Range.getBegin()); + if (Second.Range.getEnd().isValid()) + Result.Range.setEnd(Second.Range.getEnd()); + else + Result.Range.setEnd(First.Range.getEnd()); +} diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 9681117abe424..840aeb2a440eb 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -384,6 +384,54 @@ void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action, AlignPackStack.Act(PragmaLoc, Action, SlotLabel, Info); } +bool Sema::ConstantFoldAttrArgs(const AttributeCommonInfo &CI, + MutableArrayRef Args) { + llvm::SmallVector Notes; + for (unsigned Idx = 0; Idx < Args.size(); Idx++) { + Expr *&E = Args.begin()[Idx]; + assert(E && "error are handled before"); + if (E->isValueDependent() || E->isTypeDependent()) + continue; + + // FIXME: Use DefaultFunctionArrayLValueConversion() in place of the logic + // that adds implicit casts here. + if (E->getType()->isArrayType()) + E = ImpCastExprToType(E, Context.getPointerType(E->getType()), + clang::CK_ArrayToPointerDecay) + .get(); + if (E->getType()->isFunctionType()) + E = ImplicitCastExpr::Create(Context, + Context.getPointerType(E->getType()), + clang::CK_FunctionToPointerDecay, E, nullptr, + VK_PRValue, FPOptionsOverride()); + if (E->isLValue()) + E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(), + clang::CK_LValueToRValue, E, nullptr, + VK_PRValue, FPOptionsOverride()); + + Expr::EvalResult Eval; + Notes.clear(); + Eval.Diag = &Notes; + + bool Result = E->EvaluateAsConstantExpr(Eval, Context); + + /// Result means the expression can be folded to a constant. + /// Note.empty() means the expression is a valid constant expression in the + /// current language mode. + if (!Result || !Notes.empty()) { + Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type) + << CI << (Idx + 1) << AANT_ArgumentConstantExpr; + for (auto &Note : Notes) + Diag(Note.first, Note.second); + return false; + } + assert(Eval.Val.hasValue()); + E = ConstantExpr::Create(Context, E, Eval.Val); + } + + return true; +} + void Sema::DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind, SourceLocation IncludeLoc) { if (Kind == PragmaAlignPackDiagnoseKind::NonDefaultStateAtInclude) { @@ -763,7 +811,7 @@ void Sema::ActOnPragmaMSAllocText( } DeclContext *DC = ND->getDeclContext(); - if (!DC->isExternCContext()) { + if (getLangOpts().CPlusPlus && !DC->isExternCContext()) { Diag(Loc, diag::err_pragma_alloc_text_c_linkage); return; } diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 4781d71080c98..97783ebd6b530 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -828,10 +828,14 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, } if (!Found.empty()) { - if (TypeDecl *TD = Found.getAsSingle()) + if (TypeDecl *TD = Found.getAsSingle()) { Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace) << Context.getTypeDeclType(TD) << getLangOpts().CPlusPlus; - else { + } else if (Found.getAsSingle()) { + ParsedType SuggestedType; + DiagnoseUnknownTypeName(IdInfo.Identifier, IdInfo.IdentifierLoc, S, &SS, + SuggestedType); + } else { Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace) << IdInfo.Identifier << getLangOpts().CPlusPlus; if (NamedDecl *ND = Found.getAsSingle()) @@ -850,7 +854,6 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, bool EnteringContext, CXXScopeSpec &SS, - bool ErrorRecoveryLookup, bool *IsCorrectedToColon, bool OnlyNamespace) { if (SS.isInvalid()) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 453364c3ac3d9..9cb031b87f3a8 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2265,19 +2265,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, case Builtin::BI__builtin_nontemporal_store: return SemaBuiltinNontemporalOverloaded(TheCallResult); case Builtin::BI__builtin_memcpy_inline: { - if (checkArgCount(*this, TheCall, 3)) - return ExprError(); - auto ArgArrayConversionFailed = [&](unsigned Arg) { - ExprResult ArgExpr = - DefaultFunctionArrayLvalueConversion(TheCall->getArg(Arg)); - if (ArgExpr.isInvalid()) - return true; - TheCall->setArg(Arg, ArgExpr.get()); - return false; - }; - - if (ArgArrayConversionFailed(0) || ArgArrayConversionFailed(1)) - return true; clang::Expr *SizeOp = TheCall->getArg(2); // We warn about copying to or from `nullptr` pointers when `size` is // greater than 0. When `size` is value dependent we cannot evaluate its @@ -2290,6 +2277,17 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, } break; } + case Builtin::BI__builtin_memset_inline: { + clang::Expr *SizeOp = TheCall->getArg(2); + // We warn about filling to `nullptr` pointers when `size` is greater than + // 0. When `size` is value dependent we cannot evaluate its value so we bail + // out. + if (SizeOp->isValueDependent()) + break; + if (!SizeOp->EvaluateKnownConstInt(Context).isZero()) + CheckNonNullArgument(*this, TheCall->getArg(0), TheCall->getExprLoc()); + break; + } #define BUILTIN(ID, TYPE, ATTRS) #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ case Builtin::BI##ID: \ @@ -13576,6 +13574,29 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, const BuiltinType *SourceBT = dyn_cast(Source); const BuiltinType *TargetBT = dyn_cast(Target); + // Strip SVE vector types + if (SourceBT && SourceBT->isVLSTBuiltinType()) { + // Need the original target type for vector type checks + const Type *OriginalTarget = S.Context.getCanonicalType(T).getTypePtr(); + // Handle conversion from scalable to fixed when msve-vector-bits is + // specified + if (S.Context.areCompatibleSveTypes(QualType(OriginalTarget, 0), + QualType(Source, 0)) || + S.Context.areLaxCompatibleSveTypes(QualType(OriginalTarget, 0), + QualType(Source, 0))) + return; + + // If the vector cast is cast between two vectors of the same size, it is + // a bitcast, not a conversion. + if (S.Context.getTypeSize(Source) == S.Context.getTypeSize(Target)) + return; + + Source = SourceBT->getSveEltType(S.Context).getTypePtr(); + } + + if (TargetBT && TargetBT->isVLSTBuiltinType()) + Target = TargetBT->getSveEltType(S.Context).getTypePtr(); + // If the source is floating point... if (SourceBT && SourceBT->isFloatingPoint()) { // ...and the target is floating point... @@ -17734,20 +17755,18 @@ void Sema::CheckTCBEnforcement(const SourceLocation CallExprLoc, // Search through the enforce_tcb and enforce_tcb_leaf attributes to find // all TCBs the callee is a part of. llvm::StringSet<> CalleeTCBs; - for_each(Callee->specific_attrs(), - [&](const auto *A) { CalleeTCBs.insert(A->getTCBName()); }); - for_each(Callee->specific_attrs(), - [&](const auto *A) { CalleeTCBs.insert(A->getTCBName()); }); + for (const auto *A : Callee->specific_attrs()) + CalleeTCBs.insert(A->getTCBName()); + for (const auto *A : Callee->specific_attrs()) + CalleeTCBs.insert(A->getTCBName()); // Go through the TCBs the caller is a part of and emit warnings if Caller // is in a TCB that the Callee is not. - for_each( - Caller->specific_attrs(), - [&](const auto *A) { - StringRef CallerTCB = A->getTCBName(); - if (CalleeTCBs.count(CallerTCB) == 0) { - this->Diag(CallExprLoc, diag::warn_tcb_enforcement_violation) - << Callee << CallerTCB; - } - }); + for (const auto *A : Caller->specific_attrs()) { + StringRef CallerTCB = A->getTCBName(); + if (CalleeTCBs.count(CallerTCB) == 0) { + this->Diag(CallExprLoc, diag::warn_tcb_enforcement_violation) + << Callee << CallerTCB; + } + } } diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index d35e9c6e42bf2..ae2e71dcd5dac 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -1095,7 +1095,9 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { if (const UsingShadowDecl *Using = dyn_cast(R.Declaration)) { CodeCompletionResult Result(Using->getTargetDecl(), getBasePriority(Using->getTargetDecl()), - R.Qualifier); + R.Qualifier, false, + (R.Availability == CXAvailability_Available || + R.Availability == CXAvailability_Deprecated)); Result.ShadowDecl = Using; MaybeAddResult(Result, CurContext); return; @@ -1268,7 +1270,9 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, if (const auto *Using = dyn_cast(R.Declaration)) { CodeCompletionResult Result(Using->getTargetDecl(), getBasePriority(Using->getTargetDecl()), - R.Qualifier); + R.Qualifier, false, + (R.Availability == CXAvailability_Available || + R.Availability == CXAvailability_Deprecated)); Result.ShadowDecl = Using; AddResult(Result, CurContext, Hiding); return; diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 55f1c2989578d..a738befdd6cea 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -1324,7 +1324,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { bool PassAlignment = false; SmallVector PlacementArgs; - bool PromiseContainNew = [this, &PromiseType]() -> bool { + bool PromiseContainsNew = [this, &PromiseType]() -> bool { DeclarationName NewName = S.getASTContext().DeclarationNames.getCXXOperatorName(OO_New); LookupResult R(S, NewName, Loc, Sema::LookupOrdinaryName); @@ -1343,7 +1343,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { // - If no declarations are found in the scope of the promise type, a search // is performed in the global scope. Sema::AllocationFunctionScope NewScope = - PromiseContainNew ? Sema::AFS_Class : Sema::AFS_Global; + PromiseContainsNew ? Sema::AFS_Class : Sema::AFS_Global; S.FindAllocationFunctions(Loc, SourceRange(), NewScope, /*DeleteScope*/ Sema::AFS_Both, PromiseType, @@ -1354,7 +1354,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { // We don't expect to call to global operator new with (size, p0, …, pn). // So if we choose to lookup the allocation function in global scope, we // shouldn't lookup placement arguments. - if (PromiseContainNew && !collectPlacementArgs(S, FD, Loc, PlacementArgs)) + if (PromiseContainsNew && !collectPlacementArgs(S, FD, Loc, PlacementArgs)) return false; LookupAllocationFunction(); @@ -1363,7 +1363,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { // If no viable function is found ([over.match.viable]), overload resolution // is performed again on a function call created by passing just the amount of // space required as an argument of type std::size_t. - if (!OperatorNew && !PlacementArgs.empty() && PromiseContainNew) { + if (!OperatorNew && !PlacementArgs.empty() && PromiseContainsNew) { PlacementArgs.clear(); LookupAllocationFunction(); } @@ -1386,7 +1386,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { } if (!OperatorNew) { - if (PromiseContainNew) + if (PromiseContainsNew) S.Diag(Loc, diag::err_coroutine_unusable_new) << PromiseType << &FD; return false; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index d68d1f3ff070d..d8f2f332857f7 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4508,15 +4508,15 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { } // C++ doesn't have tentative definitions, so go right ahead and check here. - if (getLangOpts().CPlusPlus && - New->isThisDeclarationADefinition() == VarDecl::Definition) { + if (getLangOpts().CPlusPlus) { if (Old->isStaticDataMember() && Old->getCanonicalDecl()->isInline() && Old->getCanonicalDecl()->isConstexpr()) { // This definition won't be a definition any more once it's been merged. Diag(New->getLocation(), diag::warn_deprecated_redundant_constexpr_static_def); - } else if (VarDecl *Def = Old->getDefinition()) { - if (checkVarDeclRedefinition(Def, New)) + } else if (New->isThisDeclarationADefinition() == VarDecl::Definition) { + VarDecl *Def = Old->getDefinition(); + if (Def && checkVarDeclRedefinition(Def, New)) return; } } @@ -5461,7 +5461,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Diag(DS.getBeginLoc(), diag::ext_no_declarators) << DS.getSourceRange(); // Mock up a declarator. - Declarator Dc(DS, DeclaratorContext::Member); + Declarator Dc(DS, ParsedAttributesView::none(), DeclaratorContext::Member); TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S); assert(TInfo && "couldn't build declarator info for anonymous struct/union"); @@ -5558,7 +5558,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, assert(Record && "expected a record!"); // Mock up a declarator. - Declarator Dc(DS, DeclaratorContext::TypeName); + Declarator Dc(DS, ParsedAttributesView::none(), DeclaratorContext::TypeName); TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S); assert(TInfo && "couldn't build declarator info for anonymous struct"); @@ -7000,7 +7000,8 @@ static bool hasParsedAttr(Scope *S, const Declarator &PD, } // Finally, check attributes on the decl itself. - return PD.getAttributes().hasAttribute(Kind); + return PD.getAttributes().hasAttribute(Kind) || + PD.getDeclarationAttributes().hasAttribute(Kind); } /// Adjust the \c DeclContext for a function or variable that might be a @@ -13332,7 +13333,7 @@ StmtResult Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, DS.SetTypeSpecType(DeclSpec::TST_auto, IdentLoc, PrevSpec, DiagID, getPrintingPolicy()); - Declarator D(DS, DeclaratorContext::ForInit); + Declarator D(DS, ParsedAttributesView::none(), DeclaratorContext::ForInit); D.SetIdentifier(Ident, IdentLoc); D.takeAttributes(Attrs); @@ -14330,7 +14331,8 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, // Use the identifier location for the type source range. DS.SetRangeStart(FTI.Params[i].IdentLoc); DS.SetRangeEnd(FTI.Params[i].IdentLoc); - Declarator ParamD(DS, DeclaratorContext::KNRTypeList); + Declarator ParamD(DS, ParsedAttributesView::none(), + DeclaratorContext::KNRTypeList); ParamD.SetIdentifier(FTI.Params[i].Ident, FTI.Params[i].IdentLoc); FTI.Params[i].Param = ActOnParamDeclarator(S, ParamD); } @@ -15352,7 +15354,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, (void)Error; // Silence warning. assert(!Error && "Error setting up implicit decl!"); SourceLocation NoLoc; - Declarator D(DS, DeclaratorContext::Block); + Declarator D(DS, ParsedAttributesView::none(), DeclaratorContext::Block); D.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/false, /*IsAmbiguous=*/false, /*LParenLoc=*/NoLoc, @@ -17094,17 +17096,12 @@ void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) { // Note that FieldName may be null for anonymous bitfields. ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, - IdentifierInfo *FieldName, - QualType FieldTy, bool IsMsStruct, - Expr *BitWidth, bool *ZeroWidth) { + IdentifierInfo *FieldName, QualType FieldTy, + bool IsMsStruct, Expr *BitWidth) { assert(BitWidth); if (BitWidth->containsErrors()) return ExprError(); - // Default to true; that shouldn't confuse checks for emptiness - if (ZeroWidth) - *ZeroWidth = true; - // C99 6.7.2.1p4 - verify the field type. // C++ 9.6p3: A bit-field shall have integral or enumeration type. if (!FieldTy->isDependentType() && !FieldTy->isIntegralOrEnumerationType()) { @@ -17132,9 +17129,6 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, return ICE; BitWidth = ICE.get(); - if (Value != 0 && ZeroWidth) - *ZeroWidth = false; - // Zero-width bitfield is ok for anonymous field. if (Value == 0 && FieldName) return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName; @@ -17387,17 +17381,15 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, AbstractFieldType)) InvalidDecl = true; - bool ZeroWidth = false; if (InvalidDecl) BitWidth = nullptr; // If this is declared as a bit-field, check the bit-field. if (BitWidth) { - BitWidth = VerifyBitField(Loc, II, T, Record->isMsStruct(Context), BitWidth, - &ZeroWidth).get(); + BitWidth = + VerifyBitField(Loc, II, T, Record->isMsStruct(Context), BitWidth).get(); if (!BitWidth) { InvalidDecl = true; BitWidth = nullptr; - ZeroWidth = false; } } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index f39e1af10e3d7..af8dc853eba69 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1404,9 +1404,9 @@ static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { FD->isBitField() && S.Context.getTypeAlign(FD->getType()) <= 8); - if (S.getASTContext().getTargetInfo().getTriple().isPS4()) { + if (S.getASTContext().getTargetInfo().getTriple().isPS()) { if (BitfieldByteAligned) - // The PS4 target needs to maintain ABI backwards compatibility. + // The PS4/PS5 targets need to maintain ABI backwards compatibility. S.Diag(AL.getLoc(), diag::warn_attribute_ignored_for_field_of_type) << AL << FD->getType(); else @@ -3156,6 +3156,14 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) { S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL; } + if ((!AL.isGNUAttribute() && + !(AL.isStandardAttributeSyntax() && AL.isClangScope())) && + isa(D)) { + S.Diag(AL.getLoc(), diag::warn_unused_result_typedef_unsupported_spelling) + << AL.isGNUScope(); + return; + } + D->addAttr(::new (S.Context) WarnUnusedResultAttr(S.Context, AL, Str)); } @@ -3490,7 +3498,7 @@ bool Sema::checkTargetClonesAttrString(SourceLocation LiteralLoc, StringRef Str, return Diag(CurLoc, diag::warn_unsupported_target_attribute) << Unsupported << None << Cur << TargetClones; - if (llvm::find(Strings, Cur) != Strings.end() || DefaultIsDupe) + if (llvm::is_contained(Strings, Cur) || DefaultIsDupe) Diag(CurLoc, diag::warn_target_clone_duplicate_options); // Note: Add even if there are duplicates, since it changes name mangling. Strings.push_back(Cur); @@ -4139,48 +4147,10 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { void Sema::AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI, StringRef Str, MutableArrayRef Args) { auto *Attr = AnnotateAttr::Create(Context, Str, Args.data(), Args.size(), CI); - llvm::SmallVector Notes; - for (unsigned Idx = 0; Idx < Attr->args_size(); Idx++) { - Expr *&E = Attr->args_begin()[Idx]; - assert(E && "error are handled before"); - if (E->isValueDependent() || E->isTypeDependent()) - continue; - - if (E->getType()->isArrayType()) - E = ImpCastExprToType(E, Context.getPointerType(E->getType()), - clang::CK_ArrayToPointerDecay) - .get(); - if (E->getType()->isFunctionType()) - E = ImplicitCastExpr::Create(Context, - Context.getPointerType(E->getType()), - clang::CK_FunctionToPointerDecay, E, nullptr, - VK_PRValue, FPOptionsOverride()); - if (E->isLValue()) - E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(), - clang::CK_LValueToRValue, E, nullptr, - VK_PRValue, FPOptionsOverride()); - - Expr::EvalResult Eval; - Notes.clear(); - Eval.Diag = &Notes; - - bool Result = - E->EvaluateAsConstantExpr(Eval, Context); - - /// Result means the expression can be folded to a constant. - /// Note.empty() means the expression is a valid constant expression in the - /// current language mode. - if (!Result || !Notes.empty()) { - Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type) - << CI << (Idx + 1) << AANT_ArgumentConstantExpr; - for (auto &Note : Notes) - Diag(Note.first, Note.second); - return; - } - assert(Eval.Val.hasValue()); - E = ConstantExpr::Create(Context, E, Eval.Val); + if (ConstantFoldAttrArgs( + CI, MutableArrayRef(Attr->args_begin(), Attr->args_end()))) { + D->addAttr(Attr); } - D->addAttr(Attr); } static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { @@ -8346,15 +8316,21 @@ static bool MustDelayAttributeArguments(const ParsedAttr &AL) { /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if /// the attribute applies to decls. If the attribute is a type attribute, just /// silently ignore it if a GNU attribute. -static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, - const ParsedAttr &AL, - bool IncludeCXX11Attributes) { +static void +ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, + const Sema::ProcessDeclAttributeOptions &Options) { if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute) return; // Ignore C++11 attributes on declarator chunks: they appertain to the type // instead. - if (AL.isCXX11Attribute() && !IncludeCXX11Attributes) + // FIXME: We currently check the attribute syntax directly instead of using + // isCXX11Attribute(), which currently erroneously classifies the C11 + // `_Alignas` attribute as a C++11 attribute. `_Alignas` can appear on the + // `DeclSpec`, so we need to let it through here to make sure it is processed + // appropriately. Once the behavior of isCXX11Attribute() is fixed, we can + // go back to using that here. + if (AL.getSyntax() == ParsedAttr::AS_CXX11 && !Options.IncludeCXX11Attributes) return; // Unknown attributes are automatically warned on. Target-specific attributes @@ -8387,14 +8363,76 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, if (AL.getInfo().handleDeclAttribute(S, D, AL) != ParsedAttrInfo::NotHandled) break; if (!AL.isStmtAttr()) { - // Type attributes are handled elsewhere; silently move on. assert(AL.isTypeAttr() && "Non-type attribute not handled"); - break; + } + if (AL.isTypeAttr()) { + if (Options.IgnoreTypeAttributes) + break; + if (!AL.isStandardAttributeSyntax()) { + // Non-[[]] type attributes are handled in processTypeAttrs(); silently + // move on. + break; + } + + // According to the C and C++ standards, we should never see a + // [[]] type attribute on a declaration. However, we have in the past + // allowed some type attributes to "slide" to the `DeclSpec`, so we need + // to continue to support this legacy behavior. We only do this, however, + // if + // - we actually have a `DeclSpec`, i.e. if we're looking at a + // `DeclaratorDecl`, or + // - we are looking at an alias-declaration, where historically we have + // allowed type attributes after the identifier to slide to the type. + if (AL.slidesFromDeclToDeclSpecLegacyBehavior() && + isa(D)) { + // Suggest moving the attribute to the type instead, but only for our + // own vendor attributes; moving other vendors' attributes might hurt + // portability. + if (AL.isClangScope()) { + S.Diag(AL.getLoc(), diag::warn_type_attribute_deprecated_on_decl) + << AL << D->getLocation(); + } + + // Allow this type attribute to be handled in processTypeAttrs(); + // silently move on. + break; + } + + if (AL.getKind() == ParsedAttr::AT_Regparm) { + // `regparm` is a special case: It's a type attribute but we still want + // to treat it as if it had been written on the declaration because that + // way we'll be able to handle it directly in `processTypeAttr()`. + // If we treated `regparm` it as if it had been written on the + // `DeclSpec`, the logic in `distributeFunctionTypeAttrFromDeclSepc()` + // would try to move it to the declarator, but that doesn't work: We + // can't remove the attribute from the list of declaration attributes + // because it might be needed by other declarators in the same + // declaration. + break; + } + + if (AL.getKind() == ParsedAttr::AT_VectorSize) { + // `vector_size` is a special case: It's a type attribute semantically, + // but GCC expects the [[]] syntax to be written on the declaration (and + // warns that the attribute has no effect if it is placed on the + // decl-specifier-seq). + // Silently move on and allow the attribute to be handled in + // processTypeAttr(). + break; + } + + if (AL.getKind() == ParsedAttr::AT_NoDeref) { + // FIXME: `noderef` currently doesn't work correctly in [[]] syntax. + // See https://github.com/llvm/llvm-project/issues/55790 for details. + // We allow processTypeAttrs() to emit a warning and silently move on. + break; + } } // N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a // statement attribute is not written on a declaration, but this code is - // needed for attributes in Attr.td that do not list any subjects. - S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl) + // needed for type attributes as well as statement attributes in Attr.td + // that do not list any subjects. + S.Diag(AL.getLoc(), diag::err_attribute_invalid_on_decl) << AL << D->getLocation(); break; case ParsedAttr::AT_Interrupt: @@ -9040,14 +9078,14 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, /// ProcessDeclAttributeList - Apply all the decl attributes in the specified /// attribute list to the specified decl, ignoring any type attributes. -void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, - const ParsedAttributesView &AttrList, - bool IncludeCXX11Attributes) { +void Sema::ProcessDeclAttributeList( + Scope *S, Decl *D, const ParsedAttributesView &AttrList, + const ProcessDeclAttributeOptions &Options) { if (AttrList.empty()) return; for (const ParsedAttr &AL : AttrList) - ProcessDeclAttribute(*this, S, D, AL, IncludeCXX11Attributes); + ProcessDeclAttribute(*this, S, D, AL, Options); // FIXME: We should be able to handle these cases in TableGen. // GCC accepts @@ -9135,7 +9173,8 @@ bool Sema::ProcessAccessDeclAttributeList( AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList) { for (const ParsedAttr &AL : AttrList) { if (AL.getKind() == ParsedAttr::AT_Annotate) { - ProcessDeclAttribute(*this, nullptr, ASDecl, AL, AL.isCXX11Attribute()); + ProcessDeclAttribute(*this, nullptr, ASDecl, AL, + ProcessDeclAttributeOptions()); } else { Diag(AL.getLoc(), diag::err_only_annotate_after_access_spec); return true; @@ -9168,6 +9207,7 @@ static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) { /// used to build a declaration, complain about any decl attributes /// which might be lying around on it. void Sema::checkUnusedDeclAttributes(Declarator &D) { + ::checkUnusedDeclAttributes(*this, D.getDeclarationAttributes()); ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes()); ::checkUnusedDeclAttributes(*this, D.getAttributes()); for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) @@ -9276,17 +9316,43 @@ void Sema::ProcessPragmaWeak(Scope *S, Decl *D) { /// it, apply them to D. This is a bit tricky because PD can have attributes /// specified in many different places, and we need to find and apply them all. void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { + // Ordering of attributes can be important, so we take care to process + // attributes in the order in which they appeared in the source code. + + // First, process attributes that appeared on the declaration itself (but + // only if they don't have the legacy behavior of "sliding" to the DeclSepc). + ParsedAttributesView NonSlidingAttrs; + for (ParsedAttr &AL : PD.getDeclarationAttributes()) { + if (AL.slidesFromDeclToDeclSpecLegacyBehavior()) { + // Skip processing the attribute, but do check if it appertains to the + // declaration. This is needed for the `MatrixType` attribute, which, + // despite being a type attribute, defines a `SubjectList` that only + // allows it to be used on typedef declarations. + AL.diagnoseAppertainsTo(*this, D); + } else { + NonSlidingAttrs.addAtEnd(&AL); + } + } + ProcessDeclAttributeList(S, D, NonSlidingAttrs); + // Apply decl attributes from the DeclSpec if present. - if (!PD.getDeclSpec().getAttributes().empty()) - ProcessDeclAttributeList(S, D, PD.getDeclSpec().getAttributes()); + if (!PD.getDeclSpec().getAttributes().empty()) { + ProcessDeclAttributeList(S, D, PD.getDeclSpec().getAttributes(), + ProcessDeclAttributeOptions() + .WithIncludeCXX11Attributes(false) + .WithIgnoreTypeAttributes(true)); + } // Walk the declarator structure, applying decl attributes that were in a type // position to the decl itself. This handles cases like: // int *__attr__(x)** D; // when X is a decl attribute. - for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) + for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) { ProcessDeclAttributeList(S, D, PD.getTypeObject(i).getAttrs(), - /*IncludeCXX11Attributes=*/false); + ProcessDeclAttributeOptions() + .WithIncludeCXX11Attributes(false) + .WithIgnoreTypeAttributes(true)); + } // Finally, apply any attributes on the decl itself. ProcessDeclAttributeList(S, D, PD.getAttributes()); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index c470a46f58477..6c8704cd0b789 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5430,8 +5430,7 @@ static void DiagnoseBaseOrMemInitializerOrder( return; // Sort based on the ideal order, first in the pair. - llvm::sort(CorrelatedInitOrder, - [](auto &LHS, auto &RHS) { return LHS.first < RHS.first; }); + llvm::sort(CorrelatedInitOrder, llvm::less_first()); // Introduce a new scope as SemaDiagnosticBuilder needs to be destroyed to // emit the diagnostic before we can try adding notes. @@ -8618,10 +8617,10 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, int(1))) return true; - if (llvm::find_if(RD->friends(), [&](const FriendDecl *F) { + if (llvm::none_of(RD->friends(), [&](const FriendDecl *F) { return FD->getCanonicalDecl() == F->getFriendDecl()->getCanonicalDecl(); - }) == RD->friends().end()) { + })) { Diag(FD->getLocation(), diag::err_defaulted_comparison_not_friend) << int(DCK) << int(0) << RD; Diag(RD->getCanonicalDecl()->getLocation(), diag::note_declared_at); @@ -16861,7 +16860,8 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, // Try to convert the decl specifier to a type. This works for // friend templates because ActOnTag never produces a ClassTemplateDecl // for a TUK_Friend. - Declarator TheDeclarator(DS, DeclaratorContext::Member); + Declarator TheDeclarator(DS, ParsedAttributesView::none(), + DeclaratorContext::Member); TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S); QualType T = TSI->getType(); if (TheDeclarator.isInvalidType()) diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 5c3903e652a51..aa0034e616f27 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -1588,7 +1588,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( DS.SetRangeEnd(loc); // Form the declarator. - Declarator D(DS, DeclaratorContext::TypeName); + Declarator D(DS, ParsedAttributesView::none(), DeclaratorContext::TypeName); // If we have a typedef of an Objective-C class type that is missing a '*', // add the '*'. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 3e8bd63e89ae9..6edf5b355d029 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -10261,12 +10261,18 @@ static bool tryGCCVectorConvertAndSplat(Sema &S, ExprResult *Scalar, ExprResult *Vector) { QualType ScalarTy = Scalar->get()->getType().getUnqualifiedType(); QualType VectorTy = Vector->get()->getType().getUnqualifiedType(); - const auto *VT = VectorTy->castAs(); - - assert(!isa(VT) && - "ExtVectorTypes should not be handled here!"); - - QualType VectorEltTy = VT->getElementType(); + QualType VectorEltTy; + + if (const auto *VT = VectorTy->getAs()) { + assert(!isa(VT) && + "ExtVectorTypes should not be handled here!"); + VectorEltTy = VT->getElementType(); + } else if (VectorTy->isVLSTBuiltinType()) { + VectorEltTy = + VectorTy->castAs()->getSveEltType(S.getASTContext()); + } else { + llvm_unreachable("Only Fixed-Length and SVE Vector types are handled here"); + } // Reject cases where the vector element type or the scalar element type are // not integral or floating point types. @@ -10578,10 +10584,13 @@ QualType Sema::CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS, QualType LHSType = LHS.get()->getType().getUnqualifiedType(); QualType RHSType = RHS.get()->getType().getUnqualifiedType(); + const BuiltinType *LHSBuiltinTy = LHSType->getAs(); + const BuiltinType *RHSBuiltinTy = RHSType->getAs(); + unsigned DiagID = diag::err_typecheck_invalid_operands; if ((OperationKind == ACK_Arithmetic) && - (LHSType->castAs()->isSVEBool() || - RHSType->castAs()->isSVEBool())) { + ((LHSBuiltinTy && LHSBuiltinTy->isSVEBool()) || + (RHSBuiltinTy && RHSBuiltinTy->isSVEBool()))) { Diag(Loc, DiagID) << LHSType << RHSType << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return QualType(); @@ -10590,32 +10599,43 @@ QualType Sema::CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS, if (Context.hasSameType(LHSType, RHSType)) return LHSType; - auto tryScalableVectorConvert = [this](ExprResult *Src, QualType SrcType, - QualType DestType) { - const QualType DestBaseType = DestType->getSveEltType(Context); - if (DestBaseType->getUnqualifiedDesugaredType() == - SrcType->getUnqualifiedDesugaredType()) { - unsigned DiagID = diag::err_typecheck_invalid_operands; - if (!tryVectorConvertAndSplat(*this, Src, SrcType, DestBaseType, DestType, - DiagID)) - return DestType; - } + if (LHSType->isVLSTBuiltinType() && !RHSType->isVLSTBuiltinType()) { + if (!tryGCCVectorConvertAndSplat(*this, &RHS, &LHS)) + return LHSType; + } + if (RHSType->isVLSTBuiltinType() && !LHSType->isVLSTBuiltinType()) { + if (LHS.get()->isLValue() || + !tryGCCVectorConvertAndSplat(*this, &LHS, &RHS)) + return RHSType; + } + + if ((!LHSType->isVLSTBuiltinType() && !LHSType->isRealType()) || + (!RHSType->isVLSTBuiltinType() && !RHSType->isRealType())) { + Diag(Loc, diag::err_typecheck_vector_not_convertable_non_scalar) + << LHSType << RHSType << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); return QualType(); - }; + } - if (LHSType->isVLSTBuiltinType() && !RHSType->isVLSTBuiltinType()) { - auto DestType = tryScalableVectorConvert(&RHS, RHSType, LHSType); - if (DestType == QualType()) - return InvalidOperands(Loc, LHS, RHS); - return DestType; + if (LHSType->isVLSTBuiltinType() && RHSType->isVLSTBuiltinType() && + Context.getBuiltinVectorTypeInfo(LHSBuiltinTy).EC != + Context.getBuiltinVectorTypeInfo(RHSBuiltinTy).EC) { + Diag(Loc, diag::err_typecheck_vector_lengths_not_equal) + << LHSType << RHSType << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + return QualType(); } - if (RHSType->isVLSTBuiltinType() && !LHSType->isVLSTBuiltinType()) { - auto DestType = tryScalableVectorConvert((IsCompAssign ? nullptr : &LHS), - LHSType, RHSType); - if (DestType == QualType()) - return InvalidOperands(Loc, LHS, RHS); - return DestType; + if (LHSType->isVLSTBuiltinType() || RHSType->isVLSTBuiltinType()) { + QualType Scalar = LHSType->isVLSTBuiltinType() ? RHSType : LHSType; + QualType Vector = LHSType->isVLSTBuiltinType() ? LHSType : RHSType; + bool ScalarOrVector = + LHSType->isVLSTBuiltinType() && RHSType->isVLSTBuiltinType(); + + Diag(Loc, diag::err_typecheck_vector_not_convertable_implict_truncation) + << ScalarOrVector << Scalar << Vector; + + return QualType(); } Diag(Loc, DiagID) << LHSType << RHSType << LHS.get()->getSourceRange() @@ -10845,8 +10865,10 @@ static void diagnoseSubtractionOnNullPointer(Sema &S, SourceLocation Loc, if (S.Diags.getSuppressSystemWarnings() && S.SourceMgr.isInSystemMacro(Loc)) return; - S.Diag(Loc, diag::warn_pointer_sub_null_ptr) - << S.getLangOpts().CPlusPlus << Pointer->getSourceRange(); + S.DiagRuntimeBehavior(Loc, Pointer, + S.PDiag(diag::warn_pointer_sub_null_ptr) + << S.getLangOpts().CPlusPlus + << Pointer->getSourceRange()); } /// Diagnose invalid arithmetic on two function pointers. @@ -11394,10 +11416,16 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, return; llvm::APSInt Left = LHSResult.Val.getInt(); - // If LHS does not have a signed type and non-negative value - // then, the behavior is undefined before C++2a. Warn about it. - if (Left.isNegative() && !S.getLangOpts().isSignedOverflowDefined() && - !S.getLangOpts().CPlusPlus20) { + // Don't warn if signed overflow is defined, then all the rest of the + // diagnostics will not be triggered because the behavior is defined. + // Also don't warn in C++20 mode (and newer), as signed left shifts + // always wrap and never overflow. + if (S.getLangOpts().isSignedOverflowDefined() || S.getLangOpts().CPlusPlus20) + return; + + // If LHS does not have a non-negative value then, the + // behavior is undefined before C++2a. Warn about it. + if (Left.isNegative()) { S.DiagRuntimeBehavior(Loc, LHS.get(), S.PDiag(diag::warn_shift_lhs_negative) << LHS.get()->getSourceRange()); @@ -19604,11 +19632,17 @@ class EvaluatedExprMarker : public UsedDeclVisitor { } void Visit(Expr *E) { - if (std::find(StopAt.begin(), StopAt.end(), E) != StopAt.end()) + if (llvm::is_contained(StopAt, E)) return; Inherited::Visit(E); } + void VisitConstantExpr(ConstantExpr *E) { + // Don't mark declarations within a ConstantExpression, as this expression + // will be evaluated and folded to a value. + return; + } + void VisitDeclRefExpr(DeclRefExpr *E) { // If we were asked not to visit local variables, don't. if (SkipLocalVariables) { diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 27ec863e7a35e..fe84e3047a59d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -843,10 +843,10 @@ Sema::ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *Ex) { break; } + // FIXME: Many of the scope checks here seem incorrect. if (S->getFlags() & (Scope::FnScope | Scope::ClassScope | Scope::BlockScope | - Scope::FunctionPrototypeScope | Scope::ObjCMethodScope | - Scope::TryScope)) + Scope::ObjCMethodScope | Scope::TryScope)) break; } } @@ -3745,7 +3745,7 @@ static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall, // We do our own custom access checks below. R.suppressDiagnostics(); - SmallVector Args(TheCall->arg_begin(), TheCall->arg_end()); + SmallVector Args(TheCall->arguments()); OverloadCandidateSet Candidates(R.getNameLoc(), OverloadCandidateSet::CSK_Normal); for (LookupResult::iterator FnOvl = R.begin(), FnOvlEnd = R.end(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 016ff5ded25fb..c7e068046d7fd 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -4503,13 +4503,13 @@ static void TryListInitialization(Sema &S, Kind.getKind() == InitializationKind::IK_DirectList && ET && ET->getDecl()->isFixed() && !S.Context.hasSameUnqualifiedType(E->getType(), DestType) && - (E->getType()->isIntegralOrEnumerationType() || + (E->getType()->isIntegralOrUnscopedEnumerationType() || E->getType()->isFloatingType())) { // There are two ways that T(v) can work when T is an enumeration type. // If there is either an implicit conversion sequence from v to T or // a conversion function that can convert from v to T, then we use that. - // Otherwise, if v is of integral, enumeration, or floating-point type, - // it is converted to the enumeration type via its underlying type. + // Otherwise, if v is of integral, unscoped enumeration, or floating-point + // type, it is converted to the enumeration type via its underlying type. // There is no overlap possible between these two cases (except when the // source value is already of the destination type), and the first // case is handled by the general case for single-element lists below. diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 753decfb167cd..0615c81bff4ae 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -11429,11 +11429,11 @@ bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S, switch (Cond->getOpcode()) { case BO_EQ: { C = Cond; - D = BO->getRHS()->IgnoreImpCasts(); + D = BO->getRHS(); if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) { - E = Cond->getRHS()->IgnoreImpCasts(); + E = Cond->getRHS(); } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) { - E = Cond->getLHS()->IgnoreImpCasts(); + E = Cond->getLHS(); } else { ErrorInfo.Error = ErrorTy::InvalidComparison; ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); @@ -11444,7 +11444,7 @@ bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S, } case BO_LT: case BO_GT: { - E = BO->getRHS()->IgnoreImpCasts(); + E = BO->getRHS(); if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) && checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) { C = Cond; @@ -11524,11 +11524,11 @@ bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S, switch (Cond->getOpcode()) { case BO_EQ: { C = Cond; - D = CO->getTrueExpr()->IgnoreImpCasts(); + D = CO->getTrueExpr(); if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) { - E = Cond->getRHS()->IgnoreImpCasts(); + E = Cond->getRHS(); } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) { - E = Cond->getLHS()->IgnoreImpCasts(); + E = Cond->getLHS(); } else { ErrorInfo.Error = ErrorTy::InvalidComparison; ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); @@ -11539,7 +11539,7 @@ bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S, } case BO_LT: case BO_GT: { - E = CO->getTrueExpr()->IgnoreImpCasts(); + E = CO->getTrueExpr(); if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) && checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) { C = Cond; @@ -11632,6 +11632,7 @@ class OpenMPAtomicCompareCaptureChecker final Expr *getV() const { return V; } Expr *getR() const { return R; } bool isFailOnly() const { return IsFailOnly; } + bool isPostfixUpdate() const { return IsPostfixUpdate; } /// Check if statement \a S is valid for atomic compare capture. bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo); @@ -11661,6 +11662,8 @@ class OpenMPAtomicCompareCaptureChecker final Expr *R = nullptr; /// If 'v' is only updated when the comparison fails. bool IsFailOnly = false; + /// If original value of 'x' must be stored in 'v', not an updated one. + bool IsPostfixUpdate = false; }; bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) { @@ -11963,9 +11966,11 @@ bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S, UpdateStmt = S1; CondUpdateStmt = S2; // Check if form 45. - if (dyn_cast(BO->getRHS()->IgnoreImpCasts()) && - dyn_cast(S2)) + if (isa(BO->getRHS()->IgnoreImpCasts()) && + isa(S2)) return checkForm45(CS, ErrorInfo); + // It cannot be set before we the check for form45. + IsPostfixUpdate = true; } else { // { cond-update-stmt v = x; } UpdateStmt = S2; @@ -12141,8 +12146,10 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef Clauses, Expr *UE = nullptr; Expr *D = nullptr; Expr *CE = nullptr; + Expr *R = nullptr; bool IsXLHSInRHSPart = false; bool IsPostfixUpdate = false; + bool IsFailOnly = false; // OpenMP [2.12.6, atomic Construct] // In the next expressions: // * x and v (as applicable) are both l-value expressions with scalar type. @@ -12538,8 +12545,16 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef Clauses, << ErrorInfo.Error << ErrorInfo.NoteRange; return StmtError(); } - // TODO: We don't set X, D, E, etc. here because in code gen we will emit - // error directly. + X = Checker.getX(); + E = Checker.getE(); + D = Checker.getD(); + CE = Checker.getCond(); + V = Checker.getV(); + R = Checker.getR(); + // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'. + IsXLHSInRHSPart = Checker.isXBinopExpr(); + IsFailOnly = Checker.isFailOnly(); + IsPostfixUpdate = Checker.isPostfixUpdate(); } else { OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo; OpenMPAtomicCompareChecker Checker(*this); @@ -12547,7 +12562,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef Clauses, Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare) << ErrorInfo.ErrorRange; Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare) - << ErrorInfo.Error << ErrorInfo.NoteRange; + << ErrorInfo.Error << ErrorInfo.NoteRange; return StmtError(); } X = Checker.getX(); @@ -12563,7 +12578,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef Clauses, return OMPAtomicDirective::Create( Context, StartLoc, EndLoc, Clauses, AStmt, - {X, V, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate}); + {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly}); } StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef Clauses, diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index fbca36b1216a8..c147d26b2dff3 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -716,10 +716,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, NamedOperandList.emplace_back( std::make_pair(Names[i]->getName(), Exprs[i])); // Sort NamedOperandList. - std::stable_sort(NamedOperandList.begin(), NamedOperandList.end(), - [](const NamedOperand &LHS, const NamedOperand &RHS) { - return LHS.first < RHS.first; - }); + llvm::stable_sort(NamedOperandList, llvm::less_first()); // Find adjacent duplicate operand. SmallVector::iterator Found = std::adjacent_find(begin(NamedOperandList), end(NamedOperandList), diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 77c5677b65c87..c89dc8c3513d9 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3801,13 +3801,15 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( return nullptr; // Substitute the current template arguments. - const TemplateArgumentListInfo &TemplateArgsInfo = D->getTemplateArgsInfo(); - VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo.getLAngleLoc()); - VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo.getRAngleLoc()); + if (const ASTTemplateArgumentListInfo *TemplateArgsInfo = + D->getTemplateArgsInfo()) { + VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo->getLAngleLoc()); + VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo->getRAngleLoc()); - if (SemaRef.SubstTemplateArguments(TemplateArgsInfo.arguments(), TemplateArgs, - VarTemplateArgsInfo)) - return nullptr; + if (SemaRef.SubstTemplateArguments(TemplateArgsInfo->arguments(), + TemplateArgs, VarTemplateArgsInfo)) + return nullptr; + } // Check that the template argument list is well-formed for this template. SmallVector Converted; @@ -5554,8 +5556,18 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, // declaration of the definition. TemplateDeclInstantiator Instantiator(*this, Var->getDeclContext(), TemplateArgs); + + TemplateArgumentListInfo TemplateArgInfo; + if (const ASTTemplateArgumentListInfo *ArgInfo = + VarSpec->getTemplateArgsInfo()) { + TemplateArgInfo.setLAngleLoc(ArgInfo->getLAngleLoc()); + TemplateArgInfo.setRAngleLoc(ArgInfo->getRAngleLoc()); + for (const TemplateArgumentLoc &Arg : ArgInfo->arguments()) + TemplateArgInfo.addArgument(Arg); + } + Var = cast_or_null(Instantiator.VisitVarTemplateSpecializationDecl( - VarSpec->getSpecializedTemplate(), Def, VarSpec->getTemplateArgsInfo(), + VarSpec->getSpecializedTemplate(), Def, TemplateArgInfo, VarSpec->getTemplateArgs().asArray(), VarSpec)); if (Var) { llvm::PointerUniongetAttrs()) || hasCFReturnsAttr(D.getDeclSpec().getAttributes())) { inferNullability = NullabilityKind::Nullable; @@ -4735,6 +4767,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case DeclaratorContext::TypeName: case DeclaratorContext::FunctionalCast: case DeclaratorContext::RequiresExpr: + case DeclaratorContext::Association: // Don't infer in these contexts. break; } @@ -5182,11 +5215,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if ((T.getCVRQualifiers() || T->isAtomicType()) && !(S.getLangOpts().CPlusPlus && (T->isDependentType() || T->isRecordType()))) { - // WG14 DR 423 updated 6.7.6.3p4 to have the function declarator drop - // all qualifiers from the return type. - diagnoseRedundantReturnTypeQualifiers(S, T, D, chunkIndex); - if (!S.getLangOpts().CPlusPlus) - T = T.getAtomicUnqualifiedType(); + if (T->isVoidType() && !S.getLangOpts().CPlusPlus && + D.getFunctionDefinitionKind() == + FunctionDefinitionKind::Definition) { + // [6.9.1/3] qualified void return is invalid on a C + // function definition. Apparently ok on declarations and + // in C++ though (!) + S.Diag(DeclType.Loc, diag::err_func_returning_qualified_void) << T; + } else + diagnoseRedundantReturnTypeQualifiers(S, T, D, chunkIndex); // C++2a [dcl.fct]p12: // A volatile-qualified return type is deprecated @@ -5266,7 +5303,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // function is marked with the "overloadable" attribute. Scan // for this attribute now. if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus) - if (!D.getAttributes().hasAttribute(ParsedAttr::AT_Overloadable) && + if (!D.getDeclarationAttributes().hasAttribute( + ParsedAttr::AT_Overloadable) && + !D.getAttributes().hasAttribute(ParsedAttr::AT_Overloadable) && !D.getDeclSpec().getAttributes().hasAttribute( ParsedAttr::AT_Overloadable)) S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_param); @@ -5682,7 +5721,14 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } } - // Apply any undistributed attributes from the declarator. + // Apply any undistributed attributes from the declaration or declarator. + ParsedAttributesView NonSlidingAttrs; + for (ParsedAttr &AL : D.getDeclarationAttributes()) { + if (!AL.slidesFromDeclToDeclSpecLegacyBehavior()) { + NonSlidingAttrs.addAtEnd(&AL); + } + } + processTypeAttrs(state, T, TAL_DeclName, NonSlidingAttrs); processTypeAttrs(state, T, TAL_DeclName, D.getAttributes()); // Diagnose any ignored type attributes. @@ -5773,6 +5819,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case DeclaratorContext::TrailingReturnVar: case DeclaratorContext::TemplateArg: case DeclaratorContext::TemplateTypeArg: + case DeclaratorContext::Association: // FIXME: We may want to allow parameter packs in block-literal contexts // in the future. S.Diag(D.getEllipsisLoc(), @@ -8136,6 +8183,34 @@ static void HandleMatrixTypeAttr(QualType &CurType, const ParsedAttr &Attr, CurType = T; } +static void HandleAnnotateTypeAttr(TypeProcessingState &State, + QualType &CurType, const ParsedAttr &PA) { + Sema &S = State.getSema(); + + if (PA.getNumArgs() < 1) { + S.Diag(PA.getLoc(), diag::err_attribute_too_few_arguments) << PA << 1; + return; + } + + // Make sure that there is a string literal as the annotation's first + // argument. + StringRef Str; + if (!S.checkStringLiteralArgumentAttr(PA, 0, Str)) + return; + + llvm::SmallVector Args; + Args.reserve(PA.getNumArgs() - 1); + for (unsigned Idx = 1; Idx < PA.getNumArgs(); Idx++) { + assert(!PA.isArgIdent(Idx)); + Args.push_back(PA.getArgAsExpr(Idx)); + } + if (!S.ConstantFoldAttrArgs(PA, Args)) + return; + auto *AnnotateTypeAttr = + AnnotateTypeAttr::Create(S.Context, Str, Args.data(), Args.size(), PA); + CurType = State.getAttributedType(AnnotateTypeAttr, CurType, CurType); +} + static void HandleLifetimeBoundAttr(TypeProcessingState &State, QualType &CurType, ParsedAttr &Attr) { @@ -8146,19 +8221,6 @@ static void HandleLifetimeBoundAttr(TypeProcessingState &State, } } -static bool isAddressSpaceKind(const ParsedAttr &attr) { - auto attrKind = attr.getKind(); - - return attrKind == ParsedAttr::AT_AddressSpace || - attrKind == ParsedAttr::AT_OpenCLPrivateAddressSpace || - attrKind == ParsedAttr::AT_OpenCLGlobalAddressSpace || - attrKind == ParsedAttr::AT_OpenCLGlobalDeviceAddressSpace || - attrKind == ParsedAttr::AT_OpenCLGlobalHostAddressSpace || - attrKind == ParsedAttr::AT_OpenCLLocalAddressSpace || - attrKind == ParsedAttr::AT_OpenCLConstantAddressSpace || - attrKind == ParsedAttr::AT_OpenCLGenericAddressSpace; -} - static void processTypeAttrs(TypeProcessingState &state, QualType &type, TypeAttrLocation TAL, const ParsedAttributesView &attrs) { @@ -8198,11 +8260,14 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, if (!IsTypeAttr) continue; } - } else if (TAL != TAL_DeclChunk && !isAddressSpaceKind(attr)) { + } else if (TAL != TAL_DeclSpec && TAL != TAL_DeclChunk && + !attr.isTypeAttr()) { // Otherwise, only consider type processing for a C++11 attribute if - // it's actually been applied to a type. - // We also allow C++11 address_space and - // OpenCL language address space attributes to pass through. + // - it has actually been applied to a type (decl-specifier-seq or + // declarator chunk), or + // - it is a type attribute, irrespective of where it was applied (so + // that we can support the legacy behavior of some type attributes + // that can be applied to the declaration name). continue; } } @@ -8220,10 +8285,14 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, break; case ParsedAttr::UnknownAttribute: - if (attr.isStandardAttributeSyntax() && TAL == TAL_DeclChunk) + if (attr.isStandardAttributeSyntax()) { state.getSema().Diag(attr.getLoc(), diag::warn_unknown_attribute_ignored) << attr << attr.getRange(); + // Mark the attribute as invalid so we don't emit the same diagnostic + // multiple times. + attr.setInvalid(); + } break; case ParsedAttr::IgnoredAttribute: @@ -8292,6 +8361,15 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, break; case ParsedAttr::AT_NoDeref: { + // FIXME: `noderef` currently doesn't work correctly in [[]] syntax. + // See https://github.com/llvm/llvm-project/issues/55790 for details. + // For the time being, we simply emit a warning that the attribute is + // ignored. + if (attr.isStandardAttributeSyntax()) { + state.getSema().Diag(attr.getLoc(), diag::warn_attribute_ignored) + << attr; + break; + } ASTContext &Ctx = state.getSema().Context; type = state.getAttributedType(createSimpleAttr(Ctx, attr), type, type); @@ -8369,6 +8447,16 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, FUNCTION_TYPE_ATTRS_CASELIST: attr.setUsedAsTypeAttr(); + // Attributes with standard syntax have strict rules for what they + // appertain to and hence should not use the "distribution" logic below. + if (attr.isStandardAttributeSyntax()) { + if (!handleFunctionTypeAttr(state, attr, type)) { + diagnoseBadTypeAttribute(state.getSema(), attr, type); + attr.setInvalid(); + } + break; + } + // Never process function type attributes as part of the // declaration-specifiers. if (TAL == TAL_DeclSpec) @@ -8399,6 +8487,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, attr.setUsedAsTypeAttr(); break; } + case ParsedAttr::AT_AnnotateType: { + HandleAnnotateTypeAttr(state, type, attr); + attr.setUsedAsTypeAttr(); + break; + } } // Handle attributes that are defined in a macro. We do not want this to be diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 76629a516cddd..3d20c5914c767 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -314,7 +314,7 @@ static bool checkLanguageOptions(const LangOptions &LangOpts, #define BENIGN_LANGOPT(Name, Bits, Default, Description) #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) -#define BENIGN_VALUE_LANGOPT(Name, Type, Bits, Default, Description) +#define BENIGN_VALUE_LANGOPT(Name, Bits, Default, Description) #include "clang/Basic/LangOptions.def" if (ExistingLangOpts.ModuleFeatures != LangOpts.ModuleFeatures) { diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 09342de1eee96..bb324a76020c7 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2431,6 +2431,7 @@ void ASTStmtReader::VisitOMPAtomicDirective(OMPAtomicDirective *D) { VisitOMPExecutableDirective(D); D->Flags.IsXLHSInRHSPart = Record.readBool() ? 1 : 0; D->Flags.IsPostfixUpdate = Record.readBool() ? 1 : 0; + D->Flags.IsFailOnly = Record.readBool() ? 1 : 0; } void ASTStmtReader::VisitOMPTargetDirective(OMPTargetDirective *D) { diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 587aad3f11e06..cd4b84421a28c 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2318,6 +2318,7 @@ void ASTStmtWriter::VisitOMPAtomicDirective(OMPAtomicDirective *D) { VisitOMPExecutableDirective(D); Record.writeBool(D->isXLHSInRHSPart()); Record.writeBool(D->isPostfixUpdate()); + Record.writeBool(D->isFailOnly()); Code = serialization::STMT_OMP_ATOMIC_DIRECTIVE; } diff --git a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp index ba15abbdca718..5be5bcde4d6ef 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp @@ -144,10 +144,9 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad, SVal extentBegin = computeExtentBegin(svalBuilder, rawOffset.getRegion()); if (Optional NV = extentBegin.getAs()) { - if (NV->getAs()) { + if (auto ConcreteNV = NV->getAs()) { std::pair simplifiedOffsets = - getSimplifiedOffsets(rawOffset.getByteOffset(), - NV->castAs(), + getSimplifiedOffsets(rawOffset.getByteOffset(), *ConcreteNV, svalBuilder); rawOffsetVal = simplifiedOffsets.first; *NV = simplifiedOffsets.second; @@ -180,13 +179,13 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad, // we are doing a load/store after the last valid offset. const MemRegion *MR = rawOffset.getRegion(); DefinedOrUnknownSVal Size = getDynamicExtent(state, MR, svalBuilder); - if (!Size.getAs()) + if (!isa(Size)) break; - if (Size.getAs()) { + if (auto ConcreteSize = Size.getAs()) { std::pair simplifiedOffsets = - getSimplifiedOffsets(rawOffset.getByteOffset(), - Size.castAs(), svalBuilder); + getSimplifiedOffsets(rawOffset.getByteOffset(), *ConcreteSize, + svalBuilder); rawOffsetVal = simplifiedOffsets.first; Size = simplifiedOffsets.second; } @@ -275,7 +274,7 @@ void RegionRawOffsetV2::dumpToStream(raw_ostream &os) const { // is unknown or undefined, we lazily substitute '0'. Otherwise, // return 'val'. static inline SVal getValue(SVal val, SValBuilder &svalBuilder) { - return val.getAs() ? svalBuilder.makeArrayIndex(0) : val; + return val.isUndef() ? svalBuilder.makeZeroArrayIndex() : val; } // Scale a base value by a scaling factor, and return the scaled @@ -324,7 +323,7 @@ RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(ProgramStateRef state, case MemRegion::ElementRegionKind: { const ElementRegion *elemReg = cast(region); SVal index = elemReg->getIndex(); - if (!index.getAs()) + if (!isa(index)) return RegionRawOffsetV2(); QualType elemType = elemReg->getElementType(); // If the element is an incomplete type, go no further. diff --git a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index 2c210fb6cdb97..970bfd2d241cc 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -347,10 +347,6 @@ class CFNumberChecker : public Checker< check::PreStmt > { CFNumberChecker() : ICreate(nullptr), IGetValue(nullptr) {} void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; - -private: - void EmitError(const TypedRegion* R, const Expr *Ex, - uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind); }; } // end anonymous namespace @@ -446,7 +442,7 @@ void CFNumberChecker::checkPreStmt(const CallExpr *CE, // FIXME: We really should allow ranges of valid theType values, and // bifurcate the state appropriately. - Optional V = TheTypeVal.getAs(); + Optional V = dyn_cast(TheTypeVal); if (!V) return; @@ -758,7 +754,7 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg, continue; // Ignore pointer constants. - if (msg.getArgSVal(I).getAs()) + if (isa(msg.getArgSVal(I))) continue; // Ignore pointer types annotated with 'NSObject' attribute. @@ -907,7 +903,7 @@ static ProgramStateRef checkElementNonNil(CheckerContext &C, // Go ahead and assume the value is non-nil. SVal Val = State->getSVal(*ElementLoc); - return State->assume(Val.castAs(), true); + return State->assume(cast(Val), true); } /// Returns NULL state if the collection is known to contain elements diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 57357dadd7562..2e4c8e6436988 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -696,7 +696,7 @@ ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C, NonLoc maxVal = svalBuilder.makeIntVal(maxValInt); SVal maxMinusRight; - if (right.getAs()) { + if (isa(right)) { maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, right, sizeTy); } else { @@ -1675,7 +1675,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, // amountCopied = min (size - dstLen - 1 , srcLen) SVal freeSpace = svalBuilder.evalBinOpNN(state, BO_Sub, *lenValNL, *dstStrLengthNL, sizeTy); - if (!freeSpace.getAs()) + if (!isa(freeSpace)) return; freeSpace = svalBuilder.evalBinOp(state, BO_Sub, freeSpace, diff --git a/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp index e2b99fca7d148..45f9a82a9d0a4 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp @@ -108,7 +108,7 @@ static const NoteTag *getNoteTag(CheckerContext &C, bool CastSucceeds, bool IsKnownCast) { std::string CastToName = CastInfo ? CastInfo->to()->getAsCXXRecordDecl()->getNameAsString() - : CastToTy->getPointeeCXXRecordDecl()->getNameAsString(); + : CastToTy.getAsString(); Object = Object->IgnoreParenImpCasts(); return C.getNoteTag( @@ -163,9 +163,9 @@ static const NoteTag *getNoteTag(CheckerContext &C, bool First = true; for (QualType CastToTy: CastToTyVec) { std::string CastToName = - CastToTy->getAsCXXRecordDecl() ? - CastToTy->getAsCXXRecordDecl()->getNameAsString() : - CastToTy->getPointeeCXXRecordDecl()->getNameAsString(); + CastToTy->getAsCXXRecordDecl() + ? CastToTy->getAsCXXRecordDecl()->getNameAsString() + : CastToTy.getAsString(); Out << ' ' << ((CastToTyVec.size() == 1) ? "not" : (First ? "neither" : "nor")) << " a '" << CastToName << '\''; diff --git a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp index bb5216266de81..a678c3827e7f1 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp @@ -248,7 +248,7 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S, DefinedOrUnknownSVal location = l.castAs(); // Check for null dereferences. - if (!location.getAs()) + if (!isa(location)) return; ProgramStateRef state = C.getState(); diff --git a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp index 0245549e6a723..aaf8cca32b606 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -56,9 +56,6 @@ class DynamicTypePropagation: check::PreObjCMessage, check::PostObjCMessage > { - const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE, - CheckerContext &C) const; - /// Return a better dynamic type if one can be derived from the cast. const ObjCObjectPointerType *getBetterObjCType(const Expr *CastE, CheckerContext &C) const; diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp index 6cdbcc65f6a6e..e39f783aa0cf9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp @@ -68,13 +68,7 @@ class ErrnoModeling /// Store a MemRegion that contains the 'errno' integer value. /// The value is null if the 'errno' value was not recognized in the AST. -REGISTER_TRAIT_WITH_PROGRAMSTATE(ErrnoRegion, const void *) - -/// An internal function accessing the errno region. -/// Returns null if there isn't any associated memory region. -static const MemRegion *getErrnoRegion(ProgramStateRef State) { - return reinterpret_cast(State->get()); -} +REGISTER_TRAIT_WITH_PROGRAMSTATE(ErrnoRegion, const MemRegion *) /// Search for a variable called "errno" in the AST. /// Return nullptr if not found. @@ -185,7 +179,7 @@ bool ErrnoModeling::evalCall(const CallEvent &Call, CheckerContext &C) const { if (ErrnoLocationCalls.contains(Call)) { ProgramStateRef State = C.getState(); - const MemRegion *ErrnoR = getErrnoRegion(State); + const MemRegion *ErrnoR = State->get(); if (!ErrnoR) return false; @@ -201,7 +195,7 @@ bool ErrnoModeling::evalCall(const CallEvent &Call, CheckerContext &C) const { void ErrnoModeling::checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const { // The special errno region should never garbage collected. - if (const auto *ErrnoR = getErrnoRegion(State)) + if (const MemRegion *ErrnoR = State->get()) SR.markLive(ErrnoR); } @@ -210,7 +204,7 @@ namespace ento { namespace errno_modeling { Optional getErrnoValue(ProgramStateRef State) { - const MemRegion *ErrnoR = getErrnoRegion(State); + const MemRegion *ErrnoR = State->get(); if (!ErrnoR) return {}; QualType IntTy = State->getAnalysisManager().getASTContext().IntTy; @@ -219,7 +213,7 @@ Optional getErrnoValue(ProgramStateRef State) { ProgramStateRef setErrnoValue(ProgramStateRef State, const LocationContext *LCtx, SVal Value) { - const MemRegion *ErrnoR = getErrnoRegion(State); + const MemRegion *ErrnoR = State->get(); if (!ErrnoR) return State; return State->bindLoc(loc::MemRegionVal{ErrnoR}, Value, LCtx); @@ -227,7 +221,7 @@ ProgramStateRef setErrnoValue(ProgramStateRef State, ProgramStateRef setErrnoValue(ProgramStateRef State, CheckerContext &C, uint64_t Value) { - const MemRegion *ErrnoR = getErrnoRegion(State); + const MemRegion *ErrnoR = State->get(); if (!ErrnoR) return State; return State->bindLoc( diff --git a/clang/lib/StaticAnalyzer/Checkers/FuchsiaHandleChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/FuchsiaHandleChecker.cpp index 6e4801aa8e91b..eb3b89ee6c5ca 100644 --- a/clang/lib/StaticAnalyzer/Checkers/FuchsiaHandleChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/FuchsiaHandleChecker.cpp @@ -254,9 +254,6 @@ static const ExplodedNode *getAcquireSite(const ExplodedNode *N, SymbolRef Sym, namespace { class FuchsiaHandleSymbolVisitor final : public SymbolVisitor { public: - FuchsiaHandleSymbolVisitor(ProgramStateRef State) : State(std::move(State)) {} - ProgramStateRef getState() const { return State; } - bool VisitSymbol(SymbolRef S) override { if (const auto *HandleType = S->getType()->getAs()) if (HandleType->getDecl()->getName() == HandleTypeName) @@ -268,7 +265,6 @@ class FuchsiaHandleSymbolVisitor final : public SymbolVisitor { private: SmallVector Symbols; - ProgramStateRef State; }; } // end anonymous namespace @@ -284,7 +280,7 @@ getFuchsiaHandleSymbols(QualType QT, SVal Arg, ProgramStateRef State) { if (QT->isStructureType()) { // If we see a structure, see if there is any handle referenced by the // structure. - FuchsiaHandleSymbolVisitor Visitor(State); + FuchsiaHandleSymbolVisitor Visitor; State->scanReachableSymbols(Arg, Visitor); return Visitor.GetSymbols(); } diff --git a/clang/lib/StaticAnalyzer/Checkers/GTestChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GTestChecker.cpp index 8d9afbe88aa84..5bf05033a9a0c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/GTestChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/GTestChecker.cpp @@ -135,7 +135,7 @@ void GTestChecker::modelAssertionResultBoolConstructor( SVal BooleanArgVal = Call->getArgSVal(0); if (IsRef) { // The argument is a reference, so load from it to get the boolean value. - if (!BooleanArgVal.getAs()) + if (!isa(BooleanArgVal)) return; BooleanArgVal = C.getState()->getSVal(BooleanArgVal.castAs()); } @@ -270,20 +270,17 @@ SVal GTestChecker::getAssertionResultSuccessFieldValue( ProgramStateRef GTestChecker::assumeValuesEqual(SVal Val1, SVal Val2, ProgramStateRef State, CheckerContext &C) { - if (!Val1.getAs() || - !Val2.getAs()) + auto DVal1 = Val1.getAs(); + auto DVal2 = Val2.getAs(); + if (!DVal1.hasValue() || !DVal2.hasValue()) return State; auto ValuesEqual = - C.getSValBuilder().evalEQ(State, Val1.castAs(), - Val2.castAs()); - - if (!ValuesEqual.getAs()) + C.getSValBuilder().evalEQ(State, *DVal1, *DVal2).getAs(); + if (!ValuesEqual.hasValue()) return State; - State = C.getConstraintManager().assume( - State, ValuesEqual.castAs(), true); - + State = C.getConstraintManager().assume(State, *ValuesEqual, true); return State; } diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp index 7e237b471def5..2c02ffe33dea6 100644 --- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp @@ -92,10 +92,8 @@ bool isStdin(SVal Val, const ASTContext &ACtx) { return false; // Get it's symbol and find the declaration region it's pointing to. - const auto *Sm = dyn_cast(SymReg->getSymbol()); - if (!Sm) - return false; - const auto *DeclReg = dyn_cast(Sm->getRegion()); + const auto *DeclReg = + dyn_cast_or_null(SymReg->getSymbol()->getOriginRegion()); if (!DeclReg) return false; @@ -176,15 +174,6 @@ class ArgSet { bool isEmpty() const { return DiscreteArgs.empty() && !VariadicIndex; } - ArgVecTy ArgsUpTo(ArgIdxTy LastArgIdx) const { - ArgVecTy Args; - for (ArgIdxTy I = ReturnValueIndex; I <= LastArgIdx; ++I) { - if (contains(I)) - Args.push_back(I); - } - return Args; - } - private: ArgVecTy DiscreteArgs; Optional VariadicIndex; @@ -340,11 +329,6 @@ struct GenericTaintRuleParser { class GenericTaintChecker : public Checker { public: - static void *getTag() { - static int Tag; - return &Tag; - } - void checkPreCall(const CallEvent &Call, CheckerContext &C) const; void checkPostCall(const CallEvent &Call, CheckerContext &C) const; @@ -866,7 +850,7 @@ void GenericTaintRule::process(const GenericTaintChecker &Checker, return; const auto WouldEscape = [](SVal V, QualType Ty) -> bool { - if (!V.getAs()) + if (!isa(V)) return false; const bool IsNonConstRef = Ty->isReferenceType() && !Ty.isConstQualified(); diff --git a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp index 4961901499914..38ed9e702db4d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp @@ -308,8 +308,8 @@ bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2, const auto comparison = SVB.evalBinOp(State, Opc, NL1, NL2, SVB.getConditionType()); - assert(comparison.getAs() && - "Symbol comparison must be a `DefinedSVal`"); + assert(isa(comparison) && + "Symbol comparison must be a `DefinedSVal`"); return !State->assume(comparison.castAs(), false); } diff --git a/clang/lib/StaticAnalyzer/Checkers/Iterator.h b/clang/lib/StaticAnalyzer/Checkers/Iterator.h index 37157492fe3e9..353daf0bed08e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/Iterator.h +++ b/clang/lib/StaticAnalyzer/Checkers/Iterator.h @@ -63,9 +63,7 @@ struct IteratorPosition { return Cont == X.Cont && Valid == X.Valid && Offset == X.Offset; } - bool operator!=(const IteratorPosition &X) const { - return Cont != X.Cont || Valid != X.Valid || Offset != X.Offset; - } + bool operator!=(const IteratorPosition &X) const { return !(*this == X); } void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddPointer(Cont); @@ -101,9 +99,7 @@ struct ContainerData { return Begin == X.Begin && End == X.End; } - bool operator!=(const ContainerData &X) const { - return Begin != X.Begin || End != X.End; - } + bool operator!=(const ContainerData &X) const { return !(*this == X); } void Profile(llvm::FoldingSetNodeID &ID) const { ID.Add(Begin); diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp index 235c9010412a2..80431e65519ec 100644 --- a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp @@ -151,8 +151,6 @@ class IteratorModeling void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const; void checkPostStmt(const UnaryOperator *UO, CheckerContext &C) const; void checkPostStmt(const BinaryOperator *BO, CheckerContext &C) const; - void checkPostStmt(const CXXConstructExpr *CCE, CheckerContext &C) const; - void checkPostStmt(const DeclStmt *DS, CheckerContext &C) const; void checkPostStmt(const MaterializeTemporaryExpr *MTE, CheckerContext &C) const; void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const; @@ -631,7 +629,7 @@ void IteratorModeling::handlePtrIncrOrDecr(CheckerContext &C, const Expr *Iterator, OverloadedOperatorKind OK, SVal Offset) const { - if (!Offset.getAs()) + if (!isa(Offset)) return; QualType PtrType = Iterator->getType(); @@ -801,8 +799,8 @@ ProgramStateRef relateSymbols(ProgramStateRef State, SymbolRef Sym1, SVB.evalBinOp(State, BO_EQ, nonloc::SymbolVal(Sym1), nonloc::SymbolVal(Sym2), SVB.getConditionType()); - assert(comparison.getAs() && - "Symbol comparison must be a `DefinedSVal`"); + assert(isa(comparison) && + "Symbol comparison must be a `DefinedSVal`"); auto NewState = State->assume(comparison.castAs(), Equal); if (!NewState) diff --git a/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp index 5d6bd381d3ccf..4c0a8ba2c7c09 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp @@ -165,7 +165,7 @@ void MPIChecker::allRegionsUsedByWait( Ctx.getState(), SuperRegion, Ctx.getSValBuilder(), CE.getArgExpr(1)->getType()->getPointeeType()); const llvm::APSInt &ArrSize = - ElementCount.getAs()->getValue(); + ElementCount.castAs().getValue(); for (size_t i = 0; i < ArrSize; ++i) { const NonLoc Idx = Ctx.getSValBuilder().makeArrayIndex(i); diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index ae9a7bc6a3914..b23edb127322a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -927,11 +927,6 @@ class NoOwnershipChangeVisitor final : public NoStateChangeFuncVisitor { ID.AddPointer(&Tag); ID.AddPointer(Sym); } - - void *getTag() const { - static int Tag = 0; - return static_cast(&Tag); - } }; } // end anonymous namespace @@ -1187,7 +1182,7 @@ MallocChecker::performKernelMalloc(const CallEvent &Call, CheckerContext &C, const Expr *FlagsEx = Call.getArgExpr(Call.getNumArgs() - 1); const SVal V = C.getSVal(FlagsEx); - if (!V.getAs()) { + if (!isa(V)) { // The case where 'V' can be a location can only be due to a bad header, // so in this case bail out. return None; @@ -1912,12 +1907,12 @@ ProgramStateRef MallocChecker::FreeMemAux( return nullptr; SVal ArgVal = C.getSVal(ArgExpr); - if (!ArgVal.getAs()) + if (!isa(ArgVal)) return nullptr; DefinedOrUnknownSVal location = ArgVal.castAs(); // Check for null dereferences. - if (!location.getAs()) + if (!isa(location)) return nullptr; // The explicit NULL case, no operation is performed. @@ -2587,7 +2582,7 @@ MallocChecker::ReallocMemAux(CheckerContext &C, const CallEvent &Call, const Expr *arg0Expr = CE->getArg(0); SVal Arg0Val = C.getSVal(arg0Expr); - if (!Arg0Val.getAs()) + if (!isa(Arg0Val)) return nullptr; DefinedOrUnknownSVal arg0Val = Arg0Val.castAs(); @@ -2603,7 +2598,7 @@ MallocChecker::ReallocMemAux(CheckerContext &C, const CallEvent &Call, SVal TotalSize = C.getSVal(Arg1); if (SuffixWithN) TotalSize = evalMulForBufferSize(C, Arg1, CE->getArg(2)); - if (!TotalSize.getAs()) + if (!isa(TotalSize)) return nullptr; // Compare the size argument to 0. @@ -2913,7 +2908,7 @@ void MallocChecker::checkPreCall(const CallEvent &Call, // Check arguments for being used after free. for (unsigned I = 0, E = Call.getNumArgs(); I != E; ++I) { SVal ArgSVal = Call.getArgSVal(I); - if (ArgSVal.getAs()) { + if (isa(ArgSVal)) { SymbolRef Sym = ArgSVal.getAsSymbol(); if (!Sym) continue; diff --git a/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp index aa70db041c762..1906ca5c8f554 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp @@ -48,8 +48,8 @@ void MmapWriteExecChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const { if (matchesAny(Call, MmapFn, MprotectFn)) { SVal ProtVal = Call.getArgSVal(2); - Optional ProtLoc = ProtVal.getAs(); - int64_t Prot = ProtLoc->getValue().getSExtValue(); + auto ProtLoc = ProtVal.castAs(); + int64_t Prot = ProtLoc.getValue().getSExtValue(); if (ProtExecOv != ProtExec) ProtExec = ProtExecOv; if (ProtReadOv != ProtRead) diff --git a/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp index 4a232c6f4b3f6..e78c130a9c228 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp @@ -49,7 +49,6 @@ class MoveChecker : public Checker { public: - void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const; void checkPreCall(const CallEvent &MC, CheckerContext &C) const; void checkPostCall(const CallEvent &MC, CheckerContext &C) const; void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; diff --git a/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp index 33242b827bacd..fea35d03cb813 100644 --- a/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp @@ -214,7 +214,7 @@ void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad, CheckerContext &C) const { if (!isLoad) return; - if (loc.isUndef() || !loc.getAs()) + if (loc.isUndef() || !isa(loc)) return; ASTContext &Ctx = C.getASTContext(); diff --git a/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp index 534b5d68434f9..3481936e572bf 100644 --- a/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp @@ -136,10 +136,10 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call, if (!DV) continue; - assert(!HasRefTypeParam || DV->getAs()); + assert(!HasRefTypeParam || isa(DV.getValue())); // Process the case when the argument is not a location. - if (ExpectedToBeNonNull && !DV->getAs()) { + if (ExpectedToBeNonNull && !isa(DV.getValue())) { // If the argument is a union type, we want to handle a potential // transparent_union GCC extension. if (!ArgE) @@ -161,7 +161,7 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call, assert(++CSV->begin() == CSV->end()); // FIXME: Handle (some_union){ some_other_union_val }, which turns into // a LazyCompoundVal inside a CompoundVal. - if (!V.getAs()) + if (!isa(V)) continue; // Retrieve the corresponding expression. diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp index 43af4bb142867..a6383009e1feb 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp @@ -41,7 +41,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S, SVal V = C.getSVal(Ex); // Uninitialized value used for the mutex? - if (V.getAs()) { + if (isa(V)) { if (ExplodedNode *N = C.generateErrorNode()) { if (!BT_undef) BT_undef.reset(new BuiltinBug(this, "Uninitialized value used as mutex " diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp index c15b5f4ee609a..0244a7a3ebffb 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp @@ -47,9 +47,6 @@ class ObjCContainersChecker : public Checker< check::PreStmt, CheckerContext &C) const; public: - /// A tag to id this checker. - static void *getTag() { static int Tag; return &Tag; } - void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; ProgramStateRef checkPointerEscape(ProgramStateRef State, diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp index 17d3c042ac403..9f1a6e416dc6d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp @@ -94,19 +94,19 @@ enum SelfFlagEnum { }; } -REGISTER_MAP_WITH_PROGRAMSTATE(SelfFlag, SymbolRef, unsigned) +REGISTER_MAP_WITH_PROGRAMSTATE(SelfFlag, SymbolRef, SelfFlagEnum) REGISTER_TRAIT_WITH_PROGRAMSTATE(CalledInit, bool) /// A call receiving a reference to 'self' invalidates the object that /// 'self' contains. This keeps the "self flags" assigned to the 'self' /// object before the call so we can assign them to the new object that 'self' /// points to after the call. -REGISTER_TRAIT_WITH_PROGRAMSTATE(PreCallSelfFlags, unsigned) +REGISTER_TRAIT_WITH_PROGRAMSTATE(PreCallSelfFlags, SelfFlagEnum) static SelfFlagEnum getSelfFlags(SVal val, ProgramStateRef state) { if (SymbolRef sym = val.getAsSymbol()) - if (const unsigned *attachedFlags = state->get(sym)) - return (SelfFlagEnum)*attachedFlags; + if (const SelfFlagEnum *attachedFlags = state->get(sym)) + return *attachedFlags; return SelfFlag_None; } @@ -118,7 +118,8 @@ static void addSelfFlag(ProgramStateRef state, SVal val, SelfFlagEnum flag, CheckerContext &C) { // We tag the symbol that the SVal wraps. if (SymbolRef sym = val.getAsSymbol()) { - state = state->set(sym, getSelfFlags(val, state) | flag); + state = state->set(sym, + SelfFlagEnum(getSelfFlags(val, state) | flag)); C.addTransition(state); } } @@ -251,11 +252,12 @@ void ObjCSelfInitChecker::checkPreCall(const CallEvent &CE, for (unsigned i = 0; i < NumArgs; ++i) { SVal argV = CE.getArgSVal(i); if (isSelfVar(argV, C)) { - unsigned selfFlags = getSelfFlags(state->getSVal(argV.castAs()), C); + SelfFlagEnum selfFlags = + getSelfFlags(state->getSVal(argV.castAs()), C); C.addTransition(state->set(selfFlags)); return; } else if (hasSelfFlag(argV, SelfFlag_Self, C)) { - unsigned selfFlags = getSelfFlags(argV, C); + SelfFlagEnum selfFlags = getSelfFlags(argV, C); C.addTransition(state->set(selfFlags)); return; } @@ -270,7 +272,7 @@ void ObjCSelfInitChecker::checkPostCall(const CallEvent &CE, return; ProgramStateRef state = C.getState(); - SelfFlagEnum prevFlags = (SelfFlagEnum)state->get(); + SelfFlagEnum prevFlags = state->get(); if (!prevFlags) return; state = state->remove(); @@ -338,7 +340,7 @@ void ObjCSelfInitChecker::printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const { SelfFlagTy FlagMap = State->get(); bool DidCallInit = State->get(); - SelfFlagEnum PreCallFlags = (SelfFlagEnum)State->get(); + SelfFlagEnum PreCallFlags = State->get(); if (FlagMap.isEmpty() && !DidCallInit && !PreCallFlags) return; @@ -411,7 +413,7 @@ static bool isSelfVar(SVal location, CheckerContext &C) { AnalysisDeclContext *analCtx = C.getCurrentAnalysisDeclContext(); if (!analCtx->getSelfDecl()) return false; - if (!location.getAs()) + if (!isa(location)) return false; loc::MemRegionVal MRV = location.castAs(); diff --git a/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp index ea72ebe3ed57f..e9d5d306cc06b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp @@ -131,7 +131,7 @@ void STLAlgorithmModeling::Find(CheckerContext &C, const CallExpr *CE, nonloc::SymbolVal(NewPos->getOffset()), nonloc::SymbolVal(Pos->getOffset()), SVB.getConditionType()); - assert(GreaterOrEqual.getAs() && + assert(isa(GreaterOrEqual) && "Symbol comparison must be a `DefinedSVal`"); StateFound = StateFound->assume(GreaterOrEqual.castAs(), true); } @@ -153,7 +153,7 @@ void STLAlgorithmModeling::Find(CheckerContext &C, const CallExpr *CE, nonloc::SymbolVal(NewPos->getOffset()), nonloc::SymbolVal(Pos->getOffset()), SVB.getConditionType()); - assert(Less.getAs() && + assert(isa(Less) && "Symbol comparison must be a `DefinedSVal`"); StateFound = StateFound->assume(Less.castAs(), true); } diff --git a/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp index 1de5d7285f652..8c87a548fd91e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp @@ -89,20 +89,6 @@ class SimpleStreamChecker : public Checkerremove(sym); - return true; - } -}; -} // end anonymous namespace - SimpleStreamChecker::SimpleStreamChecker() : OpenFn("fopen"), CloseFn("fclose", 1) { // Initialize the bug types. diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp index 880a49eb15f63..92eef20d2daaf 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp @@ -50,7 +50,6 @@ class SmartPtrModeling // Whether the checker should model for null dereferences of smart pointers. bool ModelSmartPtrDereference = false; bool evalCall(const CallEvent &Call, CheckerContext &C) const; - void checkPreCall(const CallEvent &Call, CheckerContext &C) const; void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; ProgramStateRef checkRegionChanges(ProgramStateRef State, diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index b8508df95474c..786e2f1c5a3fb 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -254,7 +254,7 @@ class StdLibraryFunctionsChecker return State; DefinedOrUnknownSVal L = V.castAs(); - if (!L.getAs()) + if (!isa(L)) return State; return State->assume(L, CannotBeNull); diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index b16e1f012251d..1aa665f0ef45d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -146,7 +146,7 @@ struct StreamState { void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddPointer(LastOperation); ID.AddInteger(State); - ID.AddInteger(ErrorState); + ErrorState.Profile(ID); ID.AddBoolean(FilePositionIndeterminate); } }; diff --git a/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp index 85c81d2c4f451..614a2b2e4ec79 100644 --- a/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp @@ -22,27 +22,15 @@ using namespace ento; using namespace taint; namespace { -class TaintTesterChecker : public Checker< check::PostStmt > { - - mutable std::unique_ptr BT; - void initBugType() const; - - /// Given a pointer argument, get the symbol of the value it contains - /// (points to). - SymbolRef getPointedToSymbol(CheckerContext &C, - const Expr* Arg, - bool IssueWarning = true) const; +class TaintTesterChecker : public Checker> { + std::unique_ptr BT = + std::make_unique(this, "Tainted data", "General"); public: void checkPostStmt(const Expr *E, CheckerContext &C) const; }; } -inline void TaintTesterChecker::initBugType() const { - if (!BT) - BT.reset(new BugType(this, "Tainted data", "General")); -} - void TaintTesterChecker::checkPostStmt(const Expr *E, CheckerContext &C) const { ProgramStateRef State = C.getState(); @@ -51,7 +39,6 @@ void TaintTesterChecker::checkPostStmt(const Expr *E, if (isTainted(State, E, C.getLocationContext())) { if (ExplodedNode *N = C.generateNonFatalErrorNode()) { - initBugType(); auto report = std::make_unique(*BT, "tainted", N); report->addRange(E->getSourceRange()); C.emitReport(std::move(report)); diff --git a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp index 4182b51c02b08..38e69e81d8006 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp @@ -330,7 +330,7 @@ bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R, SVal V = State->getSVal(FieldVal); - if (isDereferencableType(T) || V.getAs()) { + if (isDereferencableType(T) || isa(V)) { if (isDereferencableUninit(FR, LocalChain)) ContainsUninitField = true; continue; diff --git a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp index f0dd0bf813aff..a6e81b3657a2a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp @@ -141,10 +141,10 @@ bool FindUninitializedFields::isDereferencableUninit( SVal V = State->getSVal(FR); assert((isDereferencableType(FR->getDecl()->getType()) || - V.getAs()) && + isa(V)) && "This method only checks dereferenceable objects!"); - if (V.isUnknown() || V.getAs()) { + if (V.isUnknown() || isa(V)) { IsAnyFieldInitialized = true; return false; } @@ -230,8 +230,8 @@ static llvm::Optional dereference(ProgramStateRef State, // If the static type of the field is a void pointer, or it is a // nonloc::LocAsInteger, we need to cast it back to the dynamic type before // dereferencing. - bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()) || - V.getAs(); + bool NeedsCastBack = + isVoidPointer(FR->getDecl()->getType()) || isa(V); // The region we'd like to acquire. const auto *R = V.getAsRegion()->getAs(); diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index 4e3024c1b06c3..c5d86f6b9a204 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -43,8 +43,6 @@ class UnixAPIMisuseChecker : public Checker< check::PreStmt > { mutable Optional Val_O_CREAT; public: - bool CheckMisuse = false, CheckPortability = false; - void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; void CheckOpen(CheckerContext &C, const CallExpr *CE) const; @@ -229,7 +227,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, // Now check if oflags has O_CREAT set. const Expr *oflagsEx = CE->getArg(FlagsArgIndex); const SVal V = C.getSVal(oflagsEx); - if (!V.getAs()) { + if (!isa(V)) { // The case where 'V' can be a location can only be due to a bad header, // so in this case bail out. return; @@ -503,7 +501,7 @@ void UnixAPIPortabilityChecker::checkPreStmt(const CallExpr *CE, mgr.registerChecker(); \ } \ \ - bool ento::shouldRegister##CHECKERNAME(const CheckerManager &mgr) { \ + bool ento::shouldRegister##CHECKERNAME(const CheckerManager &mgr) { \ return true; \ } diff --git a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp index f0dc6f5f6d3de..cf519b085892d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp @@ -278,8 +278,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { if (!State) return; - auto ArraySizeNL = ArraySize.getAs(); - if (!ArraySizeNL) { + if (!isa(ArraySize)) { // Array size could not be determined but state may contain new assumptions. C.addTransition(State); return; @@ -289,7 +288,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { if (VD) { State = setDynamicExtent(State, State->getRegion(VD, C.getLocationContext()), - ArraySize.castAs(), SVB); + ArraySize.castAs(), SVB); } // Remember our assumptions! diff --git a/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp index a09fa3d33892c..084789509533e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp @@ -82,9 +82,7 @@ class InvalidPtrChecker REGISTER_SET_WITH_PROGRAMSTATE(InvalidMemoryRegions, const MemRegion *) // Stores the region of the environment pointer of 'main' (if present). -// Note: This pointer has type 'const MemRegion *', however the trait is only -// specialized to 'const void*' and 'void*' -REGISTER_TRAIT_WITH_PROGRAMSTATE(EnvPtrRegion, const void *) +REGISTER_TRAIT_WITH_PROGRAMSTATE(EnvPtrRegion, const MemRegion *) // Stores key-value pairs, where key is function declaration and value is // pointer to memory region returned by previous call of this function @@ -95,11 +93,9 @@ void InvalidPtrChecker::EnvpInvalidatingCall(const CallEvent &Call, CheckerContext &C) const { StringRef FunctionName = Call.getCalleeIdentifier()->getName(); ProgramStateRef State = C.getState(); - const auto *Reg = State->get(); - if (!Reg) + const MemRegion *SymbolicEnvPtrRegion = State->get(); + if (!SymbolicEnvPtrRegion) return; - const auto *SymbolicEnvPtrRegion = - reinterpret_cast(const_cast(Reg)); State = State->add(SymbolicEnvPtrRegion); @@ -245,9 +241,7 @@ void InvalidPtrChecker::checkBeginFunction(CheckerContext &C) const { // Save the memory region pointed by the environment pointer parameter of // 'main'. - State = State->set( - reinterpret_cast(const_cast(EnvpReg))); - C.addTransition(State); + C.addTransition(State->set(EnvpReg)); } // Check if invalidated region is being dereferenced. diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index ccdc60049e40b..f02a1739a286f 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -527,11 +527,6 @@ class NoStoreFuncVisitor final : public NoStateChangeFuncVisitor { ID.AddPointer(RegionOfInterest); } - void *getTag() const { - static int Tag = 0; - return static_cast(&Tag); - } - private: /// \return Whether \c RegionOfInterest was modified at \p CurrN compared to /// the value it holds in \p CallExitBeginN. @@ -919,7 +914,7 @@ class MacroNullReturnSuppressionVisitor final : public BugReporterVisitor { const SVal V) { AnalyzerOptions &Options = N->getState()->getAnalysisManager().options; if (EnableNullFPSuppression && Options.ShouldSuppressNullReturnPaths && - V.getAs()) + isa(V)) BR.addVisitor(R->getAs(), V); } @@ -1035,14 +1030,13 @@ class ReturnVisitor : public TrackingBugReporterVisitor { if (RetE->isGLValue()) { if ((LValue = V.getAs())) { SVal RValue = State->getRawSVal(*LValue, RetE->getType()); - if (RValue.getAs()) + if (isa(RValue)) V = RValue; } } // Ignore aggregate rvalues. - if (V.getAs() || - V.getAs()) + if (isa(V)) return nullptr; RetE = RetE->IgnoreParenCasts(); @@ -1057,7 +1051,7 @@ class ReturnVisitor : public TrackingBugReporterVisitor { bool WouldEventBeMeaningless = false; if (State->isNull(V).isConstrainedTrue()) { - if (V.getAs()) { + if (isa(V)) { // If we have counter-suppression enabled, make sure we keep visiting // future nodes. We want to emit a path note as well, in case @@ -1087,10 +1081,7 @@ class ReturnVisitor : public TrackingBugReporterVisitor { if (N->getCFG().size() == 3) WouldEventBeMeaningless = true; - if (V.getAs()) - Out << "Returning pointer"; - else - Out << "Returning value"; + Out << (isa(V) ? "Returning pointer" : "Returning value"); } } @@ -1313,7 +1304,7 @@ static void showBRDiagnostics(llvm::raw_svector_ostream &OS, StoreInfo SI) { llvm_unreachable("Unexpected store kind"); } - if (SI.Value.getAs()) { + if (isa(SI.Value)) { OS << Action << (isObjCPointer(SI.Dest) ? "nil" : "a null pointer value"); } else if (auto CVal = SI.Value.getAs()) { @@ -1356,7 +1347,7 @@ static void showBRParamDiagnostics(llvm::raw_svector_ostream &OS, OS << "Passing "; - if (SI.Value.getAs()) { + if (isa(SI.Value)) { OS << (isObjCPointer(Param) ? "nil object reference" : "null pointer value"); @@ -1387,7 +1378,7 @@ static void showBRDefaultDiagnostics(llvm::raw_svector_ostream &OS, StoreInfo SI) { const bool HasSuffix = SI.Dest->canPrintPretty(); - if (SI.Value.getAs()) { + if (isa(SI.Value)) { OS << (isObjCPointer(SI.Dest) ? "nil object reference stored" : (HasSuffix ? "Null pointer value stored" : "Storing null pointer value")); @@ -1685,7 +1676,7 @@ PathDiagnosticPieceRef TrackConstraintBRVisitor::VisitNode( SmallString<64> sbuf; llvm::raw_svector_ostream os(sbuf); - if (Constraint.getAs()) { + if (isa(Constraint)) { os << "Assuming pointer value is "; os << (Assumption ? "non-null" : "null"); } diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp index 135e541c6390c..58963b87d0d3d 100644 --- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -680,7 +680,7 @@ SVal CXXInstanceCall::getCXXThisVal() const { return UnknownVal(); SVal ThisVal = getSVal(Base); - assert(ThisVal.isUnknownOrUndef() || ThisVal.getAs()); + assert(ThisVal.isUnknownOrUndef() || isa(ThisVal)); return ThisVal; } diff --git a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp index 73d5d9489cb78..1e2532d276338 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp @@ -127,10 +127,10 @@ static bool evalComparison(SVal LHSVal, BinaryOperatorKind ComparisonOp, if (LHSVal.isUnknownOrUndef()) return false; ProgramStateManager &Mgr = State->getStateManager(); - if (!LHSVal.getAs()) { + if (!isa(LHSVal)) { LHSVal = Mgr.getStoreManager().getBinding(State->getStore(), LHSVal.castAs()); - if (LHSVal.isUnknownOrUndef() || !LHSVal.getAs()) + if (LHSVal.isUnknownOrUndef() || !isa(LHSVal)) return false; } diff --git a/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp index 096266f75ce6c..9ef3455a110a8 100644 --- a/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp @@ -16,6 +16,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "llvm/ADT/ScopeExit.h" using namespace clang; using namespace ento; @@ -46,6 +47,21 @@ template ConstraintManager::ProgramStatePair ConstraintManager::assumeDualImpl(ProgramStateRef &State, AssumeFunction &Assume) { + if (LLVM_UNLIKELY(State->isPosteriorlyOverconstrained())) + return {State, State}; + + // Assume functions might recurse (see `reAssume` or `tryRearrange`). During + // the recursion the State might not change anymore, that means we reached a + // fixpoint. + // We avoid infinite recursion of assume calls by checking already visited + // States on the stack of assume function calls. + const ProgramState *RawSt = State.get(); + if (LLVM_UNLIKELY(AssumeStack.contains(RawSt))) + return {State, State}; + AssumeStack.push(RawSt); + auto AssumeStackBuilder = + llvm::make_scope_exit([this]() { AssumeStack.pop(); }); + ProgramStateRef StTrue = Assume(true); if (!StTrue) { diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 55920c1a7566e..9e97d711d46ad 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -118,18 +118,10 @@ namespace { /// the construction context was present and contained references to these /// AST nodes. class ConstructedObjectKey { - typedef std::pair - ConstructedObjectKeyImpl; - + using ConstructedObjectKeyImpl = + std::pair; const ConstructedObjectKeyImpl Impl; - const void *getAnyASTNodePtr() const { - if (const Stmt *S = getItem().getStmtOrNull()) - return S; - else - return getItem().getCXXCtorInitializer(); - } - public: explicit ConstructedObjectKey(const ConstructionContextItem &Item, const LocationContext *LC) @@ -312,7 +304,7 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded( if (!Result) { // If we don't have an explicit result expression, we're in "if needed" // mode. Only create a region if the current value is a NonLoc. - if (!InitValWithAdjustments.getAs()) { + if (!isa(InitValWithAdjustments)) { if (OutRegionWithAdjustments) *OutRegionWithAdjustments = nullptr; return State; @@ -321,7 +313,7 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded( } else { // We need to create a region no matter what. Make sure we don't try to // stuff a Loc into a non-pointer temporary region. - assert(!InitValWithAdjustments.getAs() || + assert(!isa(InitValWithAdjustments) || Loc::isLocType(Result->getType()) || Result->getType()->isMemberPointerType()); } @@ -613,6 +605,8 @@ void ExprEngine::printJson(raw_ostream &Out, ProgramStateRef State, } void ExprEngine::processEndWorklist() { + // This prints the name of the top-level function if we crash. + PrettyStackTraceLocationContext CrashInfo(getRootLocationContext()); getCheckerManager().runCheckersForEndAnalysis(G, BR, *this); } @@ -2341,7 +2335,7 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) { llvm_unreachable("No block with label."); } - if (V.getAs() || V.getAs()) { + if (isa(V)) { // Dispatch to the first target and mark it as a sink. //ExplodedNode* N = builder.generateNode(builder.begin(), state, true); // FIXME: add checker visit. @@ -2892,7 +2886,7 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, // If the location is not a 'Loc', it will already be handled by // the checkers. There is nothing left to do. - if (!location.getAs()) { + if (!isa(location)) { const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/nullptr, /*tag*/nullptr); ProgramStateRef state = Pred->getState(); @@ -2962,7 +2956,7 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst, SVal location, const ProgramPointTag *tag, QualType LoadTy) { - assert(!location.getAs() && "location cannot be a NonLoc."); + assert(!isa(location) && "location cannot be a NonLoc."); assert(NodeEx); assert(BoundEx); // Evaluate the location (checks for bad dereferences). @@ -3093,7 +3087,7 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, for (const Expr *O : A->outputs()) { SVal X = state->getSVal(O, Pred->getLocationContext()); - assert(!X.getAs()); // Should be an Lval, or unknown, undef. + assert(!isa(X)); // Should be an Lval, or unknown, undef. if (Optional LV = X.getAs()) state = state->bindLoc(*LV, UnknownVal(), Pred->getLocationContext()); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 45e2b34b106a2..43e298f3de088 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -29,8 +29,7 @@ static SVal conjureOffsetSymbolOnLocation( SVal Symbol, SVal Other, Expr* Expression, SValBuilder &svalBuilder, unsigned Count, const LocationContext *LCtx) { QualType Ty = Expression->getType(); - if (Other.getAs() && - Ty->isIntegralOrEnumerationType() && + if (isa(Other) && Ty->isIntegralOrEnumerationType() && Symbol.isUnknown()) { return svalBuilder.conjureSymbolVal(Expression, LCtx, Ty, Count); } @@ -372,7 +371,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_IntegralToPointer: case CK_PointerToIntegral: { SVal V = state->getSVal(Ex, LCtx); - if (V.getAs()) { + if (isa(V)) { state = state->BindExpr(CastE, LCtx, UnknownVal()); Bldr.generateNode(CastE, Pred, state); continue; diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 04de5050a681e..5a9e7169155b2 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -129,7 +129,7 @@ static std::pair()) + if (!isa(V)) return V; // If the types already match, don't do any unnecessary work. diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index 7c9babf894c7b..f0cda835e07c2 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -973,26 +973,14 @@ const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D, const MemRegion *sReg = nullptr; if (D->hasGlobalStorage() && !D->isStaticLocal()) { - - // First handle the globals defined in system headers. - if (Ctx.getSourceManager().isInSystemHeader(D->getLocation())) { - // Allow the system globals which often DO GET modified, assume the - // rest are immutable. - if (D->getName().contains("errno")) - sReg = getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind); - else - sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); - - // Treat other globals as GlobalInternal unless they are constants. + QualType Ty = D->getType(); + assert(!Ty.isNull()); + if (Ty.isConstQualified()) { + sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); + } else if (Ctx.getSourceManager().isInSystemHeader(D->getLocation())) { + sReg = getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind); } else { - QualType GQT = D->getType(); - const Type *GT = GQT.getTypePtrOrNull(); - // TODO: We could walk the complex types here and see if everything is - // constified. - if (GT && GQT.isConstQualified() && GT->isArithmeticType()) - sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); - else - sReg = getGlobalsRegion(); + sReg = getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind); } // Finally handle static locals. diff --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp index 8465cc70fbbd9..a6d0e242924b4 100644 --- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -216,7 +216,7 @@ ProgramState::invalidateRegionsImpl(ValueList Values, } ProgramStateRef ProgramState::killBinding(Loc LV) const { - assert(!LV.getAs() && "Use invalidateRegion instead."); + assert(!isa(LV) && "Use invalidateRegion instead."); Store OldStore = getStore(); const StoreRef &newStore = diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp index bf535a8d02057..e788a7a608302 100644 --- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -20,8 +20,8 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableSet.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include @@ -2535,19 +2535,10 @@ EquivalenceClass::removeMember(ProgramStateRef State, const SymbolRef Old) { return State; } -// We must declare reAssume in clang::ento, otherwise we could not declare that -// as a friend in ProgramState. More precisely, the call of reAssume would be -// ambiguous (one in the global namespace and an other which is declared in -// ProgramState is in clang::ento). -namespace clang { -namespace ento { // Re-evaluate an SVal with top-level `State->assume` logic. LLVM_NODISCARD ProgramStateRef reAssume(ProgramStateRef State, const RangeSet *Constraint, SVal TheValue) { - assert(State); - if (State->isPosteriorlyOverconstrained()) - return nullptr; if (!Constraint) return State; @@ -2570,8 +2561,6 @@ LLVM_NODISCARD ProgramStateRef reAssume(ProgramStateRef State, return State->assumeInclusiveRange(DefinedVal, Constraint->getMinValue(), Constraint->getMaxValue(), true); } -} // namespace ento -} // namespace clang // Iterate over all symbols and try to simplify them. Once a symbol is // simplified then we check if we can merge the simplified symbol's equivalence diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 43924cd4b5424..8a50cb27c8d3a 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -317,29 +317,6 @@ RegionBindingsRef RegionBindingsRef::removeBinding(const MemRegion *R, return removeBinding(BindingKey::Make(R, k)); } -//===----------------------------------------------------------------------===// -// Fine-grained control of RegionStoreManager. -//===----------------------------------------------------------------------===// - -namespace { -struct minimal_features_tag {}; -struct maximal_features_tag {}; - -class RegionStoreFeatures { - bool SupportsFields; -public: - RegionStoreFeatures(minimal_features_tag) : - SupportsFields(false) {} - - RegionStoreFeatures(maximal_features_tag) : - SupportsFields(true) {} - - void enableFields(bool t) { SupportsFields = t; } - - bool supportsFields() const { return SupportsFields; } -}; -} - //===----------------------------------------------------------------------===// // Main RegionStore logic. //===----------------------------------------------------------------------===// @@ -349,8 +326,6 @@ class InvalidateRegionsWorker; class RegionStoreManager : public StoreManager { public: - const RegionStoreFeatures Features; - RegionBindings::Factory RBFactory; mutable ClusterBindings::Factory CBFactory; @@ -377,16 +352,14 @@ class RegionStoreManager : public StoreManager { InvalidatedRegions *TopLevelRegions); public: - RegionStoreManager(ProgramStateManager& mgr, const RegionStoreFeatures &f) - : StoreManager(mgr), Features(f), - RBFactory(mgr.getAllocator()), CBFactory(mgr.getAllocator()), - SmallStructLimit(0) { + RegionStoreManager(ProgramStateManager &mgr) + : StoreManager(mgr), RBFactory(mgr.getAllocator()), + CBFactory(mgr.getAllocator()), SmallStructLimit(0) { ExprEngine &Eng = StateMgr.getOwningEngine(); AnalyzerOptions &Options = Eng.getAnalysisManager().options; SmallStructLimit = Options.RegionStoreSmallStructLimit; } - /// setImplicitDefaultValue - Set the default binding for the provided /// MemRegion to the value implicitly defined for compound literals when /// the value is not specified. @@ -674,18 +647,9 @@ class RegionStoreManager : public StoreManager { std::unique_ptr ento::CreateRegionStoreManager(ProgramStateManager &StMgr) { - RegionStoreFeatures F = maximal_features_tag(); - return std::make_unique(StMgr, F); -} - -std::unique_ptr -ento::CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr) { - RegionStoreFeatures F = minimal_features_tag(); - F.enableFields(true); - return std::make_unique(StMgr, F); + return std::make_unique(StMgr); } - //===----------------------------------------------------------------------===// // Region Cluster analysis. //===----------------------------------------------------------------------===// @@ -1397,10 +1361,10 @@ RegionStoreManager::invalidateRegions(Store store, /// the array). This is called by ExprEngine when evaluating casts /// from arrays to pointers. SVal RegionStoreManager::ArrayToPointer(Loc Array, QualType T) { - if (Array.getAs()) + if (isa(Array)) return Array; - if (!Array.getAs()) + if (!isa(Array)) return UnknownVal(); const SubRegion *R = @@ -1414,8 +1378,8 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array, QualType T) { //===----------------------------------------------------------------------===// SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T) { - assert(!L.getAs() && "location unknown"); - assert(!L.getAs() && "location undefined"); + assert(!isa(L) && "location unknown"); + assert(!isa(L) && "location undefined"); // For access to concrete addresses, return UnknownVal. Checks // for null dereferences (and similar errors) are done by checkers, not @@ -2030,8 +1994,7 @@ RegionStoreManager::getBindingForDerivedDefaultValue(RegionBindingsConstRef B, // Lazy bindings are usually handled through getExistingLazyBinding(). // We should unify these two code paths at some point. - if (val.getAs() || - val.getAs()) + if (isa(val)) return val; llvm_unreachable("Unknown default value"); @@ -2450,7 +2413,7 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B, } // Handle lazy compound values. - if (Init.getAs()) + if (isa(Init)) return bindAggregate(B, R, Init); if (Init.isUnknown()) @@ -2495,13 +2458,13 @@ RegionBindingsRef RegionStoreManager::bindVector(RegionBindingsConstRef B, const VectorType *VT = T->castAs(); // Use castAs for typedefs. // Handle lazy compound values and symbolic values. - if (V.getAs() || V.getAs()) + if (isa(V)) return bindAggregate(B, R, V); // We may get non-CompoundVal accidentally due to imprecise cast logic or // that we are binding symbolic struct value. Kill the field values, and if // the value is symbolic go and bind it as a "default" binding. - if (!V.getAs()) { + if (!isa(V)) { return bindAggregate(B, R, UnknownVal()); } @@ -2569,11 +2532,8 @@ RegionStoreManager::tryBindSmallStruct(RegionBindingsConstRef B, } RegionBindingsRef RegionStoreManager::bindStruct(RegionBindingsConstRef B, - const TypedValueRegion* R, + const TypedValueRegion *R, SVal V) { - if (!Features.supportsFields()) - return B; - QualType T = R->getValueType(); assert(T->isStructureOrClassType()); @@ -2590,13 +2550,13 @@ RegionBindingsRef RegionStoreManager::bindStruct(RegionBindingsConstRef B, return *NewB; return bindAggregate(B, R, V); } - if (V.getAs()) + if (isa(V)) return bindAggregate(B, R, V); // We may get non-CompoundVal accidentally due to imprecise cast logic or // that we are binding symbolic struct value. Kill the field values, and if // the value is symbolic go and bind it as a "default" binding. - if (V.isUnknown() || !V.getAs()) + if (V.isUnknown() || !isa(V)) return bindAggregate(B, R, UnknownVal()); // The raw CompoundVal is essentially a symbolic InitListExpr: an (immutable) diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp index ae590a3b73387..13fac37899cd2 100644 --- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -441,6 +441,30 @@ SVal SValBuilder::makeSymExprValNN(BinaryOperator::Opcode Op, return UnknownVal(); } +SVal SValBuilder::evalMinus(NonLoc X) { + switch (X.getSubKind()) { + case nonloc::ConcreteIntKind: + return makeIntVal(-X.castAs().getValue()); + case nonloc::SymbolValKind: + return makeNonLoc(X.castAs().getSymbol(), UO_Minus, + X.getType(Context)); + default: + return UnknownVal(); + } +} + +SVal SValBuilder::evalComplement(NonLoc X) { + switch (X.getSubKind()) { + case nonloc::ConcreteIntKind: + return makeIntVal(~X.castAs().getValue()); + case nonloc::SymbolValKind: + return makeNonLoc(X.castAs().getSymbol(), UO_Not, + X.getType(Context)); + default: + return UnknownVal(); + } +} + SVal SValBuilder::evalUnaryOp(ProgramStateRef state, UnaryOperator::Opcode opc, SVal operand, QualType type) { auto OpN = operand.getAs(); @@ -462,8 +486,7 @@ SVal SValBuilder::evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, if (lhs.isUnknown() || rhs.isUnknown()) return UnknownVal(); - if (lhs.getAs() || - rhs.getAs()) { + if (isa(lhs) || isa(rhs)) { return UnknownVal(); } diff --git a/clang/lib/StaticAnalyzer/Core/SVals.cpp b/clang/lib/StaticAnalyzer/Core/SVals.cpp index 1429d36107e9e..67913a55b3dcc 100644 --- a/clang/lib/StaticAnalyzer/Core/SVals.cpp +++ b/clang/lib/StaticAnalyzer/Core/SVals.cpp @@ -252,20 +252,6 @@ bool SVal::isZeroConstant() const { return isConstant(0); } -//===----------------------------------------------------------------------===// -// Transfer function dispatch for Non-Locs. -//===----------------------------------------------------------------------===// - -nonloc::ConcreteInt -nonloc::ConcreteInt::evalComplement(SValBuilder &svalBuilder) const { - return svalBuilder.makeIntVal(~getValue()); -} - -nonloc::ConcreteInt -nonloc::ConcreteInt::evalMinus(SValBuilder &svalBuilder) const { - return svalBuilder.makeIntVal(-getValue()); -} - //===----------------------------------------------------------------------===// // Pretty-Printing. //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp index e1319a4c2e413..ad31107925929 100644 --- a/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp @@ -97,12 +97,12 @@ static std::string fileNameToURI(StringRef Filename) { assert(Iter != End && "Expected there to be a non-root path component."); // Add the rest of the path components, encoding any reserved characters; // we skip past the first path component, as it was handled it above. - std::for_each(++Iter, End, [&Ret](StringRef Component) { + for (StringRef Component : llvm::make_range(++Iter, End)) { // For reasons unknown to me, we may get a backslash with Windows native // paths for the initial backslash following the drive component, which // we need to ignore as a URI path part. if (Component == "\\") - return; + continue; // Add the separator between the previous path part and the one being // currently processed. @@ -112,7 +112,7 @@ static std::string fileNameToURI(StringRef Filename) { for (char C : Component) { Ret += percentEncodeURICharacter(C); } - }); + } return std::string(Ret); } @@ -341,14 +341,14 @@ static json::Array createRules(std::vector &Diags, json::Array Rules; llvm::StringSet<> Seen; - llvm::for_each(Diags, [&](const PathDiagnostic *D) { + for (const PathDiagnostic *D : Diags) { StringRef RuleID = D->getCheckerName(); std::pair::iterator, bool> P = Seen.insert(RuleID); if (P.second) { RuleMapping[RuleID] = Rules.size(); // Maps RuleID to an Array Index. Rules.push_back(createRule(*D)); } - }); + } return Rules; } @@ -368,10 +368,9 @@ static json::Object createRun(const LangOptions &LO, json::Array Results, Artifacts; StringMap RuleMapping; json::Object Tool = createTool(Diags, RuleMapping); - - llvm::for_each(Diags, [&](const PathDiagnostic *D) { + + for (const PathDiagnostic *D : Diags) Results.push_back(createResult(LO, *D, Artifacts, RuleMapping)); - }); return json::Object{{"tool", std::move(Tool)}, {"results", std::move(Results)}, diff --git a/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp index 7460b51a76975..dcb6043e9df3a 100644 --- a/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp @@ -44,7 +44,7 @@ ProgramStateRef SimpleConstraintManager::assumeInternal(ProgramStateRef State, ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State, NonLoc Cond, bool Assumption) { State = assumeAux(State, Cond, Assumption); - if (NotifyAssumeClients && EE) + if (EE) return EE->processAssume(State, Cond, Assumption); return State; } diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index 1b0c377aedc2c..762ecc18eceaf 100644 --- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -22,6 +22,13 @@ using namespace ento; namespace { class SimpleSValBuilder : public SValBuilder { + // Query the constraint manager whether the SVal has only one possible + // (integer) value. If that is the case, the value is returned. Otherwise, + // returns NULL. + // This is an implementation detail. Checkers should use `getKnownValue()` + // instead. + const llvm::APSInt *getConstValue(ProgramStateRef state, SVal V); + // With one `simplifySValOnce` call, a compound symbols might collapse to // simpler symbol tree that is still possible to further simplify. Thus, we // do the simplification on a new symbol tree until we reach the simplest @@ -45,7 +52,7 @@ class SimpleSValBuilder : public SValBuilder { SVal simplifyUntilFixpoint(ProgramStateRef State, SVal Val); // Recursively descends into symbolic expressions and replaces symbols - // with their known values (in the sense of the getKnownValue() method). + // with their known values (in the sense of the getConstValue() method). // We traverse the symbol tree and query the constraint values for the // sub-trees and if a value is a constant we do the constant folding. SVal simplifySValOnce(ProgramStateRef State, SVal V); @@ -56,8 +63,6 @@ class SimpleSValBuilder : public SValBuilder { : SValBuilder(alloc, context, stateMgr) {} ~SimpleSValBuilder() override {} - SVal evalMinus(NonLoc val) override; - SVal evalComplement(NonLoc val) override; SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy) override; SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op, @@ -65,8 +70,9 @@ class SimpleSValBuilder : public SValBuilder { SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, NonLoc rhs, QualType resultTy) override; - /// getKnownValue - evaluates a given SVal. If the SVal has only one possible - /// (integer) value, that value is returned. Otherwise, returns NULL. + /// Evaluates a given SVal by recursively evaluating and + /// simplifying the children SVals. If the SVal has only one possible + /// (integer) value, that value is returned. Otherwise, returns NULL. const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal V) override; SVal simplifySVal(ProgramStateRef State, SVal V) override; @@ -82,34 +88,6 @@ SValBuilder *ento::createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc, return new SimpleSValBuilder(alloc, context, stateMgr); } -//===----------------------------------------------------------------------===// -// Transfer function for unary operators. -//===----------------------------------------------------------------------===// - -SVal SimpleSValBuilder::evalMinus(NonLoc val) { - switch (val.getSubKind()) { - case nonloc::ConcreteIntKind: - return val.castAs().evalMinus(*this); - case nonloc::SymbolValKind: - return makeNonLoc(val.castAs().getSymbol(), UO_Minus, - val.getType(Context)); - default: - return UnknownVal(); - } -} - -SVal SimpleSValBuilder::evalComplement(NonLoc X) { - switch (X.getSubKind()) { - case nonloc::ConcreteIntKind: - return X.castAs().evalComplement(*this); - case nonloc::SymbolValKind: - return makeNonLoc(X.castAs().getSymbol(), UO_Not, - X.getType(Context)); - default: - return UnknownVal(); - } -} - // Checks if the negation the value and flipping sign preserve // the semantics on the operation in the resultType static bool isNegationValuePreserving(const llvm::APSInt &Value, @@ -320,7 +298,6 @@ static NonLoc doRearrangeUnchecked(ProgramStateRef State, else llvm_unreachable("Operation not suitable for unchecked rearrangement!"); - // FIXME: Can we use assume() without getting into an infinite recursion? if (LSym == RSym) return SVB.evalBinOpNN(State, Op, nonloc::ConcreteInt(LInt), nonloc::ConcreteInt(RInt), ResultTy) @@ -533,7 +510,7 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state, llvm::APSInt LHSValue = lhs.castAs().getValue(); // If we're dealing with two known constants, just perform the operation. - if (const llvm::APSInt *KnownRHSValue = getKnownValue(state, rhs)) { + if (const llvm::APSInt *KnownRHSValue = getConstValue(state, rhs)) { llvm::APSInt RHSValue = *KnownRHSValue; if (BinaryOperator::isComparisonOp(op)) { // We're looking for a type big enough to compare the two values. @@ -653,7 +630,7 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state, } // For now, only handle expressions whose RHS is a constant. - if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs)) { + if (const llvm::APSInt *RHSValue = getConstValue(state, rhs)) { // If both the LHS and the current expression are additive, // fold their constants and try again. if (BinaryOperator::isAdditiveOp(op)) { @@ -700,7 +677,7 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state, } // Is the RHS a constant? - if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs)) + if (const llvm::APSInt *RHSValue = getConstValue(state, rhs)) return MakeSymIntVal(Sym, op, *RHSValue, resultTy); if (Optional V = tryRearrange(state, op, lhs, rhs, resultTy)) @@ -879,7 +856,7 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state, // This must come after the test if the RHS is a symbol, which is used to // build constraints. The address of any non-symbolic region is guaranteed // to be non-NULL, as is any label. - assert(rhs.getAs() || rhs.getAs()); + assert((isa(rhs))); if (lhs.isZeroConstant()) { switch (op) { default: @@ -1188,9 +1165,8 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state, return UnknownVal(); } -const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state, - SVal V) { - V = simplifySVal(state, V); +const llvm::APSInt *SimpleSValBuilder::getConstValue(ProgramStateRef state, + SVal V) { if (V.isUnknownOrUndef()) return nullptr; @@ -1206,6 +1182,11 @@ const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state, return nullptr; } +const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state, + SVal V) { + return getConstValue(state, simplifySVal(state, V)); +} + SVal SimpleSValBuilder::simplifyUntilFixpoint(ProgramStateRef State, SVal Val) { SVal SimplifiedVal = simplifySValOnce(State, Val); while (SimplifiedVal != Val) { @@ -1272,14 +1253,12 @@ SVal SimpleSValBuilder::simplifySValOnce(ProgramStateRef State, SVal V) { SVal VisitSymbolData(const SymbolData *S) { // No cache here. if (const llvm::APSInt *I = - SVB.getKnownValue(State, SVB.makeSymbolVal(S))) + State->getConstraintManager().getSymVal(State, S)) return Loc::isLocType(S->getType()) ? (SVal)SVB.makeIntLocVal(*I) : (SVal)SVB.makeIntVal(*I); return SVB.makeSymbolVal(S); } - // TODO: Support SymbolCast. - SVal VisitSymIntExpr(const SymIntExpr *S) { auto I = Cached.find(S); if (I != Cached.end()) @@ -1349,7 +1328,17 @@ SVal SimpleSValBuilder::simplifySValOnce(ProgramStateRef State, SVal V) { S, SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType())); } - // FIXME add VisitSymbolCast + SVal VisitSymbolCast(const SymbolCast *S) { + auto I = Cached.find(S); + if (I != Cached.end()) + return I->second; + const SymExpr *OpSym = S->getOperand(); + SVal OpVal = getConstOrVisit(OpSym); + if (isUnchanged(OpSym, OpVal)) + return skip(S); + + return cache(S, SVB.evalCast(OpVal, S->getType(), OpSym->getType())); + } SVal VisitUnarySymExpr(const UnarySymExpr *S) { auto I = Cached.find(S); @@ -1376,14 +1365,6 @@ SVal SimpleSValBuilder::simplifySValOnce(ProgramStateRef State, SVal V) { SVal VisitSVal(SVal V) { return V; } }; - // A crude way of preventing this function from calling itself from evalBinOp. - static bool isReentering = false; - if (isReentering) - return V; - - isReentering = true; SVal SimplifiedV = Simplifier(State).Visit(V); - isReentering = false; - return SimplifiedV; } diff --git a/clang/lib/StaticAnalyzer/Core/Store.cpp b/clang/lib/StaticAnalyzer/Core/Store.cpp index 2bcdb0faf5da9..96e8878da616c 100644 --- a/clang/lib/StaticAnalyzer/Core/Store.cpp +++ b/clang/lib/StaticAnalyzer/Core/Store.cpp @@ -459,10 +459,10 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, // FIXME: For absolute pointer addresses, we just return that value back as // well, although in reality we should return the offset added to that // value. See also the similar FIXME in getLValueFieldOrIvar(). - if (Base.isUnknownOrUndef() || Base.getAs()) + if (Base.isUnknownOrUndef() || isa(Base)) return Base; - if (Base.getAs()) + if (isa(Base)) return UnknownVal(); const SubRegion *BaseRegion = @@ -488,7 +488,7 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, SVal BaseIdx = ElemR->getIndex(); - if (!BaseIdx.getAs()) + if (!isa(BaseIdx)) return UnknownVal(); const llvm::APSInt &BaseIdxI = @@ -497,7 +497,7 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, // Only allow non-integer offsets if the base region has no offset itself. // FIXME: This is a somewhat arbitrary restriction. We should be using // SValBuilder here to add the two offsets without checking their types. - if (!Offset.getAs()) { + if (!isa(Offset)) { if (isa(BaseRegion->StripCasts())) return UnknownVal(); diff --git a/clang/lib/StaticAnalyzer/Core/WorkList.cpp b/clang/lib/StaticAnalyzer/Core/WorkList.cpp index 348552ba73a9b..7042a9020837a 100644 --- a/clang/lib/StaticAnalyzer/Core/WorkList.cpp +++ b/clang/lib/StaticAnalyzer/Core/WorkList.cpp @@ -205,12 +205,6 @@ class UnexploredFirstPriorityQueue : public WorkList { using QueuePriority = std::pair; using QueueItem = std::pair; - struct ExplorationComparator { - bool operator() (const QueueItem &LHS, const QueueItem &RHS) { - return LHS.second < RHS.second; - } - }; - // Number of inserted nodes, used to emulate DFS ordering in the priority // queue when insertions are equal. unsigned long Counter = 0; @@ -219,7 +213,7 @@ class UnexploredFirstPriorityQueue : public WorkList { VisitedTimesMap NumReached; // The top item is the largest one. - llvm::PriorityQueue, ExplorationComparator> + llvm::PriorityQueue, llvm::less_second> queue; public: @@ -267,12 +261,6 @@ class UnexploredFirstPriorityLocationQueue : public WorkList { using QueuePriority = std::pair; using QueueItem = std::pair; - struct ExplorationComparator { - bool operator() (const QueueItem &LHS, const QueueItem &RHS) { - return LHS.second < RHS.second; - } - }; - // Number of inserted nodes, used to emulate DFS ordering in the priority // queue when insertions are equal. unsigned long Counter = 0; @@ -281,7 +269,7 @@ class UnexploredFirstPriorityLocationQueue : public WorkList { VisitedTimesMap NumReached; // The top item is the largest one. - llvm::PriorityQueue, ExplorationComparator> + llvm::PriorityQueue, llvm::less_second> queue; public: diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index ad438f6988ffc..ca0a66f54cedc 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -171,13 +171,7 @@ class AnalysisConsumer : public AnalysisASTConsumer, } // Create the analyzer component creators. - switch (Opts->AnalysisStoreOpt) { - default: - llvm_unreachable("Unknown store manager."); -#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \ - case NAME##Model: CreateStoreMgr = CREATEFN; break; -#include "clang/StaticAnalyzer/Core/Analyses.def" - } + CreateStoreMgr = &CreateRegionStoreManager; switch (Opts->AnalysisConstraintsOpt) { default: @@ -358,7 +352,6 @@ class AnalysisConsumer : public AnalysisASTConsumer, private: void storeTopLevelDecls(DeclGroupRef DG); - std::string getFunctionName(const Decl *D); /// Check if we should skip (not analyze) the given function. AnalysisMode getModeForDecl(Decl *D, AnalysisMode Mode); diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp index eb6014a0629df..7cd15f0f65954 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp @@ -101,10 +101,7 @@ USAGE: -analyzer-config #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE }; - llvm::sort(PrintableOptions, [](const OptionAndDescriptionTy &LHS, - const OptionAndDescriptionTy &RHS) { - return LHS.first < RHS.first; - }); + llvm::sort(PrintableOptions, llvm::less_first()); for (const auto &Pair : PrintableOptions) { AnalyzerOptions::printFormattedEntry(out, Pair, /*InitialPad*/ 2, diff --git a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp index 528284ca89858..9ee6ef4f9519f 100644 --- a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp @@ -480,9 +480,7 @@ static void isOptionContainedIn(const CmdLineOptionList &OptionList, return Opt.OptionName == SuppliedOption; }; - const auto *OptionIt = llvm::find_if(OptionList, SameOptName); - - if (OptionIt == OptionList.end()) { + if (llvm::none_of(OptionList, SameOptName)) { Diags.Report(diag::err_analyzer_checker_option_unknown) << SuppliedChecker << SuppliedOption; return; diff --git a/clang/lib/Support/RISCVVIntrinsicUtils.cpp b/clang/lib/Support/RISCVVIntrinsicUtils.cpp index 92d29043f2cc0..afcd03c41f97f 100644 --- a/clang/lib/Support/RISCVVIntrinsicUtils.cpp +++ b/clang/lib/Support/RISCVVIntrinsicUtils.cpp @@ -791,13 +791,13 @@ void RVVType::applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type) { Optional RVVType::computeTypes(BasicType BT, int Log2LMUL, unsigned NF, - ArrayRef PrototypeSeq) { + ArrayRef Prototype) { // LMUL x NF must be less than or equal to 8. if ((Log2LMUL >= 1) && (1 << Log2LMUL) * NF > 8) return llvm::None; RVVTypes Types; - for (const PrototypeDescriptor &Proto : PrototypeSeq) { + for (const PrototypeDescriptor &Proto : Prototype) { auto T = computeType(BT, Log2LMUL, Proto); if (!T.hasValue()) return llvm::None; @@ -847,8 +847,8 @@ Optional RVVType::computeType(BasicType BT, int Log2LMUL, // RVVIntrinsic implementation //===----------------------------------------------------------------------===// RVVIntrinsic::RVVIntrinsic( - StringRef NewName, StringRef Suffix, StringRef NewMangledName, - StringRef MangledSuffix, StringRef IRName, bool IsMasked, + StringRef NewName, StringRef Suffix, StringRef NewOverloadedName, + StringRef OverloadedSuffix, StringRef IRName, bool IsMasked, bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme, bool HasUnMaskedOverloaded, bool HasBuiltinAlias, StringRef ManualCodegen, const RVVTypes &OutInTypes, const std::vector &NewIntrinsicTypes, @@ -858,17 +858,17 @@ RVVIntrinsic::RVVIntrinsic( HasBuiltinAlias(HasBuiltinAlias), ManualCodegen(ManualCodegen.str()), NF(NF) { - // Init BuiltinName, Name and MangledName + // Init BuiltinName, Name and OverloadedName BuiltinName = NewName.str(); Name = BuiltinName; - if (NewMangledName.empty()) - MangledName = NewName.split("_").first.str(); + if (NewOverloadedName.empty()) + OverloadedName = NewName.split("_").first.str(); else - MangledName = NewMangledName.str(); + OverloadedName = NewOverloadedName.str(); if (!Suffix.empty()) Name += "_" + Suffix.str(); - if (!MangledSuffix.empty()) - MangledName += "_" + MangledSuffix.str(); + if (!OverloadedSuffix.empty()) + OverloadedName += "_" + OverloadedSuffix.str(); if (IsMasked) { BuiltinName += "_m"; Name += "_m"; diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp index 6fd3a83fd3f7b..5041a8eb6e597 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp @@ -176,7 +176,7 @@ DependencyScanningTool::getFullDependencies( private: std::vector Dependencies; std::vector PrebuiltModuleDeps; - std::map ClangModuleDeps; + llvm::MapVector> ClangModuleDeps; std::string ContextHash; std::vector OutputPaths; const llvm::StringSet<> &AlreadySeen; diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 04f7044bc4236..16e6ac59e85fe 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -137,11 +137,11 @@ class DependencyScanningAction : public tooling::ToolAction { DependencyScanningAction( StringRef WorkingDirectory, DependencyConsumer &Consumer, llvm::IntrusiveRefCntPtr DepFS, - ScanningOutputFormat Format, bool OptimizeArgs, + ScanningOutputFormat Format, bool OptimizeArgs, bool DisableFree, llvm::Optional ModuleName = None) : WorkingDirectory(WorkingDirectory), Consumer(Consumer), DepFS(std::move(DepFS)), Format(Format), OptimizeArgs(OptimizeArgs), - ModuleName(ModuleName) {} + DisableFree(DisableFree), ModuleName(ModuleName) {} bool runInvocation(std::shared_ptr Invocation, FileManager *FileMgr, @@ -149,6 +149,8 @@ class DependencyScanningAction : public tooling::ToolAction { DiagnosticConsumer *DiagConsumer) override { // Make a deep copy of the original Clang invocation. CompilerInvocation OriginalInvocation(*Invocation); + // Restore the value of DisableFree, which may be modified by Tooling. + OriginalInvocation.getFrontendOpts().DisableFree = DisableFree; // Create a compiler instance to handle the actual work. CompilerInstance ScanInstance(std::move(PCHContainerOps)); @@ -255,6 +257,7 @@ class DependencyScanningAction : public tooling::ToolAction { llvm::IntrusiveRefCntPtr DepFS; ScanningOutputFormat Format; bool OptimizeArgs; + bool DisableFree; llvm::Optional ModuleName; }; @@ -329,9 +332,13 @@ llvm::Error DependencyScanningWorker::computeDependencies( return runWithDiags(CreateAndPopulateDiagOpts(FinalCCommandLine).release(), [&](DiagnosticConsumer &DC, DiagnosticOptions &DiagOpts) { + // DisableFree is modified by Tooling for running + // in-process; preserve the original value, which is + // always true for a driver invocation. + bool DisableFree = true; DependencyScanningAction Action( WorkingDirectory, Consumer, DepFS, Format, - OptimizeArgs, ModuleName); + OptimizeArgs, DisableFree, ModuleName); // Create an invocation that uses the underlying file // system to ensure that any file system requests that // are made by the driver do not go through the diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index 21a422f8dbbae..6c7fdbc3944a6 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -199,7 +199,7 @@ void ModuleDepCollectorPP::EndOfMainFile() { MDC.Consumer.handleDependencyOutputOpts(*MDC.Opts); for (auto &&I : MDC.ModularDeps) - MDC.Consumer.handleModuleDependency(I.second); + MDC.Consumer.handleModuleDependency(*I.second); for (auto &&I : MDC.FileDeps) MDC.Consumer.handleFileDependency(I); @@ -212,11 +212,12 @@ ModuleID ModuleDepCollectorPP::handleTopLevelModule(const Module *M) { assert(M == M->getTopLevelModule() && "Expected top level module!"); // If this module has been handled already, just return its ID. - auto ModI = MDC.ModularDeps.insert({M, ModuleDeps{}}); + auto ModI = MDC.ModularDeps.insert({M, nullptr}); if (!ModI.second) - return ModI.first->second.ID; + return ModI.first->second->ID; - ModuleDeps &MD = ModI.first->second; + ModI.first->second = std::make_unique(); + ModuleDeps &MD = *ModI.first->second; MD.ID.ModuleName = M->getFullModuleName(); MD.ImportedByMainFile = DirectModularDeps.contains(M); diff --git a/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp b/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp index a69b76a3c9712..de11263efd5aa 100644 --- a/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp +++ b/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp @@ -145,14 +145,12 @@ class AdditionalUSRFinder : public RecursiveASTVisitor { void handleVarTemplateDecl(const VarTemplateDecl *VTD) { USRSet.insert(getUSRForDecl(VTD)); USRSet.insert(getUSRForDecl(VTD->getTemplatedDecl())); - llvm::for_each(VTD->specializations(), [&](const auto *Spec) { + for (const auto *Spec : VTD->specializations()) USRSet.insert(getUSRForDecl(Spec)); - }); SmallVector PartialSpecs; VTD->getPartialSpecializations(PartialSpecs); - llvm::for_each(PartialSpecs, [&](const auto *Spec) { + for (const auto *Spec : PartialSpecs) USRSet.insert(getUSRForDecl(Spec)); - }); } void addUSRsOfCtorDtors(const CXXRecordDecl *RD) { diff --git a/clang/test/AST/ast-dump-template-decls.cpp b/clang/test/AST/ast-dump-template-decls.cpp index 51ec673ab8f3a..616a96902eff4 100644 --- a/clang/test/AST/ast-dump-template-decls.cpp +++ b/clang/test/AST/ast-dump-template-decls.cpp @@ -108,3 +108,22 @@ template // CHECK: FunctionTemplateDecl 0x{{[^ ]*}} parent 0x{{[^ ]*}} prev 0x{{[^ ]*}} col:13 f // CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} col:20 typename depth 1 index 0 Uy void V::f() {} + +namespace PR55886 { +template struct C { + template using type1 = U(T); +}; +using type2 = typename C::type1; +// CHECK: TypeAliasDecl 0x{{[^ ]*}} col:7 type2 'typename C::type1':'void (int)' +// CHECK-NEXT: ElaboratedType 0x{{[^ ]*}} 'typename C::type1' sugar +// CHECK-NEXT: TemplateSpecializationType 0x{{[^ ]*}} 'type1' sugar alias type1 +// CHECK-NEXT: TemplateArgument type 'void' +// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void' +// CHECK-NEXT: FunctionProtoType 0x{{[^ ]*}} 'void (int)' cdecl +// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'void' sugar +// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'U' dependent depth 0 index 0 +// CHECK-NEXT: TemplateTypeParm 0x{{[^ ]*}} 'U' +// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void' +// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar +// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'T' dependent depth 0 index 0 +} // namespace PR55886 diff --git a/clang/test/AST/attr-annotate-type.c b/clang/test/AST/attr-annotate-type.c new file mode 100644 index 0000000000000..115fd5912d75b --- /dev/null +++ b/clang/test/AST/attr-annotate-type.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 %s -ast-dump -fdouble-square-bracket-attributes | FileCheck %s + +// Verify that we print the [[clang::annotate_type]] attribute. +// FIXME: The arguments are currently not printed -- see also comments in +// TypePrinter.cpp. + +// Need to escape the `[[` as a regex to avoid it being interpreted as a +// substitution block. +// CHECK: VarDecl {{.*}} x1 'int {{\[\[}}clang::annotate_type(...){{]]}}':'int' +int [[clang::annotate_type("bar")]] x1; +// CHECK: VarDecl {{.*}} x2 'int * {{\[\[}}clang::annotate_type(...){{]]}}':'int *' +int *[[clang::annotate_type("bar")]] x2; diff --git a/clang/test/AST/language_address_space_attribute.cpp b/clang/test/AST/language_address_space_attribute.cpp index 93a23304d9a63..fcc293ab5e705 100644 --- a/clang/test/AST/language_address_space_attribute.cpp +++ b/clang/test/AST/language_address_space_attribute.cpp @@ -14,42 +14,63 @@ void langas() { // CHECK: VarDecl {{.*}} x_global '__global int *' __attribute__((opencl_global)) int *x_global; + // CHECK: VarDecl {{.*}} y_global '__global int *' + int [[clang::opencl_global]] *y_global; + // CHECK: VarDecl {{.*}} z_global '__global int *' [[clang::opencl_global]] int *z_global; // CHECK: VarDecl {{.*}} x_global_device '__global_device int *' __attribute__((opencl_global_device)) int *x_global_device; + // CHECK: VarDecl {{.*}} y_global_device '__global_device int *' + int [[clang::opencl_global_device]] *y_global_device; + // CHECK: VarDecl {{.*}} z_global_device '__global_device int *' [[clang::opencl_global_device]] int *z_global_device; // CHECK: VarDecl {{.*}} x_global_host '__global_host int *' __attribute__((opencl_global_host)) int *x_global_host; + // CHECK: VarDecl {{.*}} y_global_host '__global_host int *' + int [[clang::opencl_global_host]] *y_global_host; + // CHECK: VarDecl {{.*}} z_global_host '__global_host int *' [[clang::opencl_global_host]] int *z_global_host; // CHECK: VarDecl {{.*}} x_local '__local int *' __attribute__((opencl_local)) int *x_local; + // CHECK: VarDecl {{.*}} y_local '__local int *' + int [[clang::opencl_local]] *y_local; + // CHECK: VarDecl {{.*}} z_local '__local int *' [[clang::opencl_local]] int *z_local; // CHECK: VarDecl {{.*}} x_constant '__constant int *' __attribute__((opencl_constant)) int *x_constant; + // CHECK: VarDecl {{.*}} y_constant '__constant int *' + int [[clang::opencl_constant]] *y_constant; + // CHECK: VarDecl {{.*}} z_constant '__constant int *' [[clang::opencl_constant]] int *z_constant; // CHECK: VarDecl {{.*}} x_private '__private int *' __attribute__((opencl_private)) int *x_private; + // CHECK: VarDecl {{.*}} y_private '__private int *' + int [[clang::opencl_private]] *y_private; + // CHECK: VarDecl {{.*}} z_private '__private int *' [[clang::opencl_private]] int *z_private; // CHECK: VarDecl {{.*}} x_generic '__generic int *' __attribute__((opencl_generic)) int *x_generic; + // CHECK: VarDecl {{.*}} y_generic '__generic int *' + int [[clang::opencl_generic]] *y_generic; + // CHECK: VarDecl {{.*}} z_generic '__generic int *' [[clang::opencl_generic]] int *z_generic; } diff --git a/clang/test/Analysis/CFNumber.c b/clang/test/Analysis/CFNumber.c index 7ac65cc1d2b21..8c1b229f36e26 100644 --- a/clang/test/Analysis/CFNumber.c +++ b/clang/test/Analysis/CFNumber.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.coreFoundation.CFNumber,osx.cocoa.RetainCount -analyzer-store=region -verify -triple x86_64-apple-darwin9 %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.coreFoundation.CFNumber,osx.cocoa.RetainCount -verify -triple x86_64-apple-darwin9 %s typedef signed long CFIndex; typedef const struct __CFAllocator * CFAllocatorRef; diff --git a/clang/test/Analysis/CFRetainRelease_NSAssertionHandler.m b/clang/test/Analysis/CFRetainRelease_NSAssertionHandler.m index f358ee64ceb4c..2237b567c9b6c 100644 --- a/clang/test/Analysis/CFRetainRelease_NSAssertionHandler.m +++ b/clang/test/Analysis/CFRetainRelease_NSAssertionHandler.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -verify %s -analyzer-store=region +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -verify %s // expected-no-diagnostics typedef struct objc_selector *SEL; diff --git a/clang/test/Analysis/CGColorSpace.c b/clang/test/Analysis/CGColorSpace.c index 3faf21ae120d5..d8fa535ba58db 100644 --- a/clang/test/Analysis/CGColorSpace.c +++ b/clang/test/Analysis/CGColorSpace.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -verify %s typedef struct CGColorSpace *CGColorSpaceRef; extern CGColorSpaceRef CGColorSpaceCreateDeviceRGB(void); diff --git a/clang/test/Analysis/Inputs/some_system_globals.h b/clang/test/Analysis/Inputs/some_system_globals.h new file mode 100644 index 0000000000000..81d5ead82e074 --- /dev/null +++ b/clang/test/Analysis/Inputs/some_system_globals.h @@ -0,0 +1,4 @@ +#pragma clang system_header + +extern const int my_const_system_global; +extern int my_mutable_system_global; diff --git a/clang/test/Analysis/Inputs/some_user_globals.h b/clang/test/Analysis/Inputs/some_user_globals.h new file mode 100644 index 0000000000000..a63138a1a9d48 --- /dev/null +++ b/clang/test/Analysis/Inputs/some_user_globals.h @@ -0,0 +1,2 @@ +extern const int my_const_user_global; +extern int my_mutable_user_global; diff --git a/clang/test/Analysis/Malloc+MismatchedDeallocator_intersections.cpp b/clang/test/Analysis/Malloc+MismatchedDeallocator_intersections.cpp index 88435b866acd7..b0cef2591486d 100644 --- a/clang/test/Analysis/Malloc+MismatchedDeallocator_intersections.cpp +++ b/clang/test/Analysis/Malloc+MismatchedDeallocator_intersections.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator -analyzer-store region -std=c++11 -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator -std=c++11 -verify %s // expected-no-diagnostics typedef __typeof(sizeof(int)) size_t; diff --git a/clang/test/Analysis/NSPanel.m b/clang/test/Analysis/NSPanel.m index e65b0715a15f2..95fbf56d218e8 100644 --- a/clang/test/Analysis/NSPanel.m +++ b/clang/test/Analysis/NSPanel.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -verify -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -verify -Wno-objc-root-class %s // expected-no-diagnostics // BEGIN delta-debugging reduced header stuff diff --git a/clang/test/Analysis/NSString.m b/clang/test/Analysis/NSString.m index 59e333aea32df..0a00c2a0d8ecc 100644 --- a/clang/test/Analysis/NSString.m +++ b/clang/test/Analysis/NSString.m @@ -1,7 +1,7 @@ -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -verify -Wno-objc-root-class %s -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -analyzer-config mode=shallow -verify -Wno-objc-root-class %s -// RUN: %clang_analyze_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -verify -Wno-objc-root-class %s -// RUN: %clang_analyze_cc1 -DOSATOMIC_USE_INLINED -triple i386-apple-darwin10 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -verify -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -verify -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-config mode=shallow -verify -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -verify -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -DOSATOMIC_USE_INLINED -triple i386-apple-darwin10 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -verify -Wno-objc-root-class %s //===----------------------------------------------------------------------===// // The following code is reduced using delta-debugging from diff --git a/clang/test/Analysis/NSWindow.m b/clang/test/Analysis/NSWindow.m index aa36227f94d22..a656fbc4dbd6d 100644 --- a/clang/test/Analysis/NSWindow.m +++ b/clang/test/Analysis/NSWindow.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core,deadcode.DeadStores -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core,deadcode.DeadStores -verify %s // These declarations were reduced using Delta-Debugging from Foundation.h // on Mac OS X. The test cases are below. diff --git a/clang/test/Analysis/OSAtomic_mac.cpp b/clang/test/Analysis/OSAtomic_mac.cpp index e45f236b2f033..b7c07d4ef6861 100644 --- a/clang/test/Analysis/OSAtomic_mac.cpp +++ b/clang/test/Analysis/OSAtomic_mac.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,osx -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,osx -verify -fblocks %s // expected-no-diagnostics // Test handling of OSAtomicCompareAndSwap when C++ inserts "no-op" casts and we diff --git a/clang/test/Analysis/PR3991.m b/clang/test/Analysis/PR3991.m index 5d76443a0fbba..5f17d19bff8ea 100644 --- a/clang/test/Analysis/PR3991.m +++ b/clang/test/Analysis/PR3991.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-store=region -verify -triple x86_64-apple-darwin9 -Wno-incomplete-implementation %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -verify -triple x86_64-apple-darwin9 -Wno-incomplete-implementation %s // expected-no-diagnostics //===----------------------------------------------------------------------===// diff --git a/clang/test/Analysis/PR7218.c b/clang/test/Analysis/PR7218.c index 10a75c98e5156..7b43d8ee0afe6 100644 --- a/clang/test/Analysis/PR7218.c +++ b/clang/test/Analysis/PR7218.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s char PR7218(char a) { char buf[2]; buf[0] = a; diff --git a/clang/test/Analysis/analyzeOneFunction.m b/clang/test/Analysis/analyzeOneFunction.m index 80f34ad525e29..03665adc697f7 100644 --- a/clang/test/Analysis/analyzeOneFunction.m +++ b/clang/test/Analysis/analyzeOneFunction.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyze-function="-[Test1 myMethodWithY:withX:]" -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyze-function="-[Test1 myMethodWithY:withX:]" -analyzer-checker=core,osx.cocoa.RetainCount -verify %s typedef signed char BOOL; typedef unsigned int NSUInteger; diff --git a/clang/test/Analysis/analyzer-stats.c b/clang/test/Analysis/analyzer-stats.c index 69c61e17eb1f9..7e2e9164ff35d 100644 --- a/clang/test/Analysis/analyzer-stats.c +++ b/clang/test/Analysis/analyzer-stats.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,deadcode.DeadStores,debug.Stats -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks -analyzer-max-loop 4 %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,deadcode.DeadStores,debug.Stats -verify -Wno-unreachable-code -analyzer-max-loop 4 %s int foo(void); diff --git a/clang/test/Analysis/array-struct.c b/clang/test/Analysis/array-struct.c index a609f9abfa3ed..f0eba86fe71bf 100644 --- a/clang/test/Analysis/array-struct.c +++ b/clang/test/Analysis/array-struct.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.CastToStruct -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.CastToStruct -verify %s struct s { int data; diff --git a/clang/test/Analysis/blocks.m b/clang/test/Analysis/blocks.m index 9b2170718ab57..be3964f2f6ef5 100644 --- a/clang/test/Analysis/blocks.m +++ b/clang/test/Analysis/blocks.m @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core -analyzer-store=region -fblocks -analyzer-opt-analyze-nested-blocks -verify -Wno-strict-prototypes %s -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core -analyzer-store=region -fblocks -analyzer-opt-analyze-nested-blocks -verify -x objective-c++ %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core -fblocks -verify -Wno-strict-prototypes %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core -fblocks -verify -x objective-c++ %s //===----------------------------------------------------------------------===// // The following code is reduced using delta-debugging from Mac OS X headers: diff --git a/clang/test/Analysis/blocks.mm b/clang/test/Analysis/blocks.mm index 97c531e0c5dce..033be376d552c 100644 --- a/clang/test/Analysis/blocks.mm +++ b/clang/test/Analysis/blocks.mm @@ -1,7 +1,7 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core -fblocks -analyzer-opt-analyze-nested-blocks -verify -x objective-c++ %s -// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,debug.DumpCFG -fblocks -analyzer-opt-analyze-nested-blocks -analyzer-config cfg-rich-constructors=false %s > %t 2>&1 +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core -fblocks -verify -x objective-c++ %s +// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,debug.DumpCFG -fblocks -analyzer-config cfg-rich-constructors=false %s > %t 2>&1 // RUN: FileCheck --input-file=%t -check-prefixes=CHECK,WARNINGS %s -// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,debug.DumpCFG -fblocks -analyzer-opt-analyze-nested-blocks -analyzer-config cfg-rich-constructors=true %s > %t 2>&1 +// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,debug.DumpCFG -fblocks -analyzer-config cfg-rich-constructors=true %s > %t 2>&1 // RUN: FileCheck --input-file=%t -check-prefixes=CHECK,ANALYZER %s // This file tests how we construct two different flavors of the Clang CFG - diff --git a/clang/test/Analysis/bool-assignment.c b/clang/test/Analysis/bool-assignment.c index 812710786d94f..c32bc8f9e8b14 100644 --- a/clang/test/Analysis/bool-assignment.c +++ b/clang/test/Analysis/bool-assignment.c @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.BoolAssignment,alpha.security.taint -analyzer-store=region -verify -std=c99 -Dbool=_Bool %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.BoolAssignment,alpha.security.taint -analyzer-store=region -verify -x c++ %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.BoolAssignment,alpha.security.taint -verify -std=c99 -Dbool=_Bool %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.BoolAssignment,alpha.security.taint -verify -x c++ %s // Test C++'s bool and C's _Bool. // FIXME: We stopped warning on these when SValBuilder got smarter about diff --git a/clang/test/Analysis/bstring.cpp b/clang/test/Analysis/bstring.cpp index ef03aafbbb815..1b6397c3455eb 100644 --- a/clang/test/Analysis/bstring.cpp +++ b/clang/test/Analysis/bstring.cpp @@ -1,8 +1,8 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -DSUPPRESS_OUT_OF_BOUND -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring.BufferOverlap,alpha.unix.cstring.NotNullTerminated,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,unix.Malloc,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,unix.Malloc,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -DSUPPRESS_OUT_OF_BOUND -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring.BufferOverlap,alpha.unix.cstring.NotNullTerminated,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s #include "Inputs/system-header-simulator-cxx.h" #include "Inputs/system-header-simulator-for-malloc.h" diff --git a/clang/test/Analysis/cast-value-notes.cpp b/clang/test/Analysis/cast-value-notes.cpp index ddfaf07b2a0af..b3d32552e6ec8 100644 --- a/clang/test/Analysis/cast-value-notes.cpp +++ b/clang/test/Analysis/cast-value-notes.cpp @@ -73,7 +73,7 @@ void clang_analyzer_printState(); #if defined(X86) void evalReferences(const Shape &S) { const auto &C = dyn_cast(S); - // expected-note@-1 {{Assuming 'S' is not a 'Circle'}} + // expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle &'}} // expected-note@-2 {{Dereference of null pointer}} // expected-warning@-3 {{Dereference of null pointer}} clang_analyzer_printState(); @@ -93,7 +93,7 @@ void evalReferences_addrspace(const Shape &S) { #if defined(NOT_SUPPRESSED) void evalReferences_addrspace(const Shape &S) { const auto &C = dyn_cast(S); - // expected-note@-1 {{Assuming 'S' is not a 'Circle'}} + // expected-note@-1 {{Assuming 'S' is not a 'const __attribute__((address_space(3))) class clang::Circle &'}} // expected-note@-2 {{Dereference of null pointer}} // expected-warning@-3 {{Dereference of null pointer}} clang_analyzer_printState(); @@ -105,7 +105,7 @@ void evalReferences_addrspace(const Shape &S) { #elif defined(MIPS) void evalReferences(const Shape &S) { const auto &C = dyn_cast(S); - // expected-note@-1 {{Assuming 'S' is not a 'Circle'}} + // expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle &'}} // expected-note@-2 {{Dereference of null pointer}} // expected-warning@-3 {{Dereference of null pointer}} } @@ -122,25 +122,25 @@ void evalNonNullParamNonNullReturnReference(const Shape &S) { // expected-note@-1 {{'C' initialized here}} if (!dyn_cast_or_null(C)) { - // expected-note@-1 {{'C' is a 'Circle'}} + // expected-note@-1 {{Assuming 'C' is a 'const class clang::Circle *'}} // expected-note@-2 {{Taking false branch}} return; } if (dyn_cast_or_null(C)) { - // expected-note@-1 {{Assuming 'C' is not a 'Triangle'}} + // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Triangle *'}} // expected-note@-2 {{Taking false branch}} return; } if (dyn_cast_or_null(C)) { - // expected-note@-1 {{Assuming 'C' is not a 'Rectangle'}} + // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Rectangle *'}} // expected-note@-2 {{Taking false branch}} return; } if (dyn_cast_or_null(C)) { - // expected-note@-1 {{Assuming 'C' is not a 'Hexagon'}} + // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Hexagon *'}} // expected-note@-2 {{Taking false branch}} return; } @@ -176,29 +176,29 @@ void evalNonNullParamNonNullReturnReference(const Shape &S) { void evalNonNullParamNonNullReturn(const Shape *S) { const auto *C = cast(S); - // expected-note@-1 {{'S' is a 'Circle'}} + // expected-note@-1 {{'S' is a 'const class clang::Circle *'}} // expected-note@-2 {{'C' initialized here}} if (!dyn_cast_or_null(C)) { - // expected-note@-1 {{'C' is a 'Circle'}} + // expected-note@-1 {{Assuming 'C' is a 'const class clang::Circle *'}} // expected-note@-2 {{Taking false branch}} return; } if (dyn_cast_or_null(C)) { - // expected-note@-1 {{Assuming 'C' is not a 'Triangle'}} + // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Triangle *'}} // expected-note@-2 {{Taking false branch}} return; } if (dyn_cast_or_null(C)) { - // expected-note@-1 {{Assuming 'C' is not a 'Rectangle'}} + // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Rectangle *'}} // expected-note@-2 {{Taking false branch}} return; } if (dyn_cast_or_null(C)) { - // expected-note@-1 {{Assuming 'C' is not a 'Hexagon'}} + // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Hexagon *'}} // expected-note@-2 {{Taking false branch}} return; } @@ -234,10 +234,10 @@ void evalNonNullParamNonNullReturn(const Shape *S) { void evalNonNullParamNullReturn(const Shape *S) { const auto *C = dyn_cast_or_null(S); - // expected-note@-1 {{Assuming 'S' is not a 'Circle'}} + // expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle *'}} if (const auto *T = dyn_cast_or_null(S)) { - // expected-note@-1 {{Assuming 'S' is a 'Triangle'}} + // expected-note@-1 {{Assuming 'S' is a 'const class clang::Triangle *'}} // expected-note@-2 {{'T' initialized here}} // expected-note@-3 {{'T' is non-null}} // expected-note@-4 {{Taking true branch}} @@ -261,7 +261,7 @@ void evalNullParamNullReturn(const Shape *S) { void evalZeroParamNonNullReturnPointer(const Shape *S) { const auto *C = S->castAs(); - // expected-note@-1 {{'S' is a 'Circle'}} + // expected-note@-1 {{'S' is a 'const class clang::Circle *'}} // expected-note@-2 {{'C' initialized here}} (void)(1 / !C); @@ -282,12 +282,12 @@ void evalZeroParamNonNullReturn(const Shape &S) { void evalZeroParamNullReturn(const Shape *S) { const auto &C = S->getAs(); - // expected-note@-1 {{Assuming 'S' is not a 'Circle'}} + // expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle *'}} // expected-note@-2 {{Storing null pointer value}} // expected-note@-3 {{'C' initialized here}} if (!dyn_cast_or_null(S)) { - // expected-note@-1 {{Assuming 'S' is a 'Triangle'}} + // expected-note@-1 {{Assuming 'S' is a 'const class clang::Triangle *'}} // expected-note@-2 {{Taking false branch}} return; } @@ -302,3 +302,32 @@ void evalZeroParamNullReturn(const Shape *S) { // expected-note@-1 {{Division by zero}} // expected-warning@-2 {{Division by zero}} } + +// don't crash +// CastValueChecker was using QualType()->getPointeeCXXRecordDecl(), in +// getNoteTag which evaluated to nullptr, then crashed when attempting to +// deref an invocation to getNameAsString(). The fix is to use +// QualType().getAsString(). +// +// Example: +// std::string CastToName = +// CastInfo ? CastInfo->to()->getAsCXXRecordDecl()->getNameAsString() +// : CastToTy->getPointeeCXXRecordDecl()->getNameAsString(); +// Changed to: +// std::string CastToName = +// CastInfo ? CastInfo->to()->getAsCXXRecordDecl()->getNameAsString() +// : CastToTy.getAsString(); +namespace llvm { +template void isa(a &); +template class PointerUnion { +public: + template T *getAs() { + (void)isa(*this); + return nullptr; + } +}; +class LLVMContext { + PointerUnion c; + void d() { c.getAs(); } +}; +} // namespace llvm diff --git a/clang/test/Analysis/cast-value-state-dump.cpp b/clang/test/Analysis/cast-value-state-dump.cpp index 3e6a40cf1319b..c9d85f0b4460f 100644 --- a/clang/test/Analysis/cast-value-state-dump.cpp +++ b/clang/test/Analysis/cast-value-state-dump.cpp @@ -18,12 +18,12 @@ using namespace clang; void evalNonNullParamNonNullReturn(const Shape *S) { const auto *C = dyn_cast_or_null(S); - // expected-note@-1 {{Assuming 'S' is a 'Circle'}} + // expected-note@-1 {{Assuming 'S' is a 'const class clang::Circle *'}} // expected-note@-2 {{'C' initialized here}} // FIXME: We assumed that 'S' is a 'Circle' therefore it is not a 'Square'. if (dyn_cast_or_null(S)) { - // expected-note@-1 {{Assuming 'S' is not a 'Square'}} + // expected-note@-1 {{Assuming 'S' is not a 'const class clang::Square *'}} // expected-note@-2 {{Taking false branch}} return; } diff --git a/clang/test/Analysis/casts.c b/clang/test/Analysis/casts.c index afa3e1ae36ca9..1fc8a8551637c 100644 --- a/clang/test/Analysis/casts.c +++ b/clang/test/Analysis/casts.c @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -fenable-matrix -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -Wno-pointer-to-int-cast -Wno-strict-prototypes -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -fenable-matrix -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -Wno-pointer-to-int-cast -Wno-strict-prototypes -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -fenable-matrix -analyzer-checker=core,alpha.core,debug.ExprInspection -Wno-pointer-to-int-cast -Wno-strict-prototypes -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -fenable-matrix -analyzer-checker=core,alpha.core,debug.ExprInspection -Wno-pointer-to-int-cast -Wno-strict-prototypes -verify -analyzer-config eagerly-assume=false %s // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -fenable-matrix -analyzer-checker=core,alpha.core,debug.ExprInspection -Wno-pointer-to-int-cast -Wno-strict-prototypes -verify -DEAGERLY_ASSUME=1 -w %s // RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -fenable-matrix -analyzer-checker=core,alpha.core,debug.ExprInspection -Wno-pointer-to-int-cast -Wno-strict-prototypes -verify -DEAGERLY_ASSUME=1 -DBIT32=1 -w %s diff --git a/clang/test/Analysis/casts.cpp b/clang/test/Analysis/casts.cpp index aa2bd9c1fadc9..dbf628e63319f 100644 --- a/clang/test/Analysis/casts.cpp +++ b/clang/test/Analysis/casts.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core,debug.ExprInspection -verify %s void clang_analyzer_eval(bool); diff --git a/clang/test/Analysis/casts.m b/clang/test/Analysis/casts.m index eda26c68d0175..28ed75975338c 100644 --- a/clang/test/Analysis/casts.m +++ b/clang/test/Analysis/casts.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -verify %s // expected-no-diagnostics // Test function pointer casts. diff --git a/clang/test/Analysis/cfref_PR2519.c b/clang/test/Analysis/cfref_PR2519.c index 8ba608ccf3e55..5c1ab1a96012d 100644 --- a/clang/test/Analysis/cfref_PR2519.c +++ b/clang/test/Analysis/cfref_PR2519.c @@ -1,5 +1,5 @@ // UNSUPPORTED: -zos, -aix -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -verify %s // expected-no-diagnostics typedef unsigned char Boolean; diff --git a/clang/test/Analysis/cfref_rdar6080742.c b/clang/test/Analysis/cfref_rdar6080742.c index 2f7403658e8a7..95ac67cb94493 100644 --- a/clang/test/Analysis/cfref_rdar6080742.c +++ b/clang/test/Analysis/cfref_rdar6080742.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -verify %s // expected-no-diagnostics // This test case was reported in . diff --git a/clang/test/Analysis/chroot.c b/clang/test/Analysis/chroot.c index 7e514f744000b..eb512c05f86f7 100644 --- a/clang/test/Analysis/chroot.c +++ b/clang/test/Analysis/chroot.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.unix.Chroot -analyzer-store region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.unix.Chroot -verify %s extern int chroot(const char* path); extern int chdir(const char* path); diff --git a/clang/test/Analysis/concrete-address.c b/clang/test/Analysis/concrete-address.c index fe0de4a1ff257..346f5093e44f7 100644 --- a/clang/test/Analysis/concrete-address.c +++ b/clang/test/Analysis/concrete-address.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -verify %s // expected-no-diagnostics void foo(void) { diff --git a/clang/test/Analysis/coverage.c b/clang/test/Analysis/coverage.c index f0fa1d40c39d1..e257e1c0f18ec 100644 --- a/clang/test/Analysis/coverage.c +++ b/clang/test/Analysis/coverage.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -analyzer-store=region -analyzer-max-loop 4 -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -analyzer-max-loop 4 -verify %s #include "Inputs/system-header-simulator.h" typedef __typeof(sizeof(int)) size_t; diff --git a/clang/test/Analysis/cstring-syntax-cxx.cpp b/clang/test/Analysis/cstring-syntax-cxx.cpp index b2adef8e1ecee..b11b81105b920 100644 --- a/clang/test/Analysis/cstring-syntax-cxx.cpp +++ b/clang/test/Analysis/cstring-syntax-cxx.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=unix.cstring.BadSizeArg -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=unix.cstring.BadSizeArg -verify %s // expected-no-diagnostics // Ensure we don't crash on C++ declarations with special names. diff --git a/clang/test/Analysis/cxx-method-names.cpp b/clang/test/Analysis/cxx-method-names.cpp index e57e72df840ed..22ec4db34796b 100644 --- a/clang/test/Analysis/cxx-method-names.cpp +++ b/clang/test/Analysis/cxx-method-names.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,osx,alpha.unix,alpha.security.taint -analyzer-store region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,osx,alpha.unix,alpha.security.taint -verify %s // expected-no-diagnostics class Evil { diff --git a/clang/test/Analysis/dead-stores.cpp b/clang/test/Analysis/dead-stores.cpp index 94865b36a9084..a5b7a1e5e0851 100644 --- a/clang/test/Analysis/dead-stores.cpp +++ b/clang/test/Analysis/dead-stores.cpp @@ -4,7 +4,7 @@ // RUN: -verify=non-nested %s // // RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11 \ -// RUN: -analyzer-store=region -analyzer-checker=deadcode.DeadStores \ +// RUN: -analyzer-checker=deadcode.DeadStores \ // RUN: -analyzer-config deadcode.DeadStores:WarnForDeadNestedAssignments=false\ // RUN: -Wno-unreachable-code -verify=non-nested %s // diff --git a/clang/test/Analysis/default-diagnostic-visitors.c b/clang/test/Analysis/default-diagnostic-visitors.c index 894684c9c504c..d6a23b0640dd1 100644 --- a/clang/test/Analysis/default-diagnostic-visitors.c +++ b/clang/test/Analysis/default-diagnostic-visitors.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core -analyzer-store=region -analyzer-output=text -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core -analyzer-output=text -verify %s // This file is for testing enhanced diagnostics produced by the default BugReporterVisitors. diff --git a/clang/test/Analysis/delegates.m b/clang/test/Analysis/delegates.m index 23028054517e4..9a4689257c82e 100644 --- a/clang/test/Analysis/delegates.m +++ b/clang/test/Analysis/delegates.m @@ -1,7 +1,6 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -Wno-objc-root-class -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -Wno-objc-root-class -verify %s // expected-no-diagnostics - //===----------------------------------------------------------------------===// // The following code is reduced using delta-debugging from // Foundation.h (Mac OS X). diff --git a/clang/test/Analysis/deprecated-flags-and-options.cpp b/clang/test/Analysis/deprecated-flags-and-options.cpp new file mode 100644 index 0000000000000..262ce9dfd96fa --- /dev/null +++ b/clang/test/Analysis/deprecated-flags-and-options.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core %s 2>&1 \ +// RUN: | FileCheck %s --check-prefixes=CHECK + +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region %s 2>&1 \ +// RUN: | FileCheck %s --check-prefixes=CHECK,DEPRECATED-STORE +// DEPRECATED-STORE: warning: analyzer option '-analyzer-store' is deprecated. This flag will be removed in clang-16, and passing this option will be an error. + +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-opt-analyze-nested-blocks %s 2>&1 \ +// RUN: | FileCheck %s --check-prefixes=CHECK,DEPRECATED-NESTED-BLOCKS +// DEPRECATED-NESTED-BLOCKS: warning: analyzer option '-analyzer-opt-analyze-nested-blocks' is deprecated. This flag will be removed in clang-16, and passing this option will be an error. + +// RUN: %clang_analyze_cc1 -analyzer-checker=core %s --help 2>&1 \ +// RUN: | FileCheck %s --check-prefixes=CHECK-HELP +// CHECK-HELP: Analyze the definitions of blocks in addition to functions [DEPRECATED, removing in clang-16] +// CHECK-HELP: -analyzer-store Source Code Analysis - Abstract Memory Store Models [DEPRECATED, removing in clang-16] + +int empty(int x) { + // CHECK: warning: Division by zero + return x ? 0 : 0 / x; +} diff --git a/clang/test/Analysis/disable-all-checks.c b/clang/test/Analysis/disable-all-checks.c index be56ffa4045e9..f1a53346c56cd 100644 --- a/clang/test/Analysis/disable-all-checks.c +++ b/clang/test/Analysis/disable-all-checks.c @@ -1,12 +1,12 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region \ +// RUN: %clang_analyze_cc1 -analyzer-checker=core \ // RUN: -analyzer-disable-all-checks -verify %s // // RUN: %clang_analyze_cc1 -analyzer-disable-all-checks -analyzer-checker=core \ -// RUN: -analyzer-store=region -verify %s +// RUN: -verify %s // // RUN: %clang_analyze_cc1 -analyzer-disable-all-checks -verify %s // -// RUN: not %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region \ +// RUN: not %clang_analyze_cc1 -analyzer-checker=core \ // RUN: -analyzer-disable-checker non.existant.Checker -verify %s 2>&1 \ // RUN: | FileCheck %s // diff --git a/clang/test/Analysis/elementtype.c b/clang/test/Analysis/elementtype.c index 47f2ca1d90820..5897c5533150e 100644 --- a/clang/test/Analysis/elementtype.c +++ b/clang/test/Analysis/elementtype.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-store=region %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core %s typedef struct added_obj_st { int type; diff --git a/clang/test/Analysis/expr-inspection.cpp b/clang/test/Analysis/expr-inspection.cpp index 3e65305032927..94db6e38b8419 100644 --- a/clang/test/Analysis/expr-inspection.cpp +++ b/clang/test/Analysis/expr-inspection.cpp @@ -1,9 +1,17 @@ -// RUN: %clang_analyze_cc1 -x c++ -analyzer-checker=debug.ExprInspection -verify %s +// RUN: %clang_analyze_cc1 -x c++ -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config support-symbolic-integer-casts=false \ +// RUN: -verify %s + +// RUN: %clang_analyze_cc1 -x c++ -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config support-symbolic-integer-casts=true \ +// RUN: -verify %s // Self-tests for the debug.ExprInspection checker. -void clang_analyzer_denote(int x, const char *str); -void clang_analyzer_express(int x); +template +void clang_analyzer_denote(T x, const char *str); +template +void clang_analyzer_express(T x); // Invalid declarations to test basic correctness checks. void clang_analyzer_denote(); diff --git a/clang/test/Analysis/fields.c b/clang/test/Analysis/fields.c index 8d2e7ac9b47ce..203c30c5960a1 100644 --- a/clang/test/Analysis/fields.c +++ b/clang/test/Analysis/fields.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection %s -analyzer-store=region -verify +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection %s -verify void clang_analyzer_eval(int); diff --git a/clang/test/Analysis/free.c b/clang/test/Analysis/free.c index d74f28ab9b9b5..50c1efdfb1309 100644 --- a/clang/test/Analysis/free.c +++ b/clang/test/Analysis/free.c @@ -1,8 +1,8 @@ -// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-store=region \ +// RUN: %clang_analyze_cc1 -fblocks -verify %s \ // RUN: -analyzer-checker=core \ // RUN: -analyzer-checker=unix.Malloc // -// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-store=region \ +// RUN: %clang_analyze_cc1 -fblocks -verify %s \ // RUN: -analyzer-checker=core \ // RUN: -analyzer-checker=unix.Malloc \ // RUN: -analyzer-config unix.DynamicMemoryModeling:Optimistic=true diff --git a/clang/test/Analysis/free.cpp b/clang/test/Analysis/free.cpp index 85b0935a51992..a812a22c47d39 100644 --- a/clang/test/Analysis/free.cpp +++ b/clang/test/Analysis/free.cpp @@ -1,8 +1,8 @@ -// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-store=region \ +// RUN: %clang_analyze_cc1 -fblocks -verify %s \ // RUN: -analyzer-checker=core \ // RUN: -analyzer-checker=unix.Malloc // -// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-store=region \ +// RUN: %clang_analyze_cc1 -fblocks -verify %s \ // RUN: -analyzer-checker=core \ // RUN: -analyzer-checker=unix.Malloc \ // RUN: -analyzer-config unix.DynamicMemoryModeling:Optimistic=true diff --git a/clang/test/Analysis/func.c b/clang/test/Analysis/func.c index 7fea41d1f0652..9d59d2824beee 100644 --- a/clang/test/Analysis/func.c +++ b/clang/test/Analysis/func.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s void clang_analyzer_eval(int); void clang_analyzer_warnIfReached(void); diff --git a/clang/test/Analysis/globals-are-not-always-immutable.c b/clang/test/Analysis/globals-are-not-always-immutable.c new file mode 100644 index 0000000000000..26609095d8c50 --- /dev/null +++ b/clang/test/Analysis/globals-are-not-always-immutable.c @@ -0,0 +1,71 @@ +// RUN: %clang_analyze_cc1 -verify %s \ +// RUN: -analyzer-config eagerly-assume=false \ +// RUN: -analyzer-checker=core,debug.ExprInspection + +#include "Inputs/errno_var.h" +#include "Inputs/some_system_globals.h" +#include "Inputs/some_user_globals.h" + +extern void abort() __attribute__((__noreturn__)); +#define assert(expr) ((expr) ? (void)(0) : abort()) + +void invalidate_globals(void); +void clang_analyzer_eval(int x); + +/// Test the special system 'errno' +void test_errno_constraint() { + assert(errno > 2); + clang_analyzer_eval(errno > 2); // expected-warning {{TRUE}} + invalidate_globals(); + clang_analyzer_eval(errno > 2); // expected-warning {{UNKNOWN}} +} +void test_errno_assign(int x) { + errno = x; + clang_analyzer_eval(errno == x); // expected-warning {{TRUE}} + invalidate_globals(); + clang_analyzer_eval(errno == x); // expected-warning {{UNKNOWN}} +} + +/// Test user global variables +void test_my_const_user_global_constraint() { + assert(my_const_user_global > 2); + clang_analyzer_eval(my_const_user_global > 2); // expected-warning {{TRUE}} + invalidate_globals(); + clang_analyzer_eval(my_const_user_global > 2); // expected-warning {{TRUE}} +} +void test_my_const_user_global_assign(int); // One cannot assign value to a const lvalue. + +void test_my_mutable_user_global_constraint() { + assert(my_mutable_user_global > 2); + clang_analyzer_eval(my_mutable_user_global > 2); // expected-warning {{TRUE}} + invalidate_globals(); + clang_analyzer_eval(my_mutable_user_global > 2); // expected-warning {{UNKNOWN}} +} +void test_my_mutable_user_global_assign(int x) { + my_mutable_user_global = x; + clang_analyzer_eval(my_mutable_user_global == x); // expected-warning {{TRUE}} + invalidate_globals(); + clang_analyzer_eval(my_mutable_user_global == x); // expected-warning {{UNKNOWN}} +} + +/// Test system global variables +void test_my_const_system_global_constraint() { + assert(my_const_system_global > 2); + clang_analyzer_eval(my_const_system_global > 2); // expected-warning {{TRUE}} + invalidate_globals(); + clang_analyzer_eval(my_const_system_global > 2); // expected-warning {{TRUE}} +} +void test_my_const_system_global_assign(int);// One cannot assign value to a const lvalue. + +void test_my_mutable_system_global_constraint() { + assert(my_mutable_system_global > 2); + clang_analyzer_eval(my_mutable_system_global > 2); // expected-warning {{TRUE}} + invalidate_globals(); + clang_analyzer_eval(my_mutable_system_global > 2); // expected-warning {{UNKNOWN}} +} +void test_my_mutable_system_global_assign(int x) { + my_mutable_system_global = x; + clang_analyzer_eval(my_mutable_system_global == x); // expected-warning {{TRUE}} + invalidate_globals(); + clang_analyzer_eval(my_mutable_system_global == x); // expected-warning {{UNKNOWN}} +} diff --git a/clang/test/Analysis/gmalloc.c b/clang/test/Analysis/gmalloc.c index 240138e8a7a05..279e2ae844b78 100644 --- a/clang/test/Analysis/gmalloc.c +++ b/clang/test/Analysis/gmalloc.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -verify %s #include "Inputs/system-header-simulator.h" diff --git a/clang/test/Analysis/ivars.m b/clang/test/Analysis/ivars.m index d17e6d6a083da..16232e979cd1b 100644 --- a/clang/test/Analysis/ivars.m +++ b/clang/test/Analysis/ivars.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -fblocks -verify -Wno-objc-root-class -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -fblocks -verify -Wno-objc-root-class -analyzer-config eagerly-assume=false %s void clang_analyzer_eval(int); diff --git a/clang/test/Analysis/keychainAPI-diagnostic-visitor.m b/clang/test/Analysis/keychainAPI-diagnostic-visitor.m index ccc1ea1edf3e7..7c9926b1d2439 100644 --- a/clang/test/Analysis/keychainAPI-diagnostic-visitor.m +++ b/clang/test/Analysis/keychainAPI-diagnostic-visitor.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=osx.SecKeychainAPI -analyzer-store=region -analyzer-output=text -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=osx.SecKeychainAPI -analyzer-output=text -verify %s // This file is for testing enhanced diagnostics produced by the default SecKeychainAPI checker. diff --git a/clang/test/Analysis/localization-aggressive.m b/clang/test/Analysis/localization-aggressive.m index d2c79e01b1b86..4da35b5b33040 100644 --- a/clang/test/Analysis/localization-aggressive.m +++ b/clang/test/Analysis/localization-aggressive.m @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fblocks -x objective-c-header -emit-pch -o %t.pch %S/Inputs/localization-pch.h -// RUN: %clang_analyze_cc1 -fblocks -analyzer-store=region \ +// RUN: %clang_analyze_cc1 -fblocks \ // RUN: -analyzer-config optin.osx.cocoa.localizability.NonLocalizedStringChecker:AggressiveReport=true \ // RUN: -analyzer-checker=optin.osx.cocoa.localizability.NonLocalizedStringChecker \ // RUN: -analyzer-checker=optin.osx.cocoa.localizability.EmptyLocalizationContextChecker \ diff --git a/clang/test/Analysis/localization.m b/clang/test/Analysis/localization.m index 3d65119be6018..65d857cc9a46e 100644 --- a/clang/test/Analysis/localization.m +++ b/clang/test/Analysis/localization.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -fblocks -analyzer-store=region -analyzer-output=text -analyzer-checker=optin.osx.cocoa.localizability.NonLocalizedStringChecker -analyzer-checker=alpha.osx.cocoa.localizability.PluralMisuseChecker -verify %s +// RUN: %clang_analyze_cc1 -fblocks -analyzer-output=text -analyzer-checker=optin.osx.cocoa.localizability.NonLocalizedStringChecker -analyzer-checker=alpha.osx.cocoa.localizability.PluralMisuseChecker -verify %s // The larger set of tests in located in localization.m. These are tests // specific for non-aggressive reporting. diff --git a/clang/test/Analysis/lvalue.cpp b/clang/test/Analysis/lvalue.cpp index 7621139876631..622f7a19f1d97 100644 --- a/clang/test/Analysis/lvalue.cpp +++ b/clang/test/Analysis/lvalue.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s // expected-no-diagnostics int f1() { diff --git a/clang/test/Analysis/malloc-annotations.c b/clang/test/Analysis/malloc-annotations.c index 39381c5d841f2..c2fdf8a5641ae 100644 --- a/clang/test/Analysis/malloc-annotations.c +++ b/clang/test/Analysis/malloc-annotations.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-store=region -verify \ +// RUN: %clang_analyze_cc1 -verify \ // RUN: -analyzer-checker=core \ // RUN: -analyzer-checker=alpha.deadcode.UnreachableCode \ // RUN: -analyzer-checker=alpha.core.CastSize \ diff --git a/clang/test/Analysis/malloc-annotations.cpp b/clang/test/Analysis/malloc-annotations.cpp index 0aac655d19c48..d75683f9f28d3 100644 --- a/clang/test/Analysis/malloc-annotations.cpp +++ b/clang/test/Analysis/malloc-annotations.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-store=region -verify \ +// RUN: %clang_analyze_cc1 -verify \ // RUN: -analyzer-checker=core \ // RUN: -analyzer-checker=alpha.deadcode.UnreachableCode \ // RUN: -analyzer-checker=alpha.core.CastSize \ diff --git a/clang/test/Analysis/malloc.c b/clang/test/Analysis/malloc.c index 7282a74bf0f4e..ade11e6c12064 100644 --- a/clang/test/Analysis/malloc.c +++ b/clang/test/Analysis/malloc.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -Wno-strict-prototypes -Wno-error=implicit-int -analyzer-store=region -verify %s \ +// RUN: %clang_analyze_cc1 -Wno-strict-prototypes -Wno-error=implicit-int -verify %s \ // RUN: -analyzer-checker=core \ // RUN: -analyzer-checker=alpha.deadcode.UnreachableCode \ // RUN: -analyzer-checker=alpha.core.CastSize \ diff --git a/clang/test/Analysis/malloc.m b/clang/test/Analysis/malloc.m index 657a6bafba8e7..230e536747da6 100644 --- a/clang/test/Analysis/malloc.m +++ b/clang/test/Analysis/malloc.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify -Wno-objc-root-class -fblocks %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -verify -Wno-objc-root-class -fblocks %s #include "Inputs/system-header-simulator-objc.h" @class NSString; diff --git a/clang/test/Analysis/method-call-intra-p.cpp b/clang/test/Analysis/method-call-intra-p.cpp index bead20fecd54c..54284b4ddcbd5 100644 --- a/clang/test/Analysis/method-call-intra-p.cpp +++ b/clang/test/Analysis/method-call-intra-p.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s // expected-no-diagnostics // Intra-procedural C++ tests. diff --git a/clang/test/Analysis/misc-ps-64.m b/clang/test/Analysis/misc-ps-64.m index 50c0e9795d866..9b76b55f549e3 100644 --- a/clang/test/Analysis/misc-ps-64.m +++ b/clang/test/Analysis/misc-ps-64.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core -verify -fblocks %s // expected-no-diagnostics // - A bunch of misc. failures involving evaluating diff --git a/clang/test/Analysis/misc-ps-arm.m b/clang/test/Analysis/misc-ps-arm.m index c950d7d7d62df..e7c44750eb512 100644 --- a/clang/test/Analysis/misc-ps-arm.m +++ b/clang/test/Analysis/misc-ps-arm.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple thumbv7-apple-ios0.0.0 -target-feature +neon -analyzer-checker=core -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -triple thumbv7-apple-ios0.0.0 -target-feature +neon -analyzer-checker=core -verify -fblocks -Wno-objc-root-class %s // expected-no-diagnostics // - Handle casts of vectors to structs, and loading diff --git a/clang/test/Analysis/misc-ps-eager-assume.m b/clang/test/Analysis/misc-ps-eager-assume.m index 6c24dfa5708c4..38f46b73e703c 100644 --- a/clang/test/Analysis/misc-ps-eager-assume.m +++ b/clang/test/Analysis/misc-ps-eager-assume.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -verify -fblocks %s // expected-no-diagnostics // Delta-reduced header stuff (needed for test cases). @@ -125,8 +125,8 @@ void rdar7342806(void) { //===---------------------------------------------------------------------===// // PR 5627 - http://llvm.org/bugs/show_bug.cgi?id=5627 -// This test case depends on using -analyzer-config eagerly-assume=true and -// -analyzer-store=region. The 'eagerly-assume=true' causes the path +// This test case depends on using -analyzer-config eagerly-assume=true. +// The 'eagerly-assume=true' causes the path // to bifurcate when evaluating the function call argument, and a state // caching bug in ExprEngine::CheckerVisit (and friends) caused the store // to 'p' to not be evaluated along one path, but then an autotransition caused diff --git a/clang/test/Analysis/misc-ps-ranges.m b/clang/test/Analysis/misc-ps-ranges.m index 161d9817bcf1b..be7449cf56343 100644 --- a/clang/test/Analysis/misc-ps-ranges.m +++ b/clang/test/Analysis/misc-ps-ranges.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -verify -fblocks %s // // main's 'argc' argument is always > 0 diff --git a/clang/test/Analysis/misc-ps-region-store-i386.m b/clang/test/Analysis/misc-ps-region-store-i386.m index 5ca7bc3f5de44..f0ae5576d3df5 100644 --- a/clang/test/Analysis/misc-ps-region-store-i386.m +++ b/clang/test/Analysis/misc-ps-region-store-i386.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core -verify -fblocks %s // expected-no-diagnostics // Here is a case where a pointer is treated as integer, invalidated as an diff --git a/clang/test/Analysis/misc-ps-region-store-x86_64.m b/clang/test/Analysis/misc-ps-region-store-x86_64.m index d52d127e23c1f..fa028abae54f2 100644 --- a/clang/test/Analysis/misc-ps-region-store-x86_64.m +++ b/clang/test/Analysis/misc-ps-region-store-x86_64.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core -verify -fblocks %s // expected-no-diagnostics // Here is a case where a pointer is treated as integer, invalidated as an diff --git a/clang/test/Analysis/misc-ps-region-store.cpp b/clang/test/Analysis/misc-ps-region-store.cpp index c6dad5dd9d6ec..238a4d597326f 100644 --- a/clang/test/Analysis/misc-ps-region-store.cpp +++ b/clang/test/Analysis/misc-ps-region-store.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -fexceptions -fcxx-exceptions -Wno-tautological-undefined-compare -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -fexceptions -fcxx-exceptions -Wno-tautological-undefined-compare +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -fblocks %s -fexceptions -fcxx-exceptions -Wno-tautological-undefined-compare +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -fblocks %s -fexceptions -fcxx-exceptions -Wno-tautological-undefined-compare void clang_analyzer_warnIfReached(); diff --git a/clang/test/Analysis/misc-ps-region-store.m b/clang/test/Analysis/misc-ps-region-store.m index fabe8a2bb8d25..6b68392523da8 100644 --- a/clang/test/Analysis/misc-ps-region-store.m +++ b/clang/test/Analysis/misc-ps-region-store.m @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core.CastToStruct,alpha.security.ReturnPtrRange,alpha.security.ArrayBound -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks -Wno-objc-root-class -Wno-strict-prototypes -Wno-error=implicit-function-declaration %s -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -DTEST_64 -analyzer-checker=core,alpha.core.CastToStruct,alpha.security.ReturnPtrRange,alpha.security.ArrayBound -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks -Wno-objc-root-class -Wno-strict-prototypes -Wno-error=implicit-function-declaration %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core.CastToStruct,alpha.security.ReturnPtrRange,alpha.security.ArrayBound -verify -fblocks -Wno-objc-root-class -Wno-strict-prototypes -Wno-error=implicit-function-declaration %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -DTEST_64 -analyzer-checker=core,alpha.core.CastToStruct,alpha.security.ReturnPtrRange,alpha.security.ArrayBound -verify -fblocks -Wno-objc-root-class -Wno-strict-prototypes -Wno-error=implicit-function-declaration %s typedef long unsigned int size_t; void *memcpy(void *, const void *, size_t); diff --git a/clang/test/Analysis/misc-ps-region-store.mm b/clang/test/Analysis/misc-ps-region-store.mm index 4b271c4512dc8..7722f01e35bc8 100644 --- a/clang/test/Analysis/misc-ps-region-store.mm +++ b/clang/test/Analysis/misc-ps-region-store.mm @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core -verify -fblocks %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core -verify -fblocks %s // expected-no-diagnostics //===------------------------------------------------------------------------------------------===// diff --git a/clang/test/Analysis/misc-ps.m b/clang/test/Analysis/misc-ps.m index daf4489006e41..e9e56315eb268 100644 --- a/clang/test/Analysis/misc-ps.m +++ b/clang/test/Analysis/misc-ps.m @@ -1,6 +1,6 @@ // NOTE: Use '-fobjc-gc' to test the analysis being run twice, and multiple reports are not issued. -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -analyzer-store=region -Wno-strict-prototypes -Wno-pointer-to-int-cast -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -analyzer-store=region -Wno-strict-prototypes -Wno-pointer-to-int-cast -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -Wno-strict-prototypes -Wno-pointer-to-int-cast -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -Wno-strict-prototypes -Wno-pointer-to-int-cast -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s #ifndef __clang_analyzer__ #error __clang_analyzer__ not defined diff --git a/clang/test/Analysis/new-with-exceptions.cpp b/clang/test/Analysis/new-with-exceptions.cpp index 9d02574229c1b..d3a79d63f523f 100644 --- a/clang/test/Analysis/new-with-exceptions.cpp +++ b/clang/test/Analysis/new-with-exceptions.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-store region -std=c++11 -fexceptions -fcxx-exceptions -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-store region -std=c++11 -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++11 -fexceptions -fcxx-exceptions -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++11 -verify %s void clang_analyzer_eval(bool); diff --git a/clang/test/Analysis/new.cpp b/clang/test/Analysis/new.cpp index 2c3eb2825a6bb..7f523b920c6b2 100644 --- a/clang/test/Analysis/new.cpp +++ b/clang/test/Analysis/new.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -std=c++11 -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify -analyzer-config eagerly-assume=false %s #include "Inputs/system-header-simulator-cxx.h" void clang_analyzer_eval(bool); diff --git a/clang/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret-region.m b/clang/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret-region.m index cbfc266b7beeb..3a8be8eceb2e7 100644 --- a/clang/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret-region.m +++ b/clang/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret-region.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin8 -analyzer-checker=core,alpha.core -analyzer-store=region -verify -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin8 -analyzer-checker=core,alpha.core -verify -Wno-objc-root-class %s // - This test case shows that a nil instance // variable can possibly be initialized by a method. diff --git a/clang/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m b/clang/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m index f65743ac5427d..bfc3cb92b639a 100644 --- a/clang/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m +++ b/clang/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m @@ -1,8 +1,8 @@ -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin8 -analyzer-checker=core,alpha.core -analyzer-store=region -Wno-objc-root-class %s > %t.1 2>&1 +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin8 -analyzer-checker=core,alpha.core -Wno-objc-root-class %s > %t.1 2>&1 // RUN: FileCheck -input-file=%t.1 -check-prefix=CHECK-darwin8 %s -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core -analyzer-store=region -Wno-objc-root-class %s > %t.2 2>&1 +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core -Wno-objc-root-class %s > %t.2 2>&1 // RUN: FileCheck -input-file=%t.2 -check-prefix=CHECK-darwin9 %s -// RUN: %clang_analyze_cc1 -triple thumbv6-apple-ios4.0 -analyzer-checker=core,alpha.core -analyzer-store=region -Wno-objc-root-class %s > %t.3 2>&1 +// RUN: %clang_analyze_cc1 -triple thumbv6-apple-ios4.0 -analyzer-checker=core,alpha.core -Wno-objc-root-class %s > %t.3 2>&1 // RUN: FileCheck -input-file=%t.3 -check-prefix=CHECK-darwin9 %s @interface MyClass {} diff --git a/clang/test/Analysis/no-exit-cfg.c b/clang/test/Analysis/no-exit-cfg.c index 7575152295ebc..f60f413d109b7 100644 --- a/clang/test/Analysis/no-exit-cfg.c +++ b/clang/test/Analysis/no-exit-cfg.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -verify %s // expected-no-diagnostics // This is a test case for the issue reported in PR 2819: diff --git a/clang/test/Analysis/no-outofbounds.c b/clang/test/Analysis/no-outofbounds.c index 5d88224669b0c..15155729067e9 100644 --- a/clang/test/Analysis/no-outofbounds.c +++ b/clang/test/Analysis/no-outofbounds.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,alpha.unix,alpha.security.ArrayBound -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,alpha.unix,alpha.security.ArrayBound -verify %s // expected-no-diagnostics //===----------------------------------------------------------------------===// diff --git a/clang/test/Analysis/null-deref-path-notes.m b/clang/test/Analysis/null-deref-path-notes.m index 00b6c52d3544b..c5fa9e50cb393 100644 --- a/clang/test/Analysis/null-deref-path-notes.m +++ b/clang/test/Analysis/null-deref-path-notes.m @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -analyzer-output=text -fblocks -verify -Wno-objc-root-class %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -analyzer-output=plist-multi-file -fblocks -Wno-objc-root-class %s -o %t +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -fblocks -verify -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -fblocks -Wno-objc-root-class %s -o %t // RUN: %normalize_plist <%t | diff -ub %S/Inputs/expected-plists/null-deref-path-notes.m.plist - @interface Root { diff --git a/clang/test/Analysis/null-deref-ps.c b/clang/test/Analysis/null-deref-ps.c index 5c44c92bceb52..4f256527bd28f 100644 --- a/clang/test/Analysis/null-deref-ps.c +++ b/clang/test/Analysis/null-deref-ps.c @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -Wno-strict-prototypes -Wno-tautological-constant-compare -Wtautological-unsigned-zero-compare -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-store=region -analyzer-purge=none -verify %s -Wno-error=return-type -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -Wno-strict-prototypes -Wno-tautological-constant-compare -Wtautological-unsigned-zero-compare -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-store=region -verify %s -Wno-error=return-type +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -Wno-strict-prototypes -Wno-tautological-constant-compare -Wtautological-unsigned-zero-compare -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-purge=none -verify %s -Wno-error=return-type +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -Wno-strict-prototypes -Wno-tautological-constant-compare -Wtautological-unsigned-zero-compare -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -verify %s -Wno-error=return-type typedef unsigned uintptr_t; diff --git a/clang/test/Analysis/nullptr.cpp b/clang/test/Analysis/nullptr.cpp index 24b574a4ccfe2..825f6570af591 100644 --- a/clang/test/Analysis/nullptr.cpp +++ b/clang/test/Analysis/nullptr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -std=c++11 -Wno-conversion-null -analyzer-checker=core,debug.ExprInspection -analyzer-store region -analyzer-output=text -verify %s +// RUN: %clang_analyze_cc1 -std=c++11 -Wno-conversion-null -analyzer-checker=core,debug.ExprInspection -analyzer-output=text -verify %s void clang_analyzer_eval(int); diff --git a/clang/test/Analysis/objc-arc.m b/clang/test/Analysis/objc-arc.m index 5fe5eb345fdbc..5489d507478fe 100644 --- a/clang/test/Analysis/objc-arc.m +++ b/clang/test/Analysis/objc-arc.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.cocoa.RetainCount,deadcode -verify -fblocks -analyzer-opt-analyze-nested-blocks -fobjc-arc -analyzer-output=plist-multi-file -analyzer-config deadcode.DeadStores:ShowFixIts=true -o %t.plist %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.cocoa.RetainCount,deadcode -verify -fblocks -fobjc-arc -analyzer-output=plist-multi-file -analyzer-config deadcode.DeadStores:ShowFixIts=true -o %t.plist %s // RUN: %normalize_plist <%t.plist | diff -ub %S/Inputs/expected-plists/objc-arc.m.plist - typedef signed char BOOL; diff --git a/clang/test/Analysis/objc-boxing.m b/clang/test/Analysis/objc-boxing.m index a4b8057d4d5d8..fb0c3468446d0 100644 --- a/clang/test/Analysis/objc-boxing.m +++ b/clang/test/Analysis/objc-boxing.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -Wno-objc-literal-conversion -analyzer-checker=core,unix.Malloc,osx.cocoa.NonNilReturnValue,debug.ExprInspection -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -Wno-objc-literal-conversion -analyzer-checker=core,unix.Malloc,osx.cocoa.NonNilReturnValue,debug.ExprInspection -verify %s void clang_analyzer_eval(int); diff --git a/clang/test/Analysis/objc-message.m b/clang/test/Analysis/objc-message.m index c7efdb64c1974..f0daaad562e27 100644 --- a/clang/test/Analysis/objc-message.m +++ b/clang/test/Analysis/objc-message.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -Wno-objc-root-class %s extern void clang_analyzer_warnIfReached(void); void clang_analyzer_eval(int); diff --git a/clang/test/Analysis/objc-subscript.m b/clang/test/Analysis/objc-subscript.m index 155fbb7b6268f..79ec30fe198a4 100644 --- a/clang/test/Analysis/objc-subscript.m +++ b/clang/test/Analysis/objc-subscript.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -verify -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -verify -Wno-objc-root-class %s typedef signed char BOOL; typedef unsigned int NSUInteger; diff --git a/clang/test/Analysis/outofbound-notwork.c b/clang/test/Analysis/outofbound-notwork.c index 22ccd9e2c913d..cf2239cee1301 100644 --- a/clang/test/Analysis/outofbound-notwork.c +++ b/clang/test/Analysis/outofbound-notwork.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -Wno-array-bounds -analyzer-checker=core,alpha.security.ArrayBound -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -Wno-array-bounds -analyzer-checker=core,alpha.security.ArrayBound -verify %s // XFAIL: * // Once we better handle modeling of sizes of VLAs, we can pull this back diff --git a/clang/test/Analysis/outofbound.c b/clang/test/Analysis/outofbound.c index 6e61d8929f13e..009cf33f61309 100644 --- a/clang/test/Analysis/outofbound.c +++ b/clang/test/Analysis/outofbound.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -Wno-array-bounds -analyzer-store=region -verify %s \ +// RUN: %clang_analyze_cc1 -Wno-array-bounds -verify %s \ // RUN: -analyzer-checker=core \ // RUN: -analyzer-checker=unix \ // RUN: -analyzer-checker=alpha.security.ArrayBound \ diff --git a/clang/test/Analysis/override-werror.c b/clang/test/Analysis/override-werror.c index df80bac84f4af..e84c20fc0696f 100644 --- a/clang/test/Analysis/override-werror.c +++ b/clang/test/Analysis/override-werror.c @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -Werror %s -analyzer-store=region -verify -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -Werror %s -analyzer-store=region -analyzer-werror -verify=werror +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -Werror %s -verify +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -Werror %s -analyzer-werror -verify=werror // This test case illustrates that using '-analyze' overrides the effect of // -Werror. This allows basic warnings not to interfere with producing diff --git a/clang/test/Analysis/pointer-to-member.cpp b/clang/test/Analysis/pointer-to-member.cpp index e1b4d0c11949c..a1adaa719617e 100644 --- a/clang/test/Analysis/pointer-to-member.cpp +++ b/clang/test/Analysis/pointer-to-member.cpp @@ -310,3 +310,13 @@ void test() { } } // namespace testStaticCasting +namespace D126198 { +class Base {}; +class Derived : public Base {}; +int foo(int Derived::*); + +int test() { + int Base::*p = nullptr; + return foo(p); // no-crash +} +} // namespace D126198 diff --git a/clang/test/Analysis/pr22954.c b/clang/test/Analysis/pr22954.c index 8ca2f809c9e9a..6447ebd00f440 100644 --- a/clang/test/Analysis/pr22954.c +++ b/clang/test/Analysis/pr22954.c @@ -3,7 +3,7 @@ // At the moment the whole of the destination array content is invalidated. // If a.s1 region has a symbolic offset, the whole region of 'a' is invalidated. // Specific triple set to test structures of size 0. -// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,unix.Malloc,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s typedef __typeof(sizeof(int)) size_t; diff --git a/clang/test/Analysis/pr4209.m b/clang/test/Analysis/pr4209.m index 8b0eacad96949..eb43e2b017631 100644 --- a/clang/test/Analysis/pr4209.m +++ b/clang/test/Analysis/pr4209.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core -analyzer-store=region -Wno-incomplete-implementation -verify %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core -Wno-incomplete-implementation -verify %s // This test case was crashing due to how CFRefCount.cpp resolved the // ObjCInterfaceDecl* and ClassName in EvalObjCMessageExpr. diff --git a/clang/test/Analysis/pr_2542_rdar_6793404.m b/clang/test/Analysis/pr_2542_rdar_6793404.m index 5df40e88fcb48..4b6936d86ea2d 100644 --- a/clang/test/Analysis/pr_2542_rdar_6793404.m +++ b/clang/test/Analysis/pr_2542_rdar_6793404.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -pedantic -analyzer-store=region -verify -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -pedantic -verify -Wno-objc-root-class %s // BEGIN delta-debugging reduced header stuff diff --git a/clang/test/Analysis/pr_4164.c b/clang/test/Analysis/pr_4164.c index e1d4e475d69f8..8f432cbc4a24e 100644 --- a/clang/test/Analysis/pr_4164.c +++ b/clang/test/Analysis/pr_4164.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core -verify %s // expected-no-diagnostics // PR 4164: http://llvm.org/bugs/show_bug.cgi?id=4164 diff --git a/clang/test/Analysis/properties.m b/clang/test/Analysis/properties.m index 4a76b42343fc4..b12af2fadd66a 100644 --- a/clang/test/Analysis/properties.m +++ b/clang/test/Analysis/properties.m @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.Dealloc,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.Dealloc,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -fobjc-arc -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.Dealloc,debug.ExprInspection -verify -Wno-objc-root-class -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.Dealloc,debug.ExprInspection -verify -Wno-objc-root-class -fobjc-arc -analyzer-config eagerly-assume=false %s void clang_analyzer_eval(int); diff --git a/clang/test/Analysis/properties.mm b/clang/test/Analysis/properties.mm index fc3be967115e1..cad92e47e6980 100644 --- a/clang/test/Analysis/properties.mm +++ b/clang/test/Analysis/properties.mm @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -fobjc-arc %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -verify -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -verify -Wno-objc-root-class -fobjc-arc %s void clang_analyzer_eval(bool); void clang_analyzer_checkInlined(bool); diff --git a/clang/test/Analysis/ptr-arith.c b/clang/test/Analysis/ptr-arith.c index 0b7c1595aa699..8b20d6726f7d5 100644 --- a/clang/test/Analysis/ptr-arith.c +++ b/clang/test/Analysis/ptr-arith.c @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -Wno-pointer-to-int-cast -verify -triple x86_64-apple-darwin9 -Wno-tautological-pointer-compare -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -Wno-pointer-to-int-cast -verify -triple i686-apple-darwin9 -Wno-tautological-pointer-compare -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -Wno-pointer-to-int-cast -verify -triple x86_64-apple-darwin9 -Wno-tautological-pointer-compare -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -Wno-pointer-to-int-cast -verify -triple i686-apple-darwin9 -Wno-tautological-pointer-compare -analyzer-config eagerly-assume=false %s void clang_analyzer_eval(int); void clang_analyzer_dump(int); diff --git a/clang/test/Analysis/qt_malloc.cpp b/clang/test/Analysis/qt_malloc.cpp index ad25634d87b01..0d6fc470f461f 100644 --- a/clang/test/Analysis/qt_malloc.cpp +++ b/clang/test/Analysis/qt_malloc.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,cplusplus -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,cplusplus -verify %s // expected-no-diagnostics #include "Inputs/qt-simulator.h" diff --git a/clang/test/Analysis/range_casts.c b/clang/test/Analysis/range_casts.c index 746aca974d7ec..b1967730bf861 100644 --- a/clang/test/Analysis/range_casts.c +++ b/clang/test/Analysis/range_casts.c @@ -1,5 +1,5 @@ // This test checks that intersecting ranges does not cause 'system is over constrained' assertions in the case of eg: 32 bits unsigned integers getting their range from 64 bits signed integers. -// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,debug.ExprInspection -verify %s void clang_analyzer_warnIfReached(void); diff --git a/clang/test/Analysis/rdar-6442306-1.m b/clang/test/Analysis/rdar-6442306-1.m index d84000076d79d..c5205b2d83cf0 100644 --- a/clang/test/Analysis/rdar-6442306-1.m +++ b/clang/test/Analysis/rdar-6442306-1.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-disable-checker=alpha.core.PointerArithm %s -analyzer-store=region -verify +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-disable-checker=alpha.core.PointerArithm %s -verify // expected-no-diagnostics typedef int bar_return_t; diff --git a/clang/test/Analysis/rdar-6541136-region.c b/clang/test/Analysis/rdar-6541136-region.c index dc75af43e491e..f1a3a48a5fe4a 100644 --- a/clang/test/Analysis/rdar-6541136-region.c +++ b/clang/test/Analysis/rdar-6541136-region.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -verify -analyzer-checker=core,alpha.security.ArrayBound -analyzer-store=region %s +// RUN: %clang_analyze_cc1 -verify -analyzer-checker=core,alpha.security.ArrayBound %s struct tea_cheese { unsigned magic; }; typedef struct tea_cheese kernel_tea_cheese_t; diff --git a/clang/test/Analysis/rdar-6562655.m b/clang/test/Analysis/rdar-6562655.m index 8794cacb74a0e..68d12dfb123fd 100644 --- a/clang/test/Analysis/rdar-6562655.m +++ b/clang/test/Analysis/rdar-6562655.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -verify %s // expected-no-diagnostics // // This test case mainly checks that the retain/release checker doesn't crash diff --git a/clang/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m b/clang/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m index f3659aa53ca66..db28215f01593 100644 --- a/clang/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m +++ b/clang/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-store=region -verify -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -verify -Wno-objc-root-class %s // expected-no-diagnostics typedef struct Foo { int x; } Bar; diff --git a/clang/test/Analysis/rdar-7168531.m b/clang/test/Analysis/rdar-7168531.m index b2b1511dd2ab7..fb50f8e468c01 100644 --- a/clang/test/Analysis/rdar-7168531.m +++ b/clang/test/Analysis/rdar-7168531.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -analyzer-store=region %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 %s // Note that the target triple is important for this test case. It specifies that we use the // fragile Objective-C ABI. diff --git a/clang/test/Analysis/refcnt_naming.m b/clang/test/Analysis/refcnt_naming.m index c77909a0c2771..1b53e84814dad 100644 --- a/clang/test/Analysis/refcnt_naming.m +++ b/clang/test/Analysis/refcnt_naming.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -analyzer-config ipa=none -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -analyzer-config ipa=none -verify %s typedef const struct __CFString * CFStringRef; typedef const struct __CFAllocator * CFAllocatorRef; diff --git a/clang/test/Analysis/reference.cpp b/clang/test/Analysis/reference.cpp index 37113f0fa13c2..61a3db74ba907 100644 --- a/clang/test/Analysis/reference.cpp +++ b/clang/test/Analysis/reference.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -Wno-null-dereference -Wno-tautological-undefined-compare -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -Wno-null-dereference -Wno-tautological-undefined-compare -analyzer-config eagerly-assume=false %s void clang_analyzer_eval(bool); diff --git a/clang/test/Analysis/region-1.m b/clang/test/Analysis/region-1.m index 3245bd4cf744c..0cd9b47ea1b2e 100644 --- a/clang/test/Analysis/region-1.m +++ b/clang/test/Analysis/region-1.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -verify %s // expected-no-diagnostics // // This test case simply should not crash. It evaluates the logic of not diff --git a/clang/test/Analysis/retain-release-path-notes.m b/clang/test/Analysis/retain-release-path-notes.m index df40761e9be9a..3c193c1e2bc4f 100644 --- a/clang/test/Analysis/retain-release-path-notes.m +++ b/clang/test/Analysis/retain-release-path-notes.m @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=text -verify %s -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=plist-multi-file %s -o %t +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-output=text -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-output=plist-multi-file %s -o %t // RUN: %normalize_plist <%t | diff -ub %S/Inputs/expected-plists/retain-release-path-notes.m.plist - /*** diff --git a/clang/test/Analysis/retain-release-region-store.m b/clang/test/Analysis/retain-release-region-store.m index 6e63fdb0f06b5..d6c0b54470a53 100644 --- a/clang/test/Analysis/retain-release-region-store.m +++ b/clang/test/Analysis/retain-release-region-store.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple %itanium_abi_triple -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -analyzer-max-loop 6 -verify %s +// RUN: %clang_analyze_cc1 -triple %itanium_abi_triple -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-max-loop 6 -verify %s //===----------------------------------------------------------------------===// // The following code is reduced using delta-debugging from diff --git a/clang/test/Analysis/retain-release.mm b/clang/test/Analysis/retain-release.mm index 9c884e5b471f9..733d35059d20a 100644 --- a/clang/test/Analysis/retain-release.mm +++ b/clang/test/Analysis/retain-release.mm @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fblocks -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -fblocks -verify %s #if __has_feature(attribute_ns_returns_retained) #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained)) diff --git a/clang/test/Analysis/stack-addr-ps.c b/clang/test/Analysis/stack-addr-ps.c index efb57eb79aa2d..04689d0eee572 100644 --- a/clang/test/Analysis/stack-addr-ps.c +++ b/clang/test/Analysis/stack-addr-ps.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -fblocks -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core -fblocks -verify %s int* f1(void) { int x = 0; diff --git a/clang/test/Analysis/stack-addr-ps.cpp b/clang/test/Analysis/stack-addr-ps.cpp index 956dcb0428e9b..8f1cfc00690d9 100644 --- a/clang/test/Analysis/stack-addr-ps.cpp +++ b/clang/test/Analysis/stack-addr-ps.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -verify %s -Wno-undefined-bool-conversion +// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s -Wno-undefined-bool-conversion typedef __INTPTR_TYPE__ intptr_t; diff --git a/clang/test/Analysis/stack-block-returned.cpp b/clang/test/Analysis/stack-block-returned.cpp index b45cf6335b900..3d4637904179e 100644 --- a/clang/test/Analysis/stack-block-returned.cpp +++ b/clang/test/Analysis/stack-block-returned.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -fblocks -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core -fblocks -verify %s typedef void (^bptr)(void); diff --git a/clang/test/Analysis/string-fail.c b/clang/test/Analysis/string-fail.c index ff95ea9ee28f8..b617812fa252f 100644 --- a/clang/test/Analysis/string-fail.c +++ b/clang/test/Analysis/string-fail.c @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s -// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,debug.ExprInspection -verify %s +// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,debug.ExprInspection -verify %s // XFAIL: * // This file is for tests that may eventually go into string.c, or may be diff --git a/clang/test/Analysis/svalbuilder-casts.cpp b/clang/test/Analysis/svalbuilder-casts.cpp new file mode 100644 index 0000000000000..4cee98927a2ce --- /dev/null +++ b/clang/test/Analysis/svalbuilder-casts.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_analyze_cc1 %s \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config support-symbolic-integer-casts=true \ +// RUN: -analyzer-config eagerly-assume=false \ +// RUN: -triple x86_64-unknown-linux-gnu \ +// RUN: -verify + +// Test that the SValBuilder is able to look up and use a constraint for an +// operand of a SymbolCast, when the operand is constrained to a const value. + +void clang_analyzer_eval(bool); + +extern void abort() __attribute__((__noreturn__)); +#define assert(expr) ((expr) ? (void)(0) : abort()) + +void test(int x) { + // Constrain a SymSymExpr to a constant value. + assert(x * x == 1); + // It is expected to be able to get the constraint for the operand of the + // cast. + clang_analyzer_eval((char)(x * x) == 1); // expected-warning{{TRUE}} + clang_analyzer_eval((long)(x * x) == 1); // expected-warning{{TRUE}} +} + +void test1(int x, int y) { + // Even if two lower bytes of `x` equal to zero, it doesn't mean that + // the entire `x` is zero. We are not able to know the exact value of x. + // It can be one of 65536 possible values like + // [0, 65536, -65536, 131072, -131072, ...]. To avoid huge range sets we + // still assume `x` in the range [INT_MIN, INT_MAX]. + assert((short)x == 0); // Lower two bytes are set to 0. + + static_assert((short)65536 == 0, ""); + static_assert((short)-65536 == 0, ""); + static_assert((short)131072 == 0, ""); + static_assert((short)-131072 == 0, ""); + clang_analyzer_eval(x == 0); // expected-warning{{UNKNOWN}} + + // These are not truncated to short as zero. + static_assert((short)1 != 0, ""); + clang_analyzer_eval(x == 1); // expected-warning{{FALSE}} + static_assert((short)-1 != 0, ""); + clang_analyzer_eval(x == -1); // expected-warning{{FALSE}} + static_assert((short)65537 != 0, ""); + clang_analyzer_eval(x == 65537); // expected-warning{{FALSE}} + static_assert((short)-65537 != 0, ""); + clang_analyzer_eval(x == -65537); // expected-warning{{FALSE}} + static_assert((short)131073 != 0, ""); + clang_analyzer_eval(x == 131073); // expected-warning{{FALSE}} + static_assert((short)-131073 != 0, ""); + clang_analyzer_eval(x == -131073); // expected-warning{{FALSE}} + + // Check for implicit cast. + short s = y; + assert(s == 0); + clang_analyzer_eval(y == 0); // expected-warning{{UNKNOWN}} +} diff --git a/clang/test/Analysis/svalbuilder-rearrange-comparisons.c b/clang/test/Analysis/svalbuilder-rearrange-comparisons.c deleted file mode 100644 index 32af8dde71c92..0000000000000 --- a/clang/test/Analysis/svalbuilder-rearrange-comparisons.c +++ /dev/null @@ -1,998 +0,0 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection,core.builtin -analyzer-config aggressive-binary-operation-simplification=true -verify -analyzer-config eagerly-assume=false %s - -void clang_analyzer_eval(int x); -void clang_analyzer_denote(int x, const char *literal); -void clang_analyzer_express(int x); - -void exit(int); - -#define UINT_MAX (~0U) -#define INT_MAX (UINT_MAX & (UINT_MAX >> 1)) - -extern void __assert_fail (__const char *__assertion, __const char *__file, - unsigned int __line, __const char *__function) - __attribute__ ((__noreturn__)); -#define assert(expr) \ - ((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__)) - -int g(void); -int f(void) { - int x = g(); - // Assert that no overflows occur in this test file. - // Assuming that concrete integers are also within that range. - assert(x <= ((int)INT_MAX / 4)); - assert(x >= -((int)INT_MAX / 4)); - return x; -} - -void compare_different_symbol_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - clang_analyzer_express(x == y); // expected-warning {{$x - $y == 0}} -} - -void compare_different_symbol_plus_left_int_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x += 1; - clang_analyzer_express(x == y); // expected-warning {{$y - $x == 1}} -} - -void compare_different_symbol_minus_left_int_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x -= 1; - clang_analyzer_express(x == y); // expected-warning {{$x - $y == 1}} -} - -void compare_different_symbol_plus_right_int_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - y += 2; - clang_analyzer_express(y); // expected-warning {{$y + 2}} - clang_analyzer_express(x == y); // expected-warning {{$x - $y == 2}} -} - -void compare_different_symbol_minus_right_int_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - y -= 2; - clang_analyzer_express(y); // expected-warning {{$y - 2}} - clang_analyzer_express(x == y); // expected-warning {{$y - $x == 2}} -} - -void compare_different_symbol_plus_left_plus_right_int_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x += 2; - y += 1; - clang_analyzer_express(x); // expected-warning {{$x + 2}} - clang_analyzer_express(y); // expected-warning {{$y + 1}} - clang_analyzer_express(x == y); // expected-warning {{$y - $x == 1}} -} - -void compare_different_symbol_plus_left_minus_right_int_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x += 2; - y -= 1; - clang_analyzer_express(x); // expected-warning {{$x + 2}} - clang_analyzer_express(y); // expected-warning {{$y - 1}} - clang_analyzer_express(x == y); // expected-warning {{$y - $x == 3}} -} - -void compare_different_symbol_minus_left_plus_right_int_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x -= 2; - y += 1; - clang_analyzer_express(x); // expected-warning {{$x - 2}} - clang_analyzer_express(y); // expected-warning {{$y + 1}} - clang_analyzer_express(x == y); // expected-warning {{$x - $y == 3}} -} - -void compare_different_symbol_minus_left_minus_right_int_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x -= 2; - y -= 1; - clang_analyzer_express(x); // expected-warning {{$x - 2}} - clang_analyzer_express(y); // expected-warning {{$y - 1}} - clang_analyzer_express(x == y); // expected-warning {{$x - $y == 1}} -} - -void compare_same_symbol_equal(void) { - int x = f(), y = x; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_eval(x == y); // expected-warning {{TRUE}} -} - -void compare_same_symbol_plus_left_int_equal(void) { - int x = f(), y = x; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_eval(x == y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_minus_left_int_equal(void) { - int x = f(), y = x; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_eval(x == y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_plus_right_int_equal(void) { - int x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_eval(x == y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_minus_right_int_equal(void) { - int x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_eval(x == y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_plus_left_plus_right_int_equal(void) { - int x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_eval(x == y); // expected-warning {{TRUE}} -} - -void compare_same_symbol_plus_left_minus_right_int_equal(void) { - int x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_eval(x == y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_minus_left_plus_right_int_equal(void) { - int x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_eval(x == y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_minus_left_minus_right_int_equal(void) { - int x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_eval(x == y); // expected-warning {{TRUE}} -} - -void compare_different_symbol_less_or_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 0}} -} - -void compare_different_symbol_plus_left_int_less_or_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x += 1; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 1}} -} - -void compare_different_symbol_minus_left_int_less_or_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x -= 1; - clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 1}} -} - -void compare_different_symbol_plus_right_int_less_or_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - y += 2; - clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 2}} -} - -void compare_different_symbol_minus_right_int_less_or_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - y -= 2; - clang_analyzer_express(y); // expected-warning {{$y - 2}} - clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 2}} -} - -void compare_different_symbol_plus_left_plus_right_int_less_or_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x += 2; - y += 1; - clang_analyzer_express(x); // expected-warning {{$x + 2}} - clang_analyzer_express(y); // expected-warning {{$y + 1}} - clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 1}} -} - -void compare_different_symbol_plus_left_minus_right_int_less_or_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x += 2; - y -= 1; - clang_analyzer_express(x); // expected-warning {{$x + 2}} - clang_analyzer_express(y); // expected-warning {{$y - 1}} - clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 3}} -} - -void compare_different_symbol_minus_left_plus_right_int_less_or_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x -= 2; - y += 1; - clang_analyzer_express(x); // expected-warning {{$x - 2}} - clang_analyzer_express(y); // expected-warning {{$y + 1}} - clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 3}} -} - -void compare_different_symbol_minus_left_minus_right_int_less_or_equal(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x -= 2; - y -= 1; - clang_analyzer_express(x); // expected-warning {{$x - 2}} - clang_analyzer_express(y); // expected-warning {{$y - 1}} - clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 1}} -} - -void compare_same_symbol_less_or_equal(void) { - int x = f(), y = x; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} -} - -void compare_same_symbol_plus_left_int_less_or_equal(void) { - int x = f(), y = x; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_eval(x <= y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_minus_left_int_less_or_equal(void) { - int x = f(), y = x; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} -} - -void compare_same_symbol_plus_right_int_less_or_equal(void) { - int x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} -} - -void compare_same_symbol_minus_right_int_less_or_equal(void) { - int x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_eval(x <= y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_plus_left_plus_right_int_less_or_equal(void) { - int x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} -} - -void compare_same_symbol_plus_left_minus_right_int_less_or_equal(void) { - int x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_eval(x <= y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_minus_left_plus_right_int_less_or_equal(void) { - int x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} -} - -void compare_same_symbol_minus_left_minus_right_int_less_or_equal(void) { - int x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} -} - -void compare_different_symbol_less(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - clang_analyzer_express(y); // expected-warning {{$y}} - clang_analyzer_express(x < y); // expected-warning {{$x - $y < 0}} -} - -void compare_different_symbol_plus_left_int_less(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x += 1; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$y}} - clang_analyzer_express(x < y); // expected-warning {{$y - $x > 1}} -} - -void compare_different_symbol_minus_left_int_less(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x -= 1; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$y}} - clang_analyzer_express(x < y); // expected-warning {{$x - $y < 1}} -} - -void compare_different_symbol_plus_right_int_less(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - y += 2; - clang_analyzer_express(y); // expected-warning {{$y + 2}} - clang_analyzer_express(x < y); // expected-warning {{$x - $y < 2}} -} - -void compare_different_symbol_minus_right_int_less(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - y -= 2; - clang_analyzer_express(y); // expected-warning {{$y - 2}} - clang_analyzer_express(x < y); // expected-warning {{$y - $x > 2}} -} - -void compare_different_symbol_plus_left_plus_right_int_less(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x += 2; - y += 1; - clang_analyzer_express(x); // expected-warning {{$x + 2}} - clang_analyzer_express(y); // expected-warning {{$y + 1}} - clang_analyzer_express(x < y); // expected-warning {{$y - $x > 1}} -} - -void compare_different_symbol_plus_left_minus_right_int_less(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x += 2; - y -= 1; - clang_analyzer_express(x); // expected-warning {{$x + 2}} - clang_analyzer_express(y); // expected-warning {{$y - 1}} - clang_analyzer_express(x < y); // expected-warning {{$y - $x > 3}} -} - -void compare_different_symbol_minus_left_plus_right_int_less(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x -= 2; - y += 1; - clang_analyzer_express(x); // expected-warning {{$x - 2}} - clang_analyzer_express(y); // expected-warning {{$y + 1}} - clang_analyzer_express(x < y); // expected-warning {{$x - $y < 3}} -} - -void compare_different_symbol_minus_left_minus_right_int_less(void) { - int x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - x -= 2; - y -= 1; - clang_analyzer_express(x); // expected-warning {{$x - 2}} - clang_analyzer_express(y); // expected-warning {{$y - 1}} - clang_analyzer_express(x < y); // expected-warning {{$x - $y < 1}} -} - -void compare_same_symbol_less(void) { - int x = f(), y = x; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_eval(x < y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_plus_left_int_less(void) { - int x = f(), y = x; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_eval(x < y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_minus_left_int_less(void) { - int x = f(), y = x; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_eval(x < y); // expected-warning {{TRUE}} -} - -void compare_same_symbol_plus_right_int_less(void) { - int x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_eval(x < y); // expected-warning {{TRUE}} -} - -void compare_same_symbol_minus_right_int_less(void) { - int x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_eval(x < y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_plus_left_plus_right_int_less(void) { - int x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_eval(x < y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_plus_left_minus_right_int_less(void) { - int x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_eval(x < y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_minus_left_plus_right_int_less(void) { - int x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_eval(x < y); // expected-warning {{TRUE}} -} - -void compare_same_symbol_minus_left_minus_right_int_less(void) { - int x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_eval(x < y); // expected-warning {{FALSE}} -} - -void compare_different_symbol_equal_unsigned(void) { - unsigned x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - clang_analyzer_express(y); // expected-warning {{$y}} - clang_analyzer_express(x == y); // expected-warning {{$x - $y == 0}} -} - -void compare_different_symbol_plus_left_int_equal_unsigned(void) { - unsigned x = f() + 1, y = f(); - clang_analyzer_denote(x - 1, "$x"); - clang_analyzer_denote(y, "$y"); - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$y}} - clang_analyzer_express(x == y); // expected-warning {{$y - $x == 1}} -} - -void compare_different_symbol_minus_left_int_equal_unsigned(void) { - unsigned x = f() - 1, y = f(); - clang_analyzer_denote(x + 1, "$x"); - clang_analyzer_denote(y, "$y"); - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$y}} - clang_analyzer_express(x == y); // expected-warning {{$x - $y == 1}} -} - -void compare_different_symbol_plus_right_int_equal_unsigned(void) { - unsigned x = f(), y = f() + 2; - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y - 2, "$y"); - clang_analyzer_express(y); // expected-warning {{$y + 2}} - clang_analyzer_express(x == y); // expected-warning {{$x - $y == 2}} -} - -void compare_different_symbol_minus_right_int_equal_unsigned(void) { - unsigned x = f(), y = f() - 2; - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y + 2, "$y"); - clang_analyzer_express(y); // expected-warning {{$y - 2}} - clang_analyzer_express(x == y); // expected-warning {{$y - $x == 2}} -} - -void compare_different_symbol_plus_left_plus_right_int_equal_unsigned(void) { - unsigned x = f() + 2, y = f() + 1; - clang_analyzer_denote(x - 2, "$x"); - clang_analyzer_denote(y - 1, "$y"); - clang_analyzer_express(x); // expected-warning {{$x + 2}} - clang_analyzer_express(y); // expected-warning {{$y + 1}} - clang_analyzer_express(x == y); // expected-warning {{$y - $x == 1}} -} - -void compare_different_symbol_plus_left_minus_right_int_equal_unsigned(void) { - unsigned x = f() + 2, y = f() - 1; - clang_analyzer_denote(x - 2, "$x"); - clang_analyzer_denote(y + 1, "$y"); - clang_analyzer_express(x); // expected-warning {{$x + 2}} - clang_analyzer_express(y); // expected-warning {{$y - 1}} - clang_analyzer_express(x == y); // expected-warning {{$y - $x == 3}} -} - -void compare_different_symbol_minus_left_plus_right_int_equal_unsigned(void) { - unsigned x = f() - 2, y = f() + 1; - clang_analyzer_denote(x + 2, "$x"); - clang_analyzer_denote(y - 1, "$y"); - clang_analyzer_express(x); // expected-warning {{$x - 2}} - clang_analyzer_express(y); // expected-warning {{$y + 1}} - clang_analyzer_express(x == y); // expected-warning {{$x - $y == 3}} -} - -void compare_different_symbol_minus_left_minus_right_int_equal_unsigned(void) { - unsigned x = f() - 2, y = f() - 1; - clang_analyzer_denote(x + 2, "$x"); - clang_analyzer_denote(y + 1, "$y"); - clang_analyzer_express(x); // expected-warning {{$x - 2}} - clang_analyzer_express(y); // expected-warning {{$y - 1}} - clang_analyzer_express(x == y); // expected-warning {{$x - $y == 1}} -} - -void compare_same_symbol_equal_unsigned(void) { - unsigned x = f(), y = x; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_eval(x == y); // expected-warning {{TRUE}} -} - -void compare_same_symbol_plus_left_int_equal_unsigned(void) { - unsigned x = f(), y = x; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_express(x == y); // expected-warning {{$x + 1U == $x}} -} - -void compare_same_symbol_minus_left_int_equal_unsigned(void) { - unsigned x = f(), y = x; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_express(x == y); // expected-warning {{$x - 1U == $x}} -} - -void compare_same_symbol_plus_right_int_equal_unsigned(void) { - unsigned x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_express(x == y); // expected-warning {{$x == $x + 1U}} -} - -void compare_same_symbol_minus_right_int_equal_unsigned(void) { - unsigned x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_express(x == y); // expected-warning {{$x == $x - 1U}} -} - -void compare_same_symbol_plus_left_plus_right_int_equal_unsigned(void) { - unsigned x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_eval(x == y); // expected-warning {{TRUE}} -} - -void compare_same_symbol_plus_left_minus_right_int_equal_unsigned(void) { - unsigned x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_express(x == y); // expected-warning {{$x + 1U == $x - 1U}} -} - -void compare_same_symbol_minus_left_plus_right_int_equal_unsigned(void) { - unsigned x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_express(x == y); // expected-warning {{$x - 1U == $x + 1U}} -} - -void compare_same_symbol_minus_left_minus_right_int_equal_unsigned(void) { - unsigned x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_eval(x == y); // expected-warning {{TRUE}} -} - -void compare_different_symbol_less_or_equal_unsigned(void) { - unsigned x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - clang_analyzer_express(y); // expected-warning {{$y}} - clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 0}} -} - -void compare_different_symbol_plus_left_int_less_or_equal_unsigned(void) { - unsigned x = f() + 1, y = f(); - clang_analyzer_denote(x - 1, "$x"); - clang_analyzer_denote(y, "$y"); - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$y}} - clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 1}} -} - -void compare_different_symbol_minus_left_int_less_or_equal_unsigned(void) { - unsigned x = f() - 1, y = f(); - clang_analyzer_denote(x + 1, "$x"); - clang_analyzer_denote(y, "$y"); - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$y}} - clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 1}} -} - -void compare_different_symbol_plus_right_int_less_or_equal_unsigned(void) { - unsigned x = f(), y = f() + 2; - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y - 2, "$y"); - clang_analyzer_express(y); // expected-warning {{$y + 2}} - clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 2}} -} - -void compare_different_symbol_minus_right_int_less_or_equal_unsigned(void) { - unsigned x = f(), y = f() - 2; - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y + 2, "$y"); - clang_analyzer_express(y); // expected-warning {{$y - 2}} - clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 2}} -} - -void compare_different_symbol_plus_left_plus_right_int_less_or_equal_unsigned(void) { - unsigned x = f() + 2, y = f() + 1; - clang_analyzer_denote(x - 2, "$x"); - clang_analyzer_denote(y - 1, "$y"); - clang_analyzer_express(x); // expected-warning {{$x + 2}} - clang_analyzer_express(y); // expected-warning {{$y + 1}} - clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 1}} -} - -void compare_different_symbol_plus_left_minus_right_int_less_or_equal_unsigned(void) { - unsigned x = f() + 2, y = f() - 1; - clang_analyzer_denote(x - 2, "$x"); - clang_analyzer_denote(y + 1, "$y"); - clang_analyzer_express(x); // expected-warning {{$x + 2}} - clang_analyzer_express(y); // expected-warning {{$y - 1}} - clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 3}} -} - -void compare_different_symbol_minus_left_plus_right_int_less_or_equal_unsigned(void) { - unsigned x = f() - 2, y = f() + 1; - clang_analyzer_denote(x + 2, "$x"); - clang_analyzer_denote(y - 1, "$y"); - clang_analyzer_express(x); // expected-warning {{$x - 2}} - clang_analyzer_express(y); // expected-warning {{$y + 1}} - clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 3}} -} - -void compare_different_symbol_minus_left_minus_right_int_less_or_equal_unsigned(void) { - unsigned x = f() - 2, y = f() - 1; - clang_analyzer_denote(x + 2, "$x"); - clang_analyzer_denote(y + 1, "$y"); - clang_analyzer_express(x); // expected-warning {{$x - 2}} - clang_analyzer_express(y); // expected-warning {{$y - 1}} - clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 1}} -} - -void compare_same_symbol_less_or_equal_unsigned(void) { - unsigned x = f(), y = x; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} -} - -void compare_same_symbol_plus_left_int_less_or_equal_unsigned(void) { - unsigned x = f(), y = x; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_express(x <= y); // expected-warning {{$x + 1U <= $x}} -} - -void compare_same_symbol_minus_left_int_less_or_equal_unsigned(void) { - unsigned x = f(), y = x; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_express(x <= y); // expected-warning {{$x - 1U <= $x}} -} - -void compare_same_symbol_plus_right_int_less_or_equal_unsigned(void) { - unsigned x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_express(x <= y); // expected-warning {{$x <= $x + 1U}} -} - -void compare_same_symbol_minus_right_int_less_or_equal_unsigned(void) { - unsigned x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_express(x <= y); // expected-warning {{$x <= $x - 1U}} -} - -void compare_same_symbol_plus_left_plus_right_int_less_or_equal_unsigned(void) { - unsigned x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} -} - -void compare_same_symbol_plus_left_minus_right_int_less_or_equal_unsigned(void) { - unsigned x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_express(x <= y); // expected-warning {{$x + 1U <= $x - 1U}} -} - -void compare_same_symbol_minus_left_plus_right_int_less_or_equal_unsigned(void) { - unsigned x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_express(x <= y); // expected-warning {{$x - 1U <= $x + 1U}} -} - -void compare_same_symbol_minus_left_minus_right_int_less_or_equal_unsigned(void) { - unsigned x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} -} - -void compare_different_symbol_less_unsigned(void) { - unsigned x = f(), y = f(); - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y, "$y"); - clang_analyzer_express(y); // expected-warning {{$y}} - clang_analyzer_express(x < y); // expected-warning {{$x - $y < 0}} -} - -void compare_different_symbol_plus_left_int_less_unsigned(void) { - unsigned x = f() + 1, y = f(); - clang_analyzer_denote(x - 1, "$x"); - clang_analyzer_denote(y, "$y"); - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$y}} - clang_analyzer_express(x < y); // expected-warning {{$y - $x > 1}} -} - -void compare_different_symbol_minus_left_int_less_unsigned(void) { - unsigned x = f() - 1, y = f(); - clang_analyzer_denote(x + 1, "$x"); - clang_analyzer_denote(y, "$y"); - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$y}} - clang_analyzer_express(x < y); // expected-warning {{$x - $y < 1}} -} - -void compare_different_symbol_plus_right_int_less_unsigned(void) { - unsigned x = f(), y = f() + 2; - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y - 2, "$y"); - clang_analyzer_express(y); // expected-warning {{$y + 2}} - clang_analyzer_express(x < y); // expected-warning {{$x - $y < 2}} -} - -void compare_different_symbol_minus_right_int_less_unsigned(void) { - unsigned x = f(), y = f() - 2; - clang_analyzer_denote(x, "$x"); - clang_analyzer_denote(y + 2, "$y"); - clang_analyzer_express(y); // expected-warning {{$y - 2}} - clang_analyzer_express(x < y); // expected-warning {{$y - $x > 2}} -} - -void compare_different_symbol_plus_left_plus_right_int_less_unsigned(void) { - unsigned x = f() + 2, y = f() + 1; - clang_analyzer_denote(x - 2, "$x"); - clang_analyzer_denote(y - 1, "$y"); - clang_analyzer_express(x); // expected-warning {{$x + 2}} - clang_analyzer_express(y); // expected-warning {{$y + 1}} - clang_analyzer_express(x < y); // expected-warning {{$y - $x > 1}} -} - -void compare_different_symbol_plus_left_minus_right_int_less_unsigned(void) { - unsigned x = f() + 2, y = f() - 1; - clang_analyzer_denote(x - 2, "$x"); - clang_analyzer_denote(y + 1, "$y"); - clang_analyzer_express(x); // expected-warning {{$x + 2}} - clang_analyzer_express(y); // expected-warning {{$y - 1}} - clang_analyzer_express(x < y); // expected-warning {{$y - $x > 3}} -} - -void compare_different_symbol_minus_left_plus_right_int_less_unsigned(void) { - unsigned x = f() - 2, y = f() + 1; - clang_analyzer_denote(x + 2, "$x"); - clang_analyzer_denote(y - 1, "$y"); - clang_analyzer_express(x); // expected-warning {{$x - 2}} - clang_analyzer_express(y); // expected-warning {{$y + 1}} - clang_analyzer_express(x < y); // expected-warning {{$x - $y < 3}} -} - -void compare_different_symbol_minus_left_minus_right_int_less_unsigned(void) { - unsigned x = f() - 2, y = f() - 1; - clang_analyzer_denote(x + 2, "$x"); - clang_analyzer_denote(y + 1, "$y"); - clang_analyzer_express(x); // expected-warning {{$x - 2}} - clang_analyzer_express(y); // expected-warning {{$y - 1}} - clang_analyzer_express(x < y); // expected-warning {{$x - $y < 1}} -} - -void compare_same_symbol_less_unsigned(void) { - unsigned x = f(), y = x; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_eval(x < y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_plus_left_int_less_unsigned(void) { - unsigned x = f(), y = x; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_express(x < y); // expected-warning {{$x + 1U < $x}} -} - -void compare_same_symbol_minus_left_int_less_unsigned(void) { - unsigned x = f(), y = x; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x}} - clang_analyzer_express(x < y); // expected-warning {{$x - 1U < $x}} -} - -void compare_same_symbol_plus_right_int_less_unsigned(void) { - unsigned x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_express(x < y); // expected-warning {{$x < $x + 1U}} -} - -void compare_same_symbol_minus_right_int_less_unsigned(void) { - unsigned x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_express(x < y); // expected-warning {{$x < $x - 1U}} -} - -void compare_same_symbol_plus_left_plus_right_int_less_unsigned(void) { - unsigned x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_eval(x < y); // expected-warning {{FALSE}} -} - -void compare_same_symbol_plus_left_minus_right_int_less_unsigned(void) { - unsigned x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - ++x; - clang_analyzer_express(x); // expected-warning {{$x + 1}} - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_express(x < y); // expected-warning {{$x + 1U < $x - 1U}} -} - -void compare_same_symbol_minus_left_plus_right_int_less_unsigned(void) { - unsigned x = f(), y = x + 1; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x + 1}} - clang_analyzer_express(x < y); // expected-warning {{$x - 1U < $x + 1U}} -} - -void compare_same_symbol_minus_left_minus_right_int_less_unsigned(void) { - unsigned x = f(), y = x - 1; - clang_analyzer_denote(x, "$x"); - --x; - clang_analyzer_express(x); // expected-warning {{$x - 1}} - clang_analyzer_express(y); // expected-warning {{$x - 1}} - clang_analyzer_eval(x < y); // expected-warning {{FALSE}} -} - -void overflow(signed char n, signed char m) { - if (n + 0 > m + 0) { - clang_analyzer_eval(n - 126 == m + 3); // expected-warning {{UNKNOWN}} - } -} - -int mixed_integer_types(int x, int y) { - short a = x - 1U; - return a - y; -} - -unsigned gu(void); -unsigned fu(void) { - unsigned x = gu(); - // Assert that no overflows occur in this test file. - // Assuming that concrete integers are also within that range. - assert(x <= ((unsigned)UINT_MAX / 4)); - return x; -} - -void unsigned_concrete_int_no_crash(void) { - unsigned x = fu() + 1U, y = fu() + 1U; - clang_analyzer_denote(x - 1U, "$x"); - clang_analyzer_denote(y - 1U, "$y"); - clang_analyzer_express(y); // expected-warning {{$y}} - clang_analyzer_express(x == y); // expected-warning {{$x + 1U == $y + 1U}} -} diff --git a/clang/test/Analysis/svalbuilder-rearrange-comparisons.cpp b/clang/test/Analysis/svalbuilder-rearrange-comparisons.cpp new file mode 100644 index 0000000000000..06a5c7c41169b --- /dev/null +++ b/clang/test/Analysis/svalbuilder-rearrange-comparisons.cpp @@ -0,0 +1,1028 @@ +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=debug.ExprInspection,core.builtin \ +// RUN: -analyzer-config aggressive-binary-operation-simplification=true \ +// RUN: -analyzer-config support-symbolic-integer-casts=false \ +// RUN: -analyzer-config eagerly-assume=false \ +// RUN: -verify %s + +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=debug.ExprInspection,core.builtin \ +// RUN: -analyzer-config aggressive-binary-operation-simplification=true \ +// RUN: -analyzer-config support-symbolic-integer-casts=true \ +// RUN: -DSUPPORT_SYMBOLIC_INTEGER_CASTS \ +// RUN: -analyzer-config eagerly-assume=false \ +// RUN: -verify %s + +void clang_analyzer_eval(bool x); +template +void clang_analyzer_denote(T x, const char *literal); +template +void clang_analyzer_express(T x); + +void exit(int); + +#define UINT_MAX (~0U) +#define INT_MAX (UINT_MAX & (UINT_MAX >> 1)) + +extern void __assert_fail (__const char *__assertion, __const char *__file, + unsigned int __line, __const char *__function) + __attribute__ ((__noreturn__)); +#define assert(expr) \ + ((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__)) + +int g(void); +int f(void) { + int x = g(); + // Assert that no overflows occur in this test file. + // Assuming that concrete integers are also within that range. + assert(x <= ((int)INT_MAX / 4)); + assert(x >= -((int)INT_MAX / 4)); + return x; +} + +void compare_different_symbol_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + clang_analyzer_express(x == y); // expected-warning {{$x - $y == 0}} +} + +void compare_different_symbol_plus_left_int_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x += 1; + clang_analyzer_express(x == y); // expected-warning {{$y - $x == 1}} +} + +void compare_different_symbol_minus_left_int_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x -= 1; + clang_analyzer_express(x == y); // expected-warning {{$x - $y == 1}} +} + +void compare_different_symbol_plus_right_int_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + y += 2; + clang_analyzer_express(y); // expected-warning {{$y + 2}} + clang_analyzer_express(x == y); // expected-warning {{$x - $y == 2}} +} + +void compare_different_symbol_minus_right_int_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + y -= 2; + clang_analyzer_express(y); // expected-warning {{$y - 2}} + clang_analyzer_express(x == y); // expected-warning {{$y - $x == 2}} +} + +void compare_different_symbol_plus_left_plus_right_int_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x += 2; + y += 1; + clang_analyzer_express(x); // expected-warning {{$x + 2}} + clang_analyzer_express(y); // expected-warning {{$y + 1}} + clang_analyzer_express(x == y); // expected-warning {{$y - $x == 1}} +} + +void compare_different_symbol_plus_left_minus_right_int_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x += 2; + y -= 1; + clang_analyzer_express(x); // expected-warning {{$x + 2}} + clang_analyzer_express(y); // expected-warning {{$y - 1}} + clang_analyzer_express(x == y); // expected-warning {{$y - $x == 3}} +} + +void compare_different_symbol_minus_left_plus_right_int_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x -= 2; + y += 1; + clang_analyzer_express(x); // expected-warning {{$x - 2}} + clang_analyzer_express(y); // expected-warning {{$y + 1}} + clang_analyzer_express(x == y); // expected-warning {{$x - $y == 3}} +} + +void compare_different_symbol_minus_left_minus_right_int_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x -= 2; + y -= 1; + clang_analyzer_express(x); // expected-warning {{$x - 2}} + clang_analyzer_express(y); // expected-warning {{$y - 1}} + clang_analyzer_express(x == y); // expected-warning {{$x - $y == 1}} +} + +void compare_same_symbol_equal(void) { + int x = f(), y = x; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_eval(x == y); // expected-warning {{TRUE}} +} + +void compare_same_symbol_plus_left_int_equal(void) { + int x = f(), y = x; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_eval(x == y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_minus_left_int_equal(void) { + int x = f(), y = x; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_eval(x == y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_plus_right_int_equal(void) { + int x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_eval(x == y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_minus_right_int_equal(void) { + int x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_eval(x == y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_plus_left_plus_right_int_equal(void) { + int x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_eval(x == y); // expected-warning {{TRUE}} +} + +void compare_same_symbol_plus_left_minus_right_int_equal(void) { + int x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_eval(x == y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_minus_left_plus_right_int_equal(void) { + int x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_eval(x == y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_minus_left_minus_right_int_equal(void) { + int x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_eval(x == y); // expected-warning {{TRUE}} +} + +void compare_different_symbol_less_or_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 0}} +} + +void compare_different_symbol_plus_left_int_less_or_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x += 1; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 1}} +} + +void compare_different_symbol_minus_left_int_less_or_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x -= 1; + clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 1}} +} + +void compare_different_symbol_plus_right_int_less_or_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + y += 2; + clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 2}} +} + +void compare_different_symbol_minus_right_int_less_or_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + y -= 2; + clang_analyzer_express(y); // expected-warning {{$y - 2}} + clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 2}} +} + +void compare_different_symbol_plus_left_plus_right_int_less_or_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x += 2; + y += 1; + clang_analyzer_express(x); // expected-warning {{$x + 2}} + clang_analyzer_express(y); // expected-warning {{$y + 1}} + clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 1}} +} + +void compare_different_symbol_plus_left_minus_right_int_less_or_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x += 2; + y -= 1; + clang_analyzer_express(x); // expected-warning {{$x + 2}} + clang_analyzer_express(y); // expected-warning {{$y - 1}} + clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 3}} +} + +void compare_different_symbol_minus_left_plus_right_int_less_or_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x -= 2; + y += 1; + clang_analyzer_express(x); // expected-warning {{$x - 2}} + clang_analyzer_express(y); // expected-warning {{$y + 1}} + clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 3}} +} + +void compare_different_symbol_minus_left_minus_right_int_less_or_equal(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x -= 2; + y -= 1; + clang_analyzer_express(x); // expected-warning {{$x - 2}} + clang_analyzer_express(y); // expected-warning {{$y - 1}} + clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 1}} +} + +void compare_same_symbol_less_or_equal(void) { + int x = f(), y = x; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} +} + +void compare_same_symbol_plus_left_int_less_or_equal(void) { + int x = f(), y = x; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_eval(x <= y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_minus_left_int_less_or_equal(void) { + int x = f(), y = x; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} +} + +void compare_same_symbol_plus_right_int_less_or_equal(void) { + int x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} +} + +void compare_same_symbol_minus_right_int_less_or_equal(void) { + int x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_eval(x <= y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_plus_left_plus_right_int_less_or_equal(void) { + int x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} +} + +void compare_same_symbol_plus_left_minus_right_int_less_or_equal(void) { + int x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_eval(x <= y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_minus_left_plus_right_int_less_or_equal(void) { + int x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} +} + +void compare_same_symbol_minus_left_minus_right_int_less_or_equal(void) { + int x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} +} + +void compare_different_symbol_less(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + clang_analyzer_express(y); // expected-warning {{$y}} + clang_analyzer_express(x < y); // expected-warning {{$x - $y < 0}} +} + +void compare_different_symbol_plus_left_int_less(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x += 1; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$y}} + clang_analyzer_express(x < y); // expected-warning {{$y - $x > 1}} +} + +void compare_different_symbol_minus_left_int_less(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x -= 1; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$y}} + clang_analyzer_express(x < y); // expected-warning {{$x - $y < 1}} +} + +void compare_different_symbol_plus_right_int_less(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + y += 2; + clang_analyzer_express(y); // expected-warning {{$y + 2}} + clang_analyzer_express(x < y); // expected-warning {{$x - $y < 2}} +} + +void compare_different_symbol_minus_right_int_less(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + y -= 2; + clang_analyzer_express(y); // expected-warning {{$y - 2}} + clang_analyzer_express(x < y); // expected-warning {{$y - $x > 2}} +} + +void compare_different_symbol_plus_left_plus_right_int_less(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x += 2; + y += 1; + clang_analyzer_express(x); // expected-warning {{$x + 2}} + clang_analyzer_express(y); // expected-warning {{$y + 1}} + clang_analyzer_express(x < y); // expected-warning {{$y - $x > 1}} +} + +void compare_different_symbol_plus_left_minus_right_int_less(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x += 2; + y -= 1; + clang_analyzer_express(x); // expected-warning {{$x + 2}} + clang_analyzer_express(y); // expected-warning {{$y - 1}} + clang_analyzer_express(x < y); // expected-warning {{$y - $x > 3}} +} + +void compare_different_symbol_minus_left_plus_right_int_less(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x -= 2; + y += 1; + clang_analyzer_express(x); // expected-warning {{$x - 2}} + clang_analyzer_express(y); // expected-warning {{$y + 1}} + clang_analyzer_express(x < y); // expected-warning {{$x - $y < 3}} +} + +void compare_different_symbol_minus_left_minus_right_int_less(void) { + int x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + x -= 2; + y -= 1; + clang_analyzer_express(x); // expected-warning {{$x - 2}} + clang_analyzer_express(y); // expected-warning {{$y - 1}} + clang_analyzer_express(x < y); // expected-warning {{$x - $y < 1}} +} + +void compare_same_symbol_less(void) { + int x = f(), y = x; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_eval(x < y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_plus_left_int_less(void) { + int x = f(), y = x; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_eval(x < y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_minus_left_int_less(void) { + int x = f(), y = x; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_eval(x < y); // expected-warning {{TRUE}} +} + +void compare_same_symbol_plus_right_int_less(void) { + int x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_eval(x < y); // expected-warning {{TRUE}} +} + +void compare_same_symbol_minus_right_int_less(void) { + int x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_eval(x < y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_plus_left_plus_right_int_less(void) { + int x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_eval(x < y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_plus_left_minus_right_int_less(void) { + int x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_eval(x < y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_minus_left_plus_right_int_less(void) { + int x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_eval(x < y); // expected-warning {{TRUE}} +} + +void compare_same_symbol_minus_left_minus_right_int_less(void) { + int x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_eval(x < y); // expected-warning {{FALSE}} +} + +// Rearrange should happen on signed types only (tryRearrange): +// +// // Rearrange signed symbolic expressions only +// if (!SingleTy->isSignedIntegerOrEnumerationType()) +// return None; +// +// Without the symbolic casts, the SVal for `x` in `unsigned x = f()` will be +// the signed `int`. However, with the symbolic casts it will be `unsigned`. +// Thus, these tests are meaningful only if the cast is not emitted. +#ifndef SUPPORT_SYMBOLIC_INTEGER_CASTS + +void compare_different_symbol_equal_unsigned(void) { + unsigned x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + clang_analyzer_express(y); // expected-warning {{$y}} + clang_analyzer_express(x == y); // expected-warning {{$x - $y == 0}} +} + +void compare_different_symbol_plus_left_int_equal_unsigned(void) { + unsigned x = f() + 1, y = f(); + clang_analyzer_denote(x - 1, "$x"); + clang_analyzer_denote(y, "$y"); + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$y}} + clang_analyzer_express(x == y); // expected-warning {{$y - $x == 1}} +} + +void compare_different_symbol_minus_left_int_equal_unsigned(void) { + unsigned x = f() - 1, y = f(); + clang_analyzer_denote(x + 1, "$x"); + clang_analyzer_denote(y, "$y"); + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$y}} + clang_analyzer_express(x == y); // expected-warning {{$x - $y == 1}} +} + +void compare_different_symbol_plus_right_int_equal_unsigned(void) { + unsigned x = f(), y = f() + 2; + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y - 2, "$y"); + clang_analyzer_express(y); // expected-warning {{$y + 2}} + clang_analyzer_express(x == y); // expected-warning {{$x - $y == 2}} +} + +void compare_different_symbol_minus_right_int_equal_unsigned(void) { + unsigned x = f(), y = f() - 2; + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y + 2, "$y"); + clang_analyzer_express(y); // expected-warning {{$y - 2}} + clang_analyzer_express(x == y); // expected-warning {{$y - $x == 2}} +} + +void compare_different_symbol_plus_left_plus_right_int_equal_unsigned(void) { + unsigned x = f() + 2, y = f() + 1; + clang_analyzer_denote(x - 2, "$x"); + clang_analyzer_denote(y - 1, "$y"); + clang_analyzer_express(x); // expected-warning {{$x + 2}} + clang_analyzer_express(y); // expected-warning {{$y + 1}} + clang_analyzer_express(x == y); // expected-warning {{$y - $x == 1}} +} + +void compare_different_symbol_plus_left_minus_right_int_equal_unsigned(void) { + unsigned x = f() + 2, y = f() - 1; + clang_analyzer_denote(x - 2, "$x"); + clang_analyzer_denote(y + 1, "$y"); + clang_analyzer_express(x); // expected-warning {{$x + 2}} + clang_analyzer_express(y); // expected-warning {{$y - 1}} + clang_analyzer_express(x == y); // expected-warning {{$y - $x == 3}} +} + +void compare_different_symbol_minus_left_plus_right_int_equal_unsigned(void) { + unsigned x = f() - 2, y = f() + 1; + clang_analyzer_denote(x + 2, "$x"); + clang_analyzer_denote(y - 1, "$y"); + clang_analyzer_express(x); // expected-warning {{$x - 2}} + clang_analyzer_express(y); // expected-warning {{$y + 1}} + clang_analyzer_express(x == y); // expected-warning {{$x - $y == 3}} +} + +void compare_different_symbol_minus_left_minus_right_int_equal_unsigned(void) { + unsigned x = f() - 2, y = f() - 1; + clang_analyzer_denote(x + 2, "$x"); + clang_analyzer_denote(y + 1, "$y"); + clang_analyzer_express(x); // expected-warning {{$x - 2}} + clang_analyzer_express(y); // expected-warning {{$y - 1}} + clang_analyzer_express(x == y); // expected-warning {{$x - $y == 1}} +} + +void compare_same_symbol_equal_unsigned(void) { + unsigned x = f(), y = x; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_eval(x == y); // expected-warning {{TRUE}} +} + +void compare_same_symbol_plus_left_int_equal_unsigned(void) { + unsigned x = f(), y = x; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_express(x == y); // expected-warning {{$x + 1U == $x}} +} + +void compare_same_symbol_minus_left_int_equal_unsigned(void) { + unsigned x = f(), y = x; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_express(x == y); // expected-warning {{$x - 1U == $x}} +} + +void compare_same_symbol_plus_right_int_equal_unsigned(void) { + unsigned x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_express(x == y); // expected-warning {{$x == $x + 1U}} +} + +void compare_same_symbol_minus_right_int_equal_unsigned(void) { + unsigned x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_express(x == y); // expected-warning {{$x == $x - 1U}} +} + +void compare_same_symbol_plus_left_plus_right_int_equal_unsigned(void) { + unsigned x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_eval(x == y); // expected-warning {{TRUE}} +} + +void compare_same_symbol_plus_left_minus_right_int_equal_unsigned(void) { + unsigned x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_express(x == y); // expected-warning {{$x + 1U == $x - 1U}} +} + +void compare_same_symbol_minus_left_plus_right_int_equal_unsigned(void) { + unsigned x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_express(x == y); // expected-warning {{$x - 1U == $x + 1U}} +} + +void compare_same_symbol_minus_left_minus_right_int_equal_unsigned(void) { + unsigned x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_eval(x == y); // expected-warning {{TRUE}} +} + +void compare_different_symbol_less_or_equal_unsigned(void) { + unsigned x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + clang_analyzer_express(y); // expected-warning {{$y}} + clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 0}} +} + +void compare_different_symbol_plus_left_int_less_or_equal_unsigned(void) { + unsigned x = f() + 1, y = f(); + clang_analyzer_denote(x - 1, "$x"); + clang_analyzer_denote(y, "$y"); + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$y}} + clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 1}} +} + +void compare_different_symbol_minus_left_int_less_or_equal_unsigned(void) { + unsigned x = f() - 1, y = f(); + clang_analyzer_denote(x + 1, "$x"); + clang_analyzer_denote(y, "$y"); + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$y}} + clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 1}} +} + +void compare_different_symbol_plus_right_int_less_or_equal_unsigned(void) { + unsigned x = f(), y = f() + 2; + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y - 2, "$y"); + clang_analyzer_express(y); // expected-warning {{$y + 2}} + clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 2}} +} + +void compare_different_symbol_minus_right_int_less_or_equal_unsigned(void) { + unsigned x = f(), y = f() - 2; + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y + 2, "$y"); + clang_analyzer_express(y); // expected-warning {{$y - 2}} + clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 2}} +} + +void compare_different_symbol_plus_left_plus_right_int_less_or_equal_unsigned(void) { + unsigned x = f() + 2, y = f() + 1; + clang_analyzer_denote(x - 2, "$x"); + clang_analyzer_denote(y - 1, "$y"); + clang_analyzer_express(x); // expected-warning {{$x + 2}} + clang_analyzer_express(y); // expected-warning {{$y + 1}} + clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 1}} +} + +void compare_different_symbol_plus_left_minus_right_int_less_or_equal_unsigned(void) { + unsigned x = f() + 2, y = f() - 1; + clang_analyzer_denote(x - 2, "$x"); + clang_analyzer_denote(y + 1, "$y"); + clang_analyzer_express(x); // expected-warning {{$x + 2}} + clang_analyzer_express(y); // expected-warning {{$y - 1}} + clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 3}} +} + +void compare_different_symbol_minus_left_plus_right_int_less_or_equal_unsigned(void) { + unsigned x = f() - 2, y = f() + 1; + clang_analyzer_denote(x + 2, "$x"); + clang_analyzer_denote(y - 1, "$y"); + clang_analyzer_express(x); // expected-warning {{$x - 2}} + clang_analyzer_express(y); // expected-warning {{$y + 1}} + clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 3}} +} + +void compare_different_symbol_minus_left_minus_right_int_less_or_equal_unsigned(void) { + unsigned x = f() - 2, y = f() - 1; + clang_analyzer_denote(x + 2, "$x"); + clang_analyzer_denote(y + 1, "$y"); + clang_analyzer_express(x); // expected-warning {{$x - 2}} + clang_analyzer_express(y); // expected-warning {{$y - 1}} + clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 1}} +} + +void compare_same_symbol_less_or_equal_unsigned(void) { + unsigned x = f(), y = x; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} +} + +void compare_same_symbol_plus_left_int_less_or_equal_unsigned(void) { + unsigned x = f(), y = x; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_express(x <= y); // expected-warning {{$x + 1U <= $x}} +} + +void compare_same_symbol_minus_left_int_less_or_equal_unsigned(void) { + unsigned x = f(), y = x; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_express(x <= y); // expected-warning {{$x - 1U <= $x}} +} + +void compare_same_symbol_plus_right_int_less_or_equal_unsigned(void) { + unsigned x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_express(x <= y); // expected-warning {{$x <= $x + 1U}} +} + +void compare_same_symbol_minus_right_int_less_or_equal_unsigned(void) { + unsigned x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_express(x <= y); // expected-warning {{$x <= $x - 1U}} +} + +void compare_same_symbol_plus_left_plus_right_int_less_or_equal_unsigned(void) { + unsigned x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} +} + +void compare_same_symbol_plus_left_minus_right_int_less_or_equal_unsigned(void) { + unsigned x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_express(x <= y); // expected-warning {{$x + 1U <= $x - 1U}} +} + +void compare_same_symbol_minus_left_plus_right_int_less_or_equal_unsigned(void) { + unsigned x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_express(x <= y); // expected-warning {{$x - 1U <= $x + 1U}} +} + +void compare_same_symbol_minus_left_minus_right_int_less_or_equal_unsigned(void) { + unsigned x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_eval(x <= y); // expected-warning {{TRUE}} +} + +void compare_different_symbol_less_unsigned(void) { + unsigned x = f(), y = f(); + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y, "$y"); + clang_analyzer_express(y); // expected-warning {{$y}} + clang_analyzer_express(x < y); // expected-warning {{$x - $y < 0}} +} + +void compare_different_symbol_plus_left_int_less_unsigned(void) { + unsigned x = f() + 1, y = f(); + clang_analyzer_denote(x - 1, "$x"); + clang_analyzer_denote(y, "$y"); + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$y}} + clang_analyzer_express(x < y); // expected-warning {{$y - $x > 1}} +} + +void compare_different_symbol_minus_left_int_less_unsigned(void) { + unsigned x = f() - 1, y = f(); + clang_analyzer_denote(x + 1, "$x"); + clang_analyzer_denote(y, "$y"); + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$y}} + clang_analyzer_express(x < y); // expected-warning {{$x - $y < 1}} +} + +void compare_different_symbol_plus_right_int_less_unsigned(void) { + unsigned x = f(), y = f() + 2; + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y - 2, "$y"); + clang_analyzer_express(y); // expected-warning {{$y + 2}} + clang_analyzer_express(x < y); // expected-warning {{$x - $y < 2}} +} + +void compare_different_symbol_minus_right_int_less_unsigned(void) { + unsigned x = f(), y = f() - 2; + clang_analyzer_denote(x, "$x"); + clang_analyzer_denote(y + 2, "$y"); + clang_analyzer_express(y); // expected-warning {{$y - 2}} + clang_analyzer_express(x < y); // expected-warning {{$y - $x > 2}} +} + +void compare_different_symbol_plus_left_plus_right_int_less_unsigned(void) { + unsigned x = f() + 2, y = f() + 1; + clang_analyzer_denote(x - 2, "$x"); + clang_analyzer_denote(y - 1, "$y"); + clang_analyzer_express(x); // expected-warning {{$x + 2}} + clang_analyzer_express(y); // expected-warning {{$y + 1}} + clang_analyzer_express(x < y); // expected-warning {{$y - $x > 1}} +} + +void compare_different_symbol_plus_left_minus_right_int_less_unsigned(void) { + unsigned x = f() + 2, y = f() - 1; + clang_analyzer_denote(x - 2, "$x"); + clang_analyzer_denote(y + 1, "$y"); + clang_analyzer_express(x); // expected-warning {{$x + 2}} + clang_analyzer_express(y); // expected-warning {{$y - 1}} + clang_analyzer_express(x < y); // expected-warning {{$y - $x > 3}} +} + +void compare_different_symbol_minus_left_plus_right_int_less_unsigned(void) { + unsigned x = f() - 2, y = f() + 1; + clang_analyzer_denote(x + 2, "$x"); + clang_analyzer_denote(y - 1, "$y"); + clang_analyzer_express(x); // expected-warning {{$x - 2}} + clang_analyzer_express(y); // expected-warning {{$y + 1}} + clang_analyzer_express(x < y); // expected-warning {{$x - $y < 3}} +} + +void compare_different_symbol_minus_left_minus_right_int_less_unsigned(void) { + unsigned x = f() - 2, y = f() - 1; + clang_analyzer_denote(x + 2, "$x"); + clang_analyzer_denote(y + 1, "$y"); + clang_analyzer_express(x); // expected-warning {{$x - 2}} + clang_analyzer_express(y); // expected-warning {{$y - 1}} + clang_analyzer_express(x < y); // expected-warning {{$x - $y < 1}} +} + +#endif + +// These pass even with aggressive-binary-operation-simplification=false + +void compare_same_symbol_less_unsigned(void) { + unsigned x = f(), y = x; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_eval(x < y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_plus_left_int_less_unsigned(void) { + unsigned x = f(), y = x; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_express(x < y); // expected-warning {{$x + 1U < $x}} +} + +void compare_same_symbol_minus_left_int_less_unsigned(void) { + unsigned x = f(), y = x; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x}} + clang_analyzer_express(x < y); // expected-warning {{$x - 1U < $x}} +} + +void compare_same_symbol_plus_right_int_less_unsigned(void) { + unsigned x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_express(x < y); // expected-warning {{$x < $x + 1U}} +} + +void compare_same_symbol_minus_right_int_less_unsigned(void) { + unsigned x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_express(x < y); // expected-warning {{$x < $x - 1U}} +} + +void compare_same_symbol_plus_left_plus_right_int_less_unsigned(void) { + unsigned x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_eval(x < y); // expected-warning {{FALSE}} +} + +void compare_same_symbol_plus_left_minus_right_int_less_unsigned(void) { + unsigned x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + ++x; + clang_analyzer_express(x); // expected-warning {{$x + 1}} + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_express(x < y); // expected-warning {{$x + 1U < $x - 1U}} +} + +void compare_same_symbol_minus_left_plus_right_int_less_unsigned(void) { + unsigned x = f(), y = x + 1; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x + 1}} + clang_analyzer_express(x < y); // expected-warning {{$x - 1U < $x + 1U}} +} + +void compare_same_symbol_minus_left_minus_right_int_less_unsigned(void) { + unsigned x = f(), y = x - 1; + clang_analyzer_denote(x, "$x"); + --x; + clang_analyzer_express(x); // expected-warning {{$x - 1}} + clang_analyzer_express(y); // expected-warning {{$x - 1}} + clang_analyzer_eval(x < y); // expected-warning {{FALSE}} +} + +void overflow(signed char n, signed char m) { + if (n + 0 > m + 0) { + clang_analyzer_eval(n - 126 == m + 3); // expected-warning {{UNKNOWN}} + } +} + +int mixed_integer_types(int x, int y) { + short a = x - 1U; + return a - y; +} + +unsigned gu(void); +unsigned fu(void) { + unsigned x = gu(); + // Assert that no overflows occur in this test file. + // Assuming that concrete integers are also within that range. + assert(x <= ((unsigned)UINT_MAX / 4)); + return x; +} + +void unsigned_concrete_int_no_crash(void) { + unsigned x = fu() + 1U, y = fu() + 1U; + clang_analyzer_denote(x - 1U, "$x"); + clang_analyzer_denote(y - 1U, "$y"); + clang_analyzer_express(y); // expected-warning {{$y}} + clang_analyzer_express(x == y); // expected-warning {{$x + 1U == $y + 1U}} +} diff --git a/clang/test/Analysis/svalbuilder-simplify-no-crash.c b/clang/test/Analysis/svalbuilder-simplify-no-crash.c new file mode 100644 index 0000000000000..b43ccbdbfd100 --- /dev/null +++ b/clang/test/Analysis/svalbuilder-simplify-no-crash.c @@ -0,0 +1,13 @@ +// RUN: %clang_analyze_cc1 %s \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -verify + +// Here, we test that svalbuilder simplification does not produce any +// assertion failure. + +void crashing(long a, _Bool b) { + (void)(a & 1 && 0); + b = a & 1; + (void)(b << 1); // expected-warning{{core.UndefinedBinaryOperatorResult}} +} diff --git a/clang/test/Analysis/undef-buffers.c b/clang/test/Analysis/undef-buffers.c index b5058dc0ac914..4cd64c9c65155 100644 --- a/clang/test/Analysis/undef-buffers.c +++ b/clang/test/Analysis/undef-buffers.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-store=region -verify %s \ +// RUN: %clang_analyze_cc1 -verify %s \ // RUN: -analyzer-checker=core \ // RUN: -analyzer-checker=unix \ // RUN: -analyzer-checker=core.uninitialized \ diff --git a/clang/test/Analysis/uninit-ps-rdar6145427.m b/clang/test/Analysis/uninit-ps-rdar6145427.m index d735f17317cf8..225c98a20a621 100644 --- a/clang/test/Analysis/uninit-ps-rdar6145427.m +++ b/clang/test/Analysis/uninit-ps-rdar6145427.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify -analyzer-store=region %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s // Delta-Debugging reduced preamble. typedef signed char BOOL; diff --git a/clang/test/Analysis/uninit-vals-union.c b/clang/test/Analysis/uninit-vals-union.c index bccc77a4a4fee..e16cccfc9115a 100644 --- a/clang/test/Analysis/uninit-vals-union.c +++ b/clang/test/Analysis/uninit-vals-union.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core.builtin -analyzer-store=region -verify -Wno-unused %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core.builtin -verify -Wno-unused %s typedef union { int y; diff --git a/clang/test/Analysis/uninit-vals.m b/clang/test/Analysis/uninit-vals.m index 7e5f3355ccb5d..775c7ffb567c7 100644 --- a/clang/test/Analysis/uninit-vals.m +++ b/clang/test/Analysis/uninit-vals.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-store=region -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-output=text -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-output=text -verify %s typedef unsigned int NSUInteger; typedef __typeof__(sizeof(int)) size_t; diff --git a/clang/test/Analysis/unions-region.m b/clang/test/Analysis/unions-region.m index bad159fe81238..01b64d203619a 100644 --- a/clang/test/Analysis/unions-region.m +++ b/clang/test/Analysis/unions-region.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region %s -verify +// RUN: %clang_analyze_cc1 -analyzer-checker=core %s -verify // expected-no-diagnostics //===-- unions-region.m ---------------------------------------------------===// diff --git a/clang/test/Analysis/unix-fns.c b/clang/test/Analysis/unix-fns.c index 670c8c256b9c6..f23bc6e17740c 100644 --- a/clang/test/Analysis/unix-fns.c +++ b/clang/test/Analysis/unix-fns.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,unix.API,osx.API,optin.portability %s -analyzer-store=region -analyzer-output=plist -analyzer-config faux-bodies=true -fblocks -verify -o %t.plist +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,unix.API,osx.API,optin.portability %s -analyzer-output=plist -analyzer-config faux-bodies=true -fblocks -verify -o %t.plist // RUN: %normalize_plist <%t.plist | diff -ub %S/Inputs/expected-plists/unix-fns.c.plist - // RUN: mkdir -p %t.dir // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.API,osx.API,optin.portability -analyzer-output=html -analyzer-config faux-bodies=true -fblocks -o %t.dir %s diff --git a/clang/test/Analysis/unreachable-code-path.c b/clang/test/Analysis/unreachable-code-path.c index 59bca576cc0ab..cc526adece69a 100644 --- a/clang/test/Analysis/unreachable-code-path.c +++ b/clang/test/Analysis/unreachable-code-path.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,deadcode.DeadStores,alpha.deadcode.UnreachableCode -verify -analyzer-opt-analyze-nested-blocks -Wno-unused-value %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,deadcode.DeadStores,alpha.deadcode.UnreachableCode -verify -Wno-unused-value %s extern void foo(int a); diff --git a/clang/test/Analysis/valist-as-lazycompound.c b/clang/test/Analysis/valist-as-lazycompound.c index 2fbd4cb76f488..3218e03a9c657 100644 --- a/clang/test/Analysis/valist-as-lazycompound.c +++ b/clang/test/Analysis/valist-as-lazycompound.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple gcc-linaro-arm-linux-gnueabihf -analyzer-checker=core,valist.Uninitialized,valist.CopyToSelf -analyzer-output=text -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -triple gcc-linaro-arm-linux-gnueabihf -analyzer-checker=core,valist.Uninitialized,valist.CopyToSelf -analyzer-output=text -verify %s // expected-no-diagnostics typedef unsigned int size_t; diff --git a/clang/test/Analysis/valist-uninitialized-no-undef.c b/clang/test/Analysis/valist-uninitialized-no-undef.c index 6d6542a6acf99..48631429be646 100644 --- a/clang/test/Analysis/valist-uninitialized-no-undef.c +++ b/clang/test/Analysis/valist-uninitialized-no-undef.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,valist.Uninitialized,valist.CopyToSelf -analyzer-output=text -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,valist.Uninitialized,valist.CopyToSelf -analyzer-output=text -verify %s #include "Inputs/system-header-simulator-for-valist.h" diff --git a/clang/test/Analysis/valist-unterminated.c b/clang/test/Analysis/valist-unterminated.c index e19c6761784c8..22d8fc710544e 100644 --- a/clang/test/Analysis/valist-unterminated.c +++ b/clang/test/Analysis/valist-unterminated.c @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -triple hexagon-unknown-linux -analyzer-checker=core,valist.Unterminated,valist.CopyToSelf -analyzer-output=text -analyzer-store=region -verify %s -// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,valist.Unterminated,valist.CopyToSelf -analyzer-output=text -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -triple hexagon-unknown-linux -analyzer-checker=core,valist.Unterminated,valist.CopyToSelf -analyzer-output=text -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,valist.Unterminated,valist.CopyToSelf -analyzer-output=text -verify %s #include "Inputs/system-header-simulator-for-valist.h" diff --git a/clang/test/Analysis/variadic-method-types.m b/clang/test/Analysis/variadic-method-types.m index 6db93ac032e6a..78f737b42e3fa 100644 --- a/clang/test/Analysis/variadic-method-types.m +++ b/clang/test/Analysis/variadic-method-types.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.cocoa.VariadicMethodTypes -analyzer-store=region -fblocks -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.cocoa.VariadicMethodTypes -fblocks -verify %s //===----------------------------------------------------------------------===// // The following code is reduced using delta-debugging from diff --git a/clang/test/Analysis/weak-functions.c b/clang/test/Analysis/weak-functions.c index b2f297efed008..26cbfb3523a92 100644 --- a/clang/test/Analysis/weak-functions.c +++ b/clang/test/Analysis/weak-functions.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection,unix.Malloc,unix.cstring,alpha.unix.cstring,unix.API,osx.API,osx.cocoa.RetainCount -Wno-null-dereference -Wno-tautological-compare -analyzer-store=region -fblocks -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection,unix.Malloc,unix.cstring,alpha.unix.cstring,unix.API,osx.API,osx.cocoa.RetainCount -Wno-null-dereference -Wno-tautological-compare -fblocks -verify -analyzer-config eagerly-assume=false %s #define NULL 0 void clang_analyzer_eval(int); void myFunc(void); diff --git a/clang/test/C/drs/dr0xx.c b/clang/test/C/drs/dr0xx.c index 5cc0823eeb0b7..522f36c7141f3 100644 --- a/clang/test/C/drs/dr0xx.c +++ b/clang/test/C/drs/dr0xx.c @@ -9,6 +9,9 @@ /* The following are DRs which do not require tests to demonstrate * conformance or nonconformance. * + * WG14 DR001: yes + * Do functions return values by copying? + * * WG14 DR005: yes * May a conforming implementation define and recognize a pragma which would * change the semantics of the language? diff --git a/clang/test/C/drs/dr1xx.c b/clang/test/C/drs/dr1xx.c new file mode 100644 index 0000000000000..e7343c0e3573c --- /dev/null +++ b/clang/test/C/drs/dr1xx.c @@ -0,0 +1,233 @@ +/* RUN: %clang_cc1 -std=c89 -verify=expected,c89only -pedantic -Wno-c11-extensions %s + RUN: %clang_cc1 -std=c99 -verify=expected,c99untilc2x -pedantic -Wno-c11-extensions %s + RUN: %clang_cc1 -std=c11 -verify=expected,c99untilc2x -pedantic %s + RUN: %clang_cc1 -std=c17 -verify=expected,c99untilc2x -pedantic %s + RUN: %clang_cc1 -std=c2x -verify=expected,c2xandup -pedantic %s + */ + +/* The following are DRs which do not require tests to demonstrate + * conformance or nonconformance. + * + * WG14 DR100: dup 001 + * Defect with the return statement + * + * WG14 DR104: dup 084 + * Incomplete tag types in a parameter list + * + * WG14 DR109: yes + * Are undefined values and undefined behavior the same? + * + * WG14 DR110: dup 047 + * Formal parameters having array-of-non-object types + * + * WG14 DR117: yes + * Abstract semantics, sequence points, and expression evaluation + * + * WG14 DR121: yes + * Conversions of pointer values to integral types + * + * WG14 DR122: dup 015 + * Conversion/widening of bit-fields + * + * WG14 DR125: yes + * Using things declared as 'extern (qualified) void' + */ + + +/* WG14 DR101: yes + * Type qualifiers and "as if by assignment" + */ +void dr101_callee(const int val); +void dr101_caller(void) { + int val = 1; + dr101_callee(val); /* ok; const qualifier on the parameter doesn't prevent as-if assignment. */ +} + +/* WG14 DR102: yes + * Tag redeclaration constraints + */ +void dr102(void) { + struct S { int member; }; /* expected-note {{previous definition is here}} */ + struct S { int member; }; /* expected-error {{redefinition of 'S'}} */ + + union U { int member; }; /* expected-note {{previous definition is here}} */ + union U { int member; }; /* expected-error {{redefinition of 'U'}} */ + + enum E { member }; /* expected-note 2{{previous definition is here}} */ + enum E { member }; /* expected-error {{redefinition of 'E'}} + expected-error {{redefinition of enumerator 'member'}} */ +} + +/* WG14 DR103: yes + * Formal parameters of incomplete type + */ +void dr103_1(int arg[]); /* ok, not an incomplete type due to rewrite */ +void dr103_2(struct S s) {} /* expected-warning {{declaration of 'struct S' will not be visible outside of this function}} + expected-error {{variable has incomplete type 'struct S'}} + expected-note {{forward declaration of 'struct S'}} */ +void dr103_3(struct S s); /* expected-warning {{declaration of 'struct S' will not be visible outside of this function}} + expected-note {{previous declaration is here}} */ +void dr103_3(struct S { int a; } s) { } /* expected-warning {{declaration of 'struct S' will not be visible outside of this function}} + expected-error {{conflicting types for 'dr103_3'}} */ +void dr103_4(struct S s1, struct S { int a; } s2); /* expected-warning {{declaration of 'struct S' will not be visible outside of this function}} */ + +/* WG14 DR105: dup 017 + * Precedence of requirements on compatible types + * + * NB: This is also Question 3 from DR017. + */ +void dr105(void) { + /* According to C2x 6.7.6.3p14 the return type and parameter types to be + * compatible types, but qualifiers are dropped from the parameter type. + */ + extern void func(int); + extern void func(const int); /* FIXME: this should be pedantically diagnosed. */ + + extern void other_func(int); /* expected-note {{previous declaration is here}} */ + extern void other_func(int *); /* expected-error {{conflicting types for 'other_func'}} */ + + extern int i; /* expected-note {{previous declaration is here}} */ + extern float i; /* expected-error {{redeclaration of 'i' with a different type: 'float' vs 'int'}} */ +} + +/* WG14 DR106: yes + * When can you dereference a void pointer? + * + * NB: This is a partial duplicate of DR012. + */ +void dr106(void *p, int i) { + /* The behavior changed between C89 and C99. */ + (void)&*p; /* c89only-warning {{ISO C forbids taking the address of an expression of type 'void'}} */ + /* The behavior of all three of these is undefined. */ + (void)*p; + (void)(i ? *p : *p); + (void)(*p, *p); /* expected-warning {{left operand of comma operator has no effect}} */ +} + +/* WG14 DR108: yes + * Can a macro identifier hide a keyword? + */ +void dr108(void) { +#define const + const int i = 12; +#undef const + const int j = 12; /* expected-note {{variable 'j' declared const here}} */ + + i = 100; /* Okay, the keyword was hidden by the macro. */ + j = 100; /* expected-error {{cannot assign to variable 'j' with const-qualified type 'const int'}} */ +} + +/* WG14 DR111: yes + * Conversion of pointer-to-qualified type values to type (void*) values + */ +void dr111(const char *ccp, void *vp) { + vp = ccp; /* expected-warning {{assigning to 'void *' from 'const char *' discards qualifiers}} */ +} + +/* WG14 DR112: yes + * Null pointer constants and relational comparisons + */ +void dr112(void *vp) { + /* The behavior of this expression is pedantically undefined. + * FIXME: should we diagnose under -pedantic? + */ + (void)(vp > (void*)0); +} + +/* WG14 DR113: yes + * Return expressions in functions declared to return qualified void + */ +volatile void dr113_v(volatile void *vvp) { /* expected-warning {{function cannot return qualified void type 'volatile void'}} */ + return *vvp; /* expected-warning {{void function 'dr113_v' should not return void expression}} */ +} +const void dr113_c(const void *cvp) { /* expected-warning {{function cannot return qualified void type 'const void'}} */ + return *cvp; /* expected-warning {{void function 'dr113_c' should not return void expression}} */ +} + +/* WG14 DR114: yes + * Initialization of multi-dimensional char array objects + */ +void dr114(void) { + char array[2][5] = { "defghi" }; /* expected-warning {{initializer-string for char array is too long}} */ +} + +/* WG14 DR115: yes + * Member declarators as declarators + */ +void dr115(void) { + struct { int mbr; }; /* expected-warning {{declaration does not declare anything}} */ + union { int mbr; }; /* expected-warning {{declaration does not declare anything}} */ +} + +/* WG14 DR116: yes + * Implicit unary & applied to register arrays + */ +void dr116(void) { + register int array[5] = { 0, 1, 2, 3, 4 }; + (void)array; /* expected-error {{address of register variable requested}} */ + (void)array[3]; /* expected-error {{address of register variable requested}} */ + (void)(array + 3); /* expected-error {{address of register variable requested}} */ +} + +/* WG14 DR118: yes + * Completion point for enumerated types + */ +void dr118(void) { + enum E { + /* The enum isn't a complete type until the closing }, but an + * implementation may complete the type earlier if it has sufficient type + * information to calculate size or alignment, etc. + * + * On Microsoft targets, an enum is always implicit int sized, so the type + * is sufficiently complete there. On other platforms, it is an incomplete + * type at this point. + */ + Val = sizeof(enum E) + #ifndef _WIN32 + /* expected-error@-2 {{invalid application of 'sizeof' to an incomplete type 'enum E'}} */ + /* expected-note@-12 {{definition of 'enum E' is not complete until the closing '}'}} */ + #endif + }; +} + +/* WG14 DR119: yes + * Initialization of multi-dimensional array objects + */ +void dr119(void) { + static int array[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; /* expected-error {{array has incomplete element type 'int[]'}} */ +} + +/* WG14 DR120: yes + * Semantics of assignment to (and initialization of) bit-fields + */ +void dr120(void) { + /* We could verify this one with a codegen test to ensure that the proper + * value is stored into bit, but the diagnostic tells us what the value is + * after conversion, so we can lean on that for verification. + */ + struct S { unsigned bit:1; }; + struct S object1 = { 3 }; /* expected-warning {{implicit truncation from 'int' to bit-field changes value from 3 to 1}} */ + struct S object2; + object2.bit = 3; /* expected-warning {{implicit truncation from 'int' to bit-field changes value from 3 to 1}} */ +} + +/* WG14 DR123: yes + * 'Type categories' and qualified types + */ +void dr123(void) { + /* Both of these examples are strictly conforming. */ + enum E1 { + enumerator1 = (const int) 9 + }; + enum E2 { + enumerator2 = (volatile int) 9 + }; +} + +/* WG14 DR124: yes + * Casts to 'a void type' versus casts to 'the void type' + */ +void dr124(void) { + /* A cast can cast to void or any qualified version of void. */ + (const volatile void)0; +} diff --git a/clang/test/C/drs/dr4xx.c b/clang/test/C/drs/dr4xx.c new file mode 100644 index 0000000000000..ab3407520f592 --- /dev/null +++ b/clang/test/C/drs/dr4xx.c @@ -0,0 +1,32 @@ +/* RUN: %clang_cc1 -std=c89 -verify=expected,c89only -pedantic -Wno-c11-extensions %s + RUN: %clang_cc1 -std=c99 -verify=expected,c99untilc2x -pedantic -Wno-c11-extensions %s + RUN: %clang_cc1 -std=c11 -verify=expected,c99untilc2x -pedantic %s + RUN: %clang_cc1 -std=c17 -verify=expected,c99untilc2x -pedantic %s + RUN: %clang_cc1 -std=c2x -verify=expected,c2xandup -pedantic %s + */ + +/* The following are DRs which do not require tests to demonstrate + * conformance or nonconformance. + */ + + +/* WG14 DR423: partial + * Defect Report relative to n1570: underspecification for qualified rvalues + */ + +/* FIXME: this should pass because the qualifier on the return type should be + * dropped when forming the function type. + */ +const int dr423_const(void); +int dr423_nonconst(void); +_Static_assert(__builtin_types_compatible_p(__typeof__(dr423_const), __typeof__(dr423_nonconst)), "fail"); /* expected-error {{fail}} */ + +void dr423_func(void) { + const int i = 12; + __typeof__(i) v1 = 12; /* expected-note {{variable 'v1' declared const here}} */ + __typeof__((const int)12) v2 = 12; + + v1 = 100; /* expected-error {{cannot assign to variable 'v1' with const-qualified type 'typeof (i)' (aka 'const int')}} */ + v2 = 100; /* Not an error; the qualifier was stripped. */ +} + diff --git a/clang/test/CXX/basic/basic.def/p2.cpp b/clang/test/CXX/basic/basic.def/p2.cpp index 598a79a8a3d7d..ccb7a66cff8f0 100644 --- a/clang/test/CXX/basic/basic.def/p2.cpp +++ b/clang/test/CXX/basic/basic.def/p2.cpp @@ -5,4 +5,9 @@ namespace { static constexpr int n = 0; }; const int A::n; // expected-warning {{deprecated}} + + struct B { + static constexpr int m = 0; + }; + constexpr int B::m; // expected-warning {{deprecated}} } diff --git a/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp b/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp index 7055acad6ccf9..975557c5187bb 100644 --- a/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp +++ b/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp @@ -96,7 +96,9 @@ void func(); struct A1 { A1(const A1 &); - A1(A1 &&) = delete; // expected-note 2{{'A1' has been explicitly marked deleted here}} + A1(A1 &&) = delete; + // expected-note@-1 2{{'A1' has been explicitly marked deleted here}} + // cxx11_2b-note@-2 3{{'A1' has been explicitly marked deleted here}} }; void test1() { try { @@ -125,6 +127,22 @@ void test3(A1 a) try { } catch (...) { throw a; // expected-error {{call to deleted constructor of 'test_throw_parameter::A1'}} } + +#if __cplusplus >= 201103L +namespace PR54341 { +void test4(A1 a) { + void f(decltype((throw a, 0))); + // expected-error@-1 {{call to deleted constructor of 'test_throw_parameter::A1'}} + + void g(int = decltype(throw a, 0){}); + // expected-error@-1 {{call to deleted constructor of 'test_throw_parameter::A1'}} +} + +void test5(A1 a, int = decltype(throw a, 0){}) {} +// expected-error@-1 {{call to deleted constructor of 'test_throw_parameter::A1'}} +} // namespace PR54341 +#endif + } // namespace test_throw_parameter // During the first overload resolution, the selected function no diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p1.cpp index 142d4d6f369f6..afa7869da5f43 100644 --- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p1.cpp @@ -7,4 +7,4 @@ struct [[nodiscard("Wrong")]] S3 {}; [[nodiscard]] int f(); enum [[nodiscard]] E {}; -namespace [[nodiscard]] N {} // expected-warning {{'nodiscard' attribute only applies to Objective-C methods, enums, structs, unions, classes, functions, and function pointers}} +namespace [[nodiscard]] N {} // expected-warning {{'nodiscard' attribute only applies to Objective-C methods, enums, structs, unions, classes, functions, function pointers, and typedefs}} diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp index 81efbb0a47271..6d2bc3f25179b 100644 --- a/clang/test/CXX/expr/expr.const/p2-0x.cpp +++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp @@ -162,9 +162,9 @@ namespace UndefinedBehavior { constexpr int shl_signed_ok = 1 << 30; // ok constexpr int shl_signed_into_sign = 1 << 31; // ok (DR1457) constexpr int shl_signed_into_sign_2 = 0x7fffffff << 1; // ok (DR1457) - constexpr int shl_signed_off_end = 2 << 31; // cxx11-error {{constant expression}} cxx11-note {{signed left shift discards bits}} expected-warning {{signed shift result (0x100000000) requires 34 bits to represent, but 'int' only has 32 bits}} - constexpr int shl_signed_off_end_2 = 0x7fffffff << 2; // cxx11-error {{constant expression}} cxx11-note {{signed left shift discards bits}} expected-warning {{signed shift result (0x1FFFFFFFC) requires 34 bits to represent, but 'int' only has 32 bits}} - constexpr int shl_signed_overflow = 1024 << 31; // cxx11-error {{constant expression}} cxx11-note {{signed left shift discards bits}} expected-warning {{requires 43 bits to represent}} + constexpr int shl_signed_off_end = 2 << 31; // cxx11-error {{constant expression}} cxx11-note {{signed left shift discards bits}} cxx11-warning {{signed shift result (0x100000000) requires 34 bits to represent, but 'int' only has 32 bits}} + constexpr int shl_signed_off_end_2 = 0x7fffffff << 2; // cxx11-error {{constant expression}} cxx11-note {{signed left shift discards bits}} cxx11-warning {{signed shift result (0x1FFFFFFFC) requires 34 bits to represent, but 'int' only has 32 bits}} + constexpr int shl_signed_overflow = 1024 << 31; // cxx11-error {{constant expression}} cxx11-note {{signed left shift discards bits}} cxx11-warning {{requires 43 bits to represent}} constexpr int shl_signed_ok2 = 1024 << 20; // ok constexpr int shr_m1 = 0 >> -1; // expected-error {{constant expression}} expected-note {{negative shift count -1}} diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp index 7eddef1cb71f3..871bdc2a58c7b 100644 --- a/clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp @@ -80,7 +80,7 @@ namespace print_dependent_TemplateSpecializationType { template struct Foo { template struct Bar; template struct Bar<0, T, Y> {}; - // expected-note-re@-1 {{previous declaration {{.*}} 'Bar<0UL, int, type-parameter-0-0>' is here}} + // expected-note-re@-1 {{previous declaration {{.*}} 'Bar<0, int, type-parameter-0-0>' is here}} template struct Bar<0, U, Y> {}; // expected-error@-1 {{partial specialization 'Bar<0, int, Y>' cannot be redeclared}} }; diff --git a/clang/test/ClangScanDeps/modules-disable-free.c b/clang/test/ClangScanDeps/modules-disable-free.c new file mode 100644 index 0000000000000..16e5092128764 --- /dev/null +++ b/clang/test/ClangScanDeps/modules-disable-free.c @@ -0,0 +1,34 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed -e "s|DIR|%/t|g" %t/compile-commands.json.in > %t/compile-commands.json + +// RUN: clang-scan-deps -compilation-database %t/compile-commands.json -j 1 -format experimental-full \ +// RUN: -mode preprocess-dependency-directives -generate-modules-path-args > %t/output +// RUN: FileCheck %s < %t/output + +// CHECK: "-disable-free", + +//--- compile-commands.json.in + +[{ + "directory": "DIR", + "command": "clang -c DIR/main.c -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fimplicit-module-maps", + "file": "DIR/main.c" +}] + +//--- module.modulemap + +module A { + header "a.h" +} + +//--- a.h + +void a(void); + +//--- main.c + +#include "a.h" +void m() { + a(); +} diff --git a/clang/test/CodeGen/64bit-swiftcall.c b/clang/test/CodeGen/64bit-swiftcall.c index a027129a4bbbb..f1fb8e10dc0ad 100644 --- a/clang/test/CodeGen/64bit-swiftcall.c +++ b/clang/test/CodeGen/64bit-swiftcall.c @@ -125,7 +125,7 @@ TEST(struct_1); // CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4 // CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 // CHECK: [[T1:%.*]] = load i64, i64* [[GEP1]], align 4 -// CHECK: [[R0:%.*]] = insertvalue { i64, i64 } undef, i64 [[T0]], 0 +// CHECK: [[R0:%.*]] = insertvalue { i64, i64 } poison, i64 [[T0]], 0 // CHECK: [[R1:%.*]] = insertvalue { i64, i64 } [[R0]], i64 [[T1]], 1 // CHECK: ret { i64, i64 } [[R1]] // CHECK: } @@ -174,7 +174,7 @@ TEST(struct_2); // CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4 // CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 // CHECK: [[T1:%.*]] = load i64, i64* [[GEP1]], align 4 -// CHECK: [[R0:%.*]] = insertvalue { i64, i64 } undef, i64 [[T0]], 0 +// CHECK: [[R0:%.*]] = insertvalue { i64, i64 } poison, i64 [[T0]], 0 // CHECK: [[R1:%.*]] = insertvalue { i64, i64 } [[R0]], i64 [[T1]], 1 // CHECK: ret { i64, i64 } [[R1]] // CHECK: } @@ -395,7 +395,7 @@ TEST(int8) // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 // CHECK: [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align -// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, <4 x i32> }]] undef, <4 x i32> [[FIRST]], 0 +// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, <4 x i32> }]] poison, <4 x i32> [[FIRST]], 0 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], <4 x i32> [[SECOND]], 1 // CHECK: ret [[UAGG]] [[T1]] // CHECK-LABEL: define {{.*}} @take_int8(<4 x i32> %0, <4 x i32> %1) @@ -439,7 +439,7 @@ TEST(int5) // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align -// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, i32 }]] undef, <4 x i32> [[FIRST]], 0 +// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, i32 }]] poison, <4 x i32> [[FIRST]], 0 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1 // CHECK: ret [[UAGG]] [[T1]] // CHECK-LABEL: define {{.*}} @take_int5(<4 x i32> %0, i32 %1) diff --git a/clang/test/CodeGen/Inputs/sanitizer-special-case-list-globals.txt b/clang/test/CodeGen/Inputs/sanitizer-special-case-list-globals.txt new file mode 100644 index 0000000000000..81eaa53d25ea0 --- /dev/null +++ b/clang/test/CodeGen/Inputs/sanitizer-special-case-list-globals.txt @@ -0,0 +1,9 @@ +global:always_ignored +[address] +global:asan_ignored +[hwaddress] +global:hwasan_ignored +[memtag] +global:memtag_ignored +[cfi-vcall|cfi-icall] +src:* diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-pair-mma.c b/clang/test/CodeGen/PowerPC/builtins-ppc-pair-mma.c index 72867007afddf..f7811a4d1129c 100644 --- a/clang/test/CodeGen/PowerPC/builtins-ppc-pair-mma.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-pair-mma.c @@ -1048,7 +1048,7 @@ void test65(unsigned char *vqp, unsigned char *vpp, vector unsigned char vc, uns // CHECK-NEXT: tail call void @llvm.ppc.vsx.stxvp(<256 x i1> [[TMP1]], i8* [[TMP2]]) // CHECK-NEXT: ret void // -void test66(const __vector_pair *vpp, const __vector_pair *vp2) { +void test66(const __vector_pair *vpp, __vector_pair *vp2) { __vector_pair vp = __builtin_vsx_lxvp(0L, vpp); __builtin_vsx_stxvp(vp, 0L, vp2); } @@ -1063,7 +1063,7 @@ void test66(const __vector_pair *vpp, const __vector_pair *vp2) { // CHECK-NEXT: tail call void @llvm.ppc.vsx.stxvp(<256 x i1> [[TMP2]], i8* [[TMP4]]) // CHECK-NEXT: ret void // -void test67(const __vector_pair *vpp, signed long offset, const __vector_pair *vp2) { +void test67(const __vector_pair *vpp, signed long offset, __vector_pair *vp2) { __vector_pair vp = __builtin_vsx_lxvp(offset, vpp); __builtin_vsx_stxvp(vp, offset, vp2); } @@ -1078,7 +1078,7 @@ void test67(const __vector_pair *vpp, signed long offset, const __vector_pair *v // CHECK-NEXT: tail call void @llvm.ppc.vsx.stxvp(<256 x i1> [[TMP2]], i8* [[TMP4]]) // CHECK-NEXT: ret void // -void test68(const __vector_pair *vpp, const __vector_pair *vp2) { +void test68(const __vector_pair *vpp, __vector_pair *vp2) { __vector_pair vp = __builtin_vsx_lxvp(18L, vpp); __builtin_vsx_stxvp(vp, 18L, vp2); } @@ -1093,7 +1093,7 @@ void test68(const __vector_pair *vpp, const __vector_pair *vp2) { // CHECK-NEXT: tail call void @llvm.ppc.vsx.stxvp(<256 x i1> [[TMP2]], i8* [[TMP4]]) // CHECK-NEXT: ret void // -void test69(const __vector_pair *vpp, const __vector_pair *vp2) { +void test69(const __vector_pair *vpp, __vector_pair *vp2) { __vector_pair vp = __builtin_vsx_lxvp(1L, vpp); __builtin_vsx_stxvp(vp, 1L, vp2); } @@ -1108,7 +1108,7 @@ void test69(const __vector_pair *vpp, const __vector_pair *vp2) { // CHECK-NEXT: tail call void @llvm.ppc.vsx.stxvp(<256 x i1> [[TMP2]], i8* [[TMP4]]) // CHECK-NEXT: ret void // -void test70(const __vector_pair *vpp, const __vector_pair *vp2) { +void test70(const __vector_pair *vpp, __vector_pair *vp2) { __vector_pair vp = __builtin_vsx_lxvp(42L, vpp); __builtin_vsx_stxvp(vp, 42L, vp2); } @@ -1123,7 +1123,7 @@ void test70(const __vector_pair *vpp, const __vector_pair *vp2) { // CHECK-NEXT: tail call void @llvm.ppc.vsx.stxvp(<256 x i1> [[TMP2]], i8* [[TMP4]]) // CHECK-NEXT: ret void // -void test71(const __vector_pair *vpp, const __vector_pair *vp2) { +void test71(const __vector_pair *vpp, __vector_pair *vp2) { __vector_pair vp = __builtin_vsx_lxvp(32768L, vpp); __builtin_vsx_stxvp(vp, 32768L, vp2); } @@ -1138,7 +1138,7 @@ void test71(const __vector_pair *vpp, const __vector_pair *vp2) { // CHECK-NEXT: tail call void @llvm.ppc.vsx.stxvp(<256 x i1> [[TMP2]], i8* [[TMP4]]) // CHECK-NEXT: ret void // -void test72(const __vector_pair *vpp, const __vector_pair *vp2) { +void test72(const __vector_pair *vpp, __vector_pair *vp2) { __vector_pair vp = __builtin_vsx_lxvp(32799L, vpp); __builtin_vsx_stxvp(vp, 32799L, vp2); } @@ -1240,7 +1240,7 @@ void test77(unsigned char *vqp, unsigned char *vpp, vector unsigned char vc, uns // CHECK-NEXT: tail call void @llvm.ppc.vsx.stxvp(<256 x i1> [[TMP1]], i8* [[TMP2]]) // CHECK-NEXT: ret void // -void test78(const __vector_pair *vpp, const __vector_pair *vp2) { +void test78(const __vector_pair *vpp, __vector_pair *vp2) { __vector_pair vp = __builtin_mma_lxvp(0L, vpp); __builtin_mma_stxvp(vp, 0L, vp2); } @@ -1255,7 +1255,7 @@ void test78(const __vector_pair *vpp, const __vector_pair *vp2) { // CHECK-NEXT: tail call void @llvm.ppc.vsx.stxvp(<256 x i1> [[TMP2]], i8* [[TMP4]]) // CHECK-NEXT: ret void // -void test79(const __vector_pair *vpp, signed long offset, const __vector_pair *vp2) { +void test79(const __vector_pair *vpp, signed long offset, __vector_pair *vp2) { __vector_pair vp = __builtin_mma_lxvp(offset, vpp); __builtin_mma_stxvp(vp, offset, vp2); } @@ -1270,7 +1270,7 @@ void test79(const __vector_pair *vpp, signed long offset, const __vector_pair *v // CHECK-NEXT: tail call void @llvm.ppc.vsx.stxvp(<256 x i1> [[TMP2]], i8* [[TMP4]]) // CHECK-NEXT: ret void // -void test80(const __vector_pair *vpp, const __vector_pair *vp2) { +void test80(const __vector_pair *vpp, __vector_pair *vp2) { __vector_pair vp = __builtin_mma_lxvp(18L, vpp); __builtin_mma_stxvp(vp, 18L, vp2); } @@ -1285,7 +1285,7 @@ void test80(const __vector_pair *vpp, const __vector_pair *vp2) { // CHECK-NEXT: tail call void @llvm.ppc.vsx.stxvp(<256 x i1> [[TMP2]], i8* [[TMP4]]) // CHECK-NEXT: ret void // -void test81(const __vector_pair *vpp, const __vector_pair *vp2) { +void test81(const __vector_pair *vpp, __vector_pair *vp2) { __vector_pair vp = __builtin_mma_lxvp(1L, vpp); __builtin_mma_stxvp(vp, 1L, vp2); } @@ -1300,7 +1300,7 @@ void test81(const __vector_pair *vpp, const __vector_pair *vp2) { // CHECK-NEXT: tail call void @llvm.ppc.vsx.stxvp(<256 x i1> [[TMP2]], i8* [[TMP4]]) // CHECK-NEXT: ret void // -void test82(const __vector_pair *vpp, const __vector_pair *vp2) { +void test82(const __vector_pair *vpp, __vector_pair *vp2) { __vector_pair vp = __builtin_mma_lxvp(42L, vpp); __builtin_mma_stxvp(vp, 42L, vp2); } @@ -1315,7 +1315,7 @@ void test82(const __vector_pair *vpp, const __vector_pair *vp2) { // CHECK-NEXT: tail call void @llvm.ppc.vsx.stxvp(<256 x i1> [[TMP2]], i8* [[TMP4]]) // CHECK-NEXT: ret void // -void test83(const __vector_pair *vpp, const __vector_pair *vp2) { +void test83(const __vector_pair *vpp, __vector_pair *vp2) { __vector_pair vp = __builtin_mma_lxvp(32768L, vpp); __builtin_mma_stxvp(vp, 32768L, vp2); } @@ -1330,7 +1330,7 @@ void test83(const __vector_pair *vpp, const __vector_pair *vp2) { // CHECK-NEXT: tail call void @llvm.ppc.vsx.stxvp(<256 x i1> [[TMP2]], i8* [[TMP4]]) // CHECK-NEXT: ret void // -void test84(const __vector_pair *vpp, const __vector_pair *vp2) { +void test84(const __vector_pair *vpp, __vector_pair *vp2) { __vector_pair vp = __builtin_mma_lxvp(32799L, vpp); __builtin_mma_stxvp(vp, 32799L, vp2); } diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics/vread-csr.c b/clang/test/CodeGen/RISCV/rvv-intrinsics/vread-csr.c new file mode 100644 index 0000000000000..d4334bddc1b90 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics/vread-csr.c @@ -0,0 +1,42 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +v -disable-O0-optnone -emit-llvm %s -o - \ +// RUN: | opt -S -O2 | FileCheck %s + +#include + +// CHECK-LABEL: @vread_csr_vstart( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 asm sideeffect "csrr\09$0, vstart", "=r,~{memory}"() #[[ATTR1:[0-9]+]], !srcloc !4 +// CHECK-NEXT: ret i64 [[TMP0]] +// +unsigned long vread_csr_vstart(void) { + return vread_csr(RVV_VSTART); +} + +// CHECK-LABEL: @vread_csr_vxsat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 asm sideeffect "csrr\09$0, vxsat", "=r,~{memory}"() #[[ATTR1]], !srcloc !5 +// CHECK-NEXT: ret i64 [[TMP0]] +// +unsigned long vread_csr_vxsat(void) { + return vread_csr(RVV_VXSAT); +} + +// CHECK-LABEL: @vread_csr_vxrm( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 asm sideeffect "csrr\09$0, vxrm", "=r,~{memory}"() #[[ATTR1]], !srcloc !6 +// CHECK-NEXT: ret i64 [[TMP0]] +// +unsigned long vread_csr_vxrm(void) { + return vread_csr(RVV_VXRM); +} + +// CHECK-LABEL: @vread_csr_vcsr( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 asm sideeffect "csrr\09$0, vcsr", "=r,~{memory}"() #[[ATTR1]], !srcloc !7 +// CHECK-NEXT: ret i64 [[TMP0]] +// +unsigned long vread_csr_vcsr(void) { + return vread_csr(RVV_VCSR); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics/vwrite-csr.c b/clang/test/CodeGen/RISCV/rvv-intrinsics/vwrite-csr.c new file mode 100644 index 0000000000000..a94f599d7c7c3 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics/vwrite-csr.c @@ -0,0 +1,42 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +v -disable-O0-optnone -emit-llvm %s -o - \ +// RUN: | opt -S -O2 | FileCheck %s + +#include + +// CHECK-LABEL: @vwrite_csr_vstart( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void asm sideeffect "csrw\09vstart, ${0:z}", "rJ,~{memory}"(i64 [[VALUE:%.*]]) #[[ATTR1:[0-9]+]], !srcloc !4 +// CHECK-NEXT: ret void +// +void vwrite_csr_vstart(unsigned long value) { + vwrite_csr(RVV_VSTART, value); +} + +// CHECK-LABEL: @vwrite_csr_vxsat( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void asm sideeffect "csrw\09vxsat, ${0:z}", "rJ,~{memory}"(i64 [[VALUE:%.*]]) #[[ATTR1]], !srcloc !5 +// CHECK-NEXT: ret void +// +void vwrite_csr_vxsat(unsigned long value) { + vwrite_csr(RVV_VXSAT, value); +} + +// CHECK-LABEL: @vwrite_csr_vxrm( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void asm sideeffect "csrw\09vxrm, ${0:z}", "rJ,~{memory}"(i64 [[VALUE:%.*]]) #[[ATTR1]], !srcloc !6 +// CHECK-NEXT: ret void +// +void vwrite_csr_vxrm(unsigned long value) { + vwrite_csr(RVV_VXRM, value); +} + +// CHECK-LABEL: @vwrite_csr_vcsr( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void asm sideeffect "csrw\09vcsr, ${0:z}", "rJ,~{memory}"(i64 [[VALUE:%.*]]) #[[ATTR1]], !srcloc !7 +// CHECK-NEXT: ret void +// +void vwrite_csr_vcsr(unsigned long value) { + vwrite_csr(RVV_VCSR, value); +} diff --git a/clang/test/CodeGen/X86/3dnow-builtins.c b/clang/test/CodeGen/X86/3dnow-builtins.c index 71a46c9b44b5c..af754b71555c4 100644 --- a/clang/test/CodeGen/X86/3dnow-builtins.c +++ b/clang/test/CodeGen/X86/3dnow-builtins.c @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-unknown-unknown -target-feature +3dnowa -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=GCC -check-prefix=CHECK // RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-scei-ps4 -target-feature +3dnowa -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=PS4 -check-prefix=CHECK +// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-sie-ps5 -target-feature +3dnowa -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=PS4 -check-prefix=CHECK #include diff --git a/clang/test/CodeGen/X86/avx-union.c b/clang/test/CodeGen/X86/avx-union.c index 386d8cc32ec47..65fd62cf45bf0 100644 --- a/clang/test/CodeGen/X86/avx-union.c +++ b/clang/test/CodeGen/X86/avx-union.c @@ -5,6 +5,7 @@ // RUN: %clang_cc1 -no-opaque-pointers -w -ffreestanding -triple x86_64-linux-gnu -target-feature +avx -fclang-abi-compat=10.0 -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK-LEGACY,AVX // RUN: %clang_cc1 -no-opaque-pointers -w -ffreestanding -triple x86_64-linux-gnu -target-feature +avx512f -fclang-abi-compat=11.0 -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK-LEGACY,AVX512-LEGACY // RUN: %clang_cc1 -no-opaque-pointers -w -ffreestanding -triple x86_64-scei-ps4 -target-feature +avx -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-LEGACY +// RUN: %clang_cc1 -no-opaque-pointers -w -ffreestanding -triple x86_64-sie-ps5 -target-feature +avx -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-LEGACY // This tests verifies that a union parameter should pass by a vector regitster whose first eightbyte is SSE and the other eightbytes are SSEUP. diff --git a/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c b/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c index f14e7d1e84262..c57c476032025 100644 --- a/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c +++ b/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c @@ -328,6 +328,132 @@ svfloat64_t add_scalar_f64(svfloat64_t a, double b) { return a + b; } +// CHECK-LABEL: @add_i8_i_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[ADD]] +// +svint8_t add_i8_i_lit(svint8_t a) { + return a + 0; +} + +// CHECK-LABEL: @add_i8_il_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[ADD]] +// +svint8_t add_i8_il_lit(svint8_t a) { + return a + 0l; +} + +// CHECK-LABEL: @add_i8_ill_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[ADD]] +// +svint8_t add_i8_ill_lit(svint8_t a) { + return a + 0ll; +} + +// CHECK-LABEL: @add_i8_u_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[ADD]] +// +svint8_t add_i8_u_lit(svint8_t a) { + return a + 0u; +} + +// CHECK-LABEL: @add_i8_ul_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[ADD]] +// +svint8_t add_i8_ul_lit(svint8_t a) { + return a + 0ul; +} + +// CHECK-LABEL: @add_i8_ull_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[ADD]] +// +svint8_t add_i8_ull_lit(svint8_t a) { + return a + 0ull; +} + +// CHECK-LABEL: @add_f64_i_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = fadd [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[ADD]] +// +svfloat64_t add_f64_i_lit(svfloat64_t a) { + return a + 0; +} + +// CHECK-LABEL: @add_f64_il_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = fadd [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[ADD]] +// +svfloat64_t add_f64_il_lit(svfloat64_t a) { + return a + 0l; +} + +// CHECK-LABEL: @add_f64_ill_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = fadd [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[ADD]] +// +svfloat64_t add_f64_ill_lit(svfloat64_t a) { + return a + 0ll; +} + +// CHECK-LABEL: @add_f64_u_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = fadd [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[ADD]] +// +svfloat64_t add_f64_u_lit(svfloat64_t a) { + return a + 0u; +} + +// CHECK-LABEL: @add_f64_ul_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = fadd [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[ADD]] +// +svfloat64_t add_f64_ul_lit(svfloat64_t a) { + return a + 0ul; +} + +// CHECK-LABEL: @add_f64_ull_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = fadd [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[ADD]] +// +svfloat64_t add_f64_ull_lit(svfloat64_t a) { + return a + 0ull; +} + +// CHECK-LABEL: @add_f64_f_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = fadd [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[ADD]] +// +svfloat64_t add_f64_f_lit(svfloat64_t a) { + return a + 0.f; +} + +// CHECK-LABEL: @add_f64_d_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = fadd [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[ADD]] +// +svfloat64_t add_f64_d_lit(svfloat64_t a) { + return a + 0.; +} + // SUBTRACTION // CHECK-LABEL: @sub_i8( diff --git a/clang/test/CodeGen/aarch64-sve-vls-arith-ops.c b/clang/test/CodeGen/aarch64-sve-vls-arith-ops.c new file mode 100644 index 0000000000000..38b1f970fdc0d --- /dev/null +++ b/clang/test/CodeGen/aarch64-sve-vls-arith-ops.c @@ -0,0 +1,1984 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \ +// RUN: -fallow-half-arguments-and-returns -disable-O0-optnone -mvscale-min=4 -mvscale-max=4 \ +// RUN: -emit-llvm -o - %s | opt -S -sroa | FileCheck %s + +// REQUIRES: aarch64-registered-target + +#include + +#define N 512 + +typedef svint8_t fixed_int8_t __attribute__((arm_sve_vector_bits(N))); +typedef svint16_t fixed_int16_t __attribute__((arm_sve_vector_bits(N))); +typedef svint32_t fixed_int32_t __attribute__((arm_sve_vector_bits(N))); +typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svuint8_t fixed_uint8_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint16_t fixed_uint16_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint32_t fixed_uint32_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint64_t fixed_uint64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svfloat16_t fixed_float16_t __attribute__((arm_sve_vector_bits(N))); +typedef svfloat32_t fixed_float32_t __attribute__((arm_sve_vector_bits(N))); +typedef svfloat64_t fixed_float64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N))); + +// ADDITION + +// CHECK-LABEL: @add_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t add_i8(fixed_int8_t a, fixed_int8_t b) { + return a + b; +} + +// CHECK-LABEL: @add_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t add_i16(fixed_int16_t a, fixed_int16_t b) { + return a + b; +} + +// CHECK-LABEL: @add_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t add_i32(fixed_int32_t a, fixed_int32_t b) { + return a + b; +} + +// CHECK-LABEL: @add_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t add_i64(fixed_int64_t a, fixed_int64_t b) { + return a + b; +} + +// CHECK-LABEL: @add_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t add_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a + b; +} + +// CHECK-LABEL: @add_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t add_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a + b; +} + +// CHECK-LABEL: @add_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t add_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a + b; +} + +// CHECK-LABEL: @add_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t add_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a + b; +} + +// CHECK-LABEL: @add_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = fpext <32 x half> [[A]] to <32 x float> +// CHECK-NEXT: [[CONV2:%.*]] = fpext <32 x half> [[B]] to <32 x float> +// CHECK-NEXT: [[ADD:%.*]] = fadd <32 x float> [[CONV]], [[CONV2]] +// CHECK-NEXT: [[CONV3:%.*]] = fptrunc <32 x float> [[ADD]] to <32 x half> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8f16.v32f16( undef, <32 x half> [[CONV3]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float16_t add_f16(fixed_float16_t a, fixed_float16_t b) { + return a + b; +} + +// CHECK-LABEL: @add_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = fadd <16 x float> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.v16f32( undef, <16 x float> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float32_t add_f32(fixed_float32_t a, fixed_float32_t b) { + return a + b; +} + +// CHECK-LABEL: @add_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = fadd <8 x double> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2f64.v8f64( undef, <8 x double> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float64_t add_f64(fixed_float64_t a, fixed_float64_t b) { + return a + b; +} + +// CHECK-LABEL: @add_inplace_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t add_inplace_i8(fixed_int8_t a, fixed_int8_t b) { + return a += b; +} + +// CHECK-LABEL: @add_inplace_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t add_inplace_i16(fixed_int16_t a, fixed_int16_t b) { + return a += b; +} + +// CHECK-LABEL: @add_inplace_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t add_inplace_i32(fixed_int32_t a, fixed_int32_t b) { + return a += b; +} + +// CHECK-LABEL: @add_inplace_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t add_inplace_i64(fixed_int64_t a, fixed_int64_t b) { + return a += b; +} + +// CHECK-LABEL: @add_inplace_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t add_inplace_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a += b; +} + +// CHECK-LABEL: @add_inplace_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t add_inplace_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a += b; +} + +// CHECK-LABEL: @add_inplace_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t add_inplace_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a += b; +} + +// CHECK-LABEL: @add_inplace_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = add <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t add_inplace_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a += b; +} + +// CHECK-LABEL: @add_inplace_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = fpext <32 x half> [[B]] to <32 x float> +// CHECK-NEXT: [[CONV2:%.*]] = fpext <32 x half> [[A]] to <32 x float> +// CHECK-NEXT: [[ADD:%.*]] = fadd <32 x float> [[CONV2]], [[CONV]] +// CHECK-NEXT: [[CONV3:%.*]] = fptrunc <32 x float> [[ADD]] to <32 x half> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8f16.v32f16( undef, <32 x half> [[CONV3]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float16_t add_inplace_f16(fixed_float16_t a, fixed_float16_t b) { + return a += b; +} + +// CHECK-LABEL: @add_inplace_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = fadd <16 x float> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.v16f32( undef, <16 x float> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float32_t add_inplace_f32(fixed_float32_t a, fixed_float32_t b) { + return a += b; +} + +// CHECK-LABEL: @add_inplace_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[ADD:%.*]] = fadd <8 x double> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2f64.v8f64( undef, <8 x double> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float64_t add_inplace_f64(fixed_float64_t a, fixed_float64_t b) { + return a += b; +} + +// CHECK-LABEL: @add_scalar_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add <64 x i8> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t add_scalar_i8(fixed_int8_t a, int8_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add <32 x i16> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t add_scalar_i16(fixed_int16_t a, int16_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add <16 x i32> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t add_scalar_i32(fixed_int32_t a, int32_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add <8 x i64> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t add_scalar_i64(fixed_int64_t a, int64_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add <64 x i8> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t add_scalar_u8(fixed_uint8_t a, uint8_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add <32 x i16> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t add_scalar_u16(fixed_uint16_t a, uint16_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add <16 x i32> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t add_scalar_u32(fixed_uint32_t a, uint32_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add <8 x i64> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t add_scalar_u64(fixed_uint64_t a, uint64_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x half> poison, half [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x half> [[SPLAT_SPLATINSERT]], <32 x half> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = fadd <32 x half> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8f16.v32f16( undef, <32 x half> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float16_t add_scalar_f16(fixed_float16_t a, __fp16 b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x float> poison, float [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x float> [[SPLAT_SPLATINSERT]], <16 x float> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = fadd <16 x float> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.v16f32( undef, <16 x float> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float32_t add_scalar_f32(fixed_float32_t a, float b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x double> poison, double [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x double> [[SPLAT_SPLATINSERT]], <8 x double> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = fadd <8 x double> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2f64.v8f64( undef, <8 x double> [[ADD]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float64_t add_scalar_f64(fixed_float64_t a, double b) { + return a + b; +} + +// SUBTRACTION + +// CHECK-LABEL: @sub_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t sub_i8(fixed_int8_t a, fixed_int8_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t sub_i16(fixed_int16_t a, fixed_int16_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t sub_i32(fixed_int32_t a, fixed_int32_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t sub_i64(fixed_int64_t a, fixed_int64_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t sub_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t sub_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t sub_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t sub_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = fpext <32 x half> [[A]] to <32 x float> +// CHECK-NEXT: [[CONV2:%.*]] = fpext <32 x half> [[B]] to <32 x float> +// CHECK-NEXT: [[SUB:%.*]] = fsub <32 x float> [[CONV]], [[CONV2]] +// CHECK-NEXT: [[CONV3:%.*]] = fptrunc <32 x float> [[SUB]] to <32 x half> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8f16.v32f16( undef, <32 x half> [[CONV3]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float16_t sub_f16(fixed_float16_t a, fixed_float16_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = fsub <16 x float> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.v16f32( undef, <16 x float> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float32_t sub_f32(fixed_float32_t a, fixed_float32_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = fsub <8 x double> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2f64.v8f64( undef, <8 x double> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float64_t sub_f64(fixed_float64_t a, fixed_float64_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_inplace_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t sub_inplace_i8(fixed_int8_t a, fixed_int8_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_inplace_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t sub_inplace_i16(fixed_int16_t a, fixed_int16_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_inplace_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t sub_inplace_i32(fixed_int32_t a, fixed_int32_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_inplace_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t sub_inplace_i64(fixed_int64_t a, fixed_int64_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_inplace_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t sub_inplace_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_inplace_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t sub_inplace_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_inplace_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t sub_inplace_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_inplace_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = sub <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t sub_inplace_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_inplace_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = fpext <32 x half> [[A]] to <32 x float> +// CHECK-NEXT: [[CONV2:%.*]] = fpext <32 x half> [[B]] to <32 x float> +// CHECK-NEXT: [[SUB:%.*]] = fsub <32 x float> [[CONV]], [[CONV2]] +// CHECK-NEXT: [[CONV3:%.*]] = fptrunc <32 x float> [[SUB]] to <32 x half> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8f16.v32f16( undef, <32 x half> [[CONV3]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float16_t sub_inplace_f16(fixed_float16_t a, fixed_float16_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_inplace_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = fsub <16 x float> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.v16f32( undef, <16 x float> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float32_t sub_inplace_f32(fixed_float32_t a, fixed_float32_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_inplace_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SUB:%.*]] = fsub <8 x double> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2f64.v8f64( undef, <8 x double> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float64_t sub_inplace_f64(fixed_float64_t a, fixed_float64_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub <64 x i8> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t sub_scalar_i8(fixed_int8_t a, int8_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub <32 x i16> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t sub_scalar_i16(fixed_int16_t a, int16_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub <16 x i32> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t sub_scalar_i32(fixed_int32_t a, int32_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub <8 x i64> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t sub_scalar_i64(fixed_int64_t a, int64_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub <64 x i8> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t sub_scalar_u8(fixed_uint8_t a, uint8_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub <32 x i16> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t sub_scalar_u16(fixed_uint16_t a, uint16_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub <16 x i32> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t sub_scalar_u32(fixed_uint32_t a, uint32_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub <8 x i64> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t sub_scalar_u64(fixed_uint64_t a, uint64_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x half> poison, half [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x half> [[SPLAT_SPLATINSERT]], <32 x half> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = fsub <32 x half> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8f16.v32f16( undef, <32 x half> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float16_t sub_scalar_f16(fixed_float16_t a, __fp16 b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x float> poison, float [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x float> [[SPLAT_SPLATINSERT]], <16 x float> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = fsub <16 x float> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.v16f32( undef, <16 x float> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float32_t sub_scalar_f32(fixed_float32_t a, float b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x double> poison, double [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x double> [[SPLAT_SPLATINSERT]], <8 x double> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = fsub <8 x double> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2f64.v8f64( undef, <8 x double> [[SUB]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float64_t sub_scalar_f64(fixed_float64_t a, double b) { + return a - b; +} + +// MULTIPLICATION + +// CHECK-LABEL: @mul_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t mul_i8(fixed_int8_t a, fixed_int8_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t mul_i16(fixed_int16_t a, fixed_int16_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t mul_i32(fixed_int32_t a, fixed_int32_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t mul_i64(fixed_int64_t a, fixed_int64_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t mul_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t mul_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t mul_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t mul_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = fpext <32 x half> [[A]] to <32 x float> +// CHECK-NEXT: [[CONV2:%.*]] = fpext <32 x half> [[B]] to <32 x float> +// CHECK-NEXT: [[MUL:%.*]] = fmul <32 x float> [[CONV]], [[CONV2]] +// CHECK-NEXT: [[CONV3:%.*]] = fptrunc <32 x float> [[MUL]] to <32 x half> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8f16.v32f16( undef, <32 x half> [[CONV3]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float16_t mul_f16(fixed_float16_t a, fixed_float16_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = fmul <16 x float> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.v16f32( undef, <16 x float> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float32_t mul_f32(fixed_float32_t a, fixed_float32_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = fmul <8 x double> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2f64.v8f64( undef, <8 x double> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float64_t mul_f64(fixed_float64_t a, fixed_float64_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_inplace_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t mul_inplace_i8(fixed_int8_t a, fixed_int8_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_inplace_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t mul_inplace_i16(fixed_int16_t a, fixed_int16_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_inplace_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t mul_inplace_i32(fixed_int32_t a, fixed_int32_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_inplace_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t mul_inplace_i64(fixed_int64_t a, fixed_int64_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_inplace_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t mul_inplace_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_inplace_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t mul_inplace_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_inplace_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t mul_inplace_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_inplace_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = mul <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t mul_inplace_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_inplace_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = fpext <32 x half> [[A]] to <32 x float> +// CHECK-NEXT: [[CONV2:%.*]] = fpext <32 x half> [[B]] to <32 x float> +// CHECK-NEXT: [[MUL:%.*]] = fmul <32 x float> [[CONV]], [[CONV2]] +// CHECK-NEXT: [[CONV3:%.*]] = fptrunc <32 x float> [[MUL]] to <32 x half> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8f16.v32f16( undef, <32 x half> [[CONV3]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float16_t mul_inplace_f16(fixed_float16_t a, fixed_float16_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_inplace_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = fmul <16 x float> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.v16f32( undef, <16 x float> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float32_t mul_inplace_f32(fixed_float32_t a, fixed_float32_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_inplace_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[MUL:%.*]] = fmul <8 x double> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2f64.v8f64( undef, <8 x double> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float64_t mul_inplace_f64(fixed_float64_t a, fixed_float64_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul <64 x i8> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t mul_scalar_i8(fixed_int8_t a, int8_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul <32 x i16> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t mul_scalar_i16(fixed_int16_t a, int16_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul <16 x i32> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t mul_scalar_i32(fixed_int32_t a, int32_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul <8 x i64> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t mul_scalar_i64(fixed_int64_t a, int64_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul <64 x i8> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t mul_scalar_u8(fixed_uint8_t a, uint8_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul <32 x i16> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t mul_scalar_u16(fixed_uint16_t a, uint16_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul <16 x i32> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t mul_scalar_u32(fixed_uint32_t a, uint32_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul <8 x i64> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t mul_scalar_u64(fixed_uint64_t a, uint64_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x half> poison, half [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x half> [[SPLAT_SPLATINSERT]], <32 x half> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = fmul <32 x half> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8f16.v32f16( undef, <32 x half> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float16_t mul_scalar_f16(fixed_float16_t a, __fp16 b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x float> poison, float [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x float> [[SPLAT_SPLATINSERT]], <16 x float> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = fmul <16 x float> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.v16f32( undef, <16 x float> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float32_t mul_scalar_f32(fixed_float32_t a, float b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x double> poison, double [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x double> [[SPLAT_SPLATINSERT]], <8 x double> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = fmul <8 x double> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2f64.v8f64( undef, <8 x double> [[MUL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float64_t mul_scalar_f64(fixed_float64_t a, double b) { + return a * b; +} + +// DIVISION + +// CHECK-LABEL: @div_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = sdiv <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t div_i8(fixed_int8_t a, fixed_int8_t b) { + return a / b; +} + +// CHECK-LABEL: @div_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = sdiv <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t div_i16(fixed_int16_t a, fixed_int16_t b) { + return a / b; +} + +// CHECK-LABEL: @div_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = sdiv <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t div_i32(fixed_int32_t a, fixed_int32_t b) { + return a / b; +} + +// CHECK-LABEL: @div_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = sdiv <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t div_i64(fixed_int64_t a, fixed_int64_t b) { + return a / b; +} + +// CHECK-LABEL: @div_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = udiv <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t div_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a / b; +} + +// CHECK-LABEL: @div_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = udiv <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t div_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a / b; +} + +// CHECK-LABEL: @div_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = udiv <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t div_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a / b; +} + +// CHECK-LABEL: @div_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = udiv <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t div_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a / b; +} + +// CHECK-LABEL: @div_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = fpext <32 x half> [[A]] to <32 x float> +// CHECK-NEXT: [[CONV2:%.*]] = fpext <32 x half> [[B]] to <32 x float> +// CHECK-NEXT: [[DIV:%.*]] = fdiv <32 x float> [[CONV]], [[CONV2]] +// CHECK-NEXT: [[CONV3:%.*]] = fptrunc <32 x float> [[DIV]] to <32 x half> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8f16.v32f16( undef, <32 x half> [[CONV3]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float16_t div_f16(fixed_float16_t a, fixed_float16_t b) { + return a / b; +} + +// CHECK-LABEL: @div_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = fdiv <16 x float> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.v16f32( undef, <16 x float> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float32_t div_f32(fixed_float32_t a, fixed_float32_t b) { + return a / b; +} + +// CHECK-LABEL: @div_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = fdiv <8 x double> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2f64.v8f64( undef, <8 x double> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float64_t div_f64(fixed_float64_t a, fixed_float64_t b) { + return a / b; +} + +// CHECK-LABEL: @div_inplace_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = sdiv <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t div_inplace_i8(fixed_int8_t a, fixed_int8_t b) { + return a / b; +} + +// CHECK-LABEL: @div_inplace_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = sdiv <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t div_inplace_i16(fixed_int16_t a, fixed_int16_t b) { + return a / b; +} + +// CHECK-LABEL: @div_inplace_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = sdiv <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t div_inplace_i32(fixed_int32_t a, fixed_int32_t b) { + return a / b; +} + +// CHECK-LABEL: @div_inplace_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = sdiv <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t div_inplace_i64(fixed_int64_t a, fixed_int64_t b) { + return a / b; +} + +// CHECK-LABEL: @div_inplace_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = udiv <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t div_inplace_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a / b; +} + +// CHECK-LABEL: @div_inplace_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = udiv <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t div_inplace_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a / b; +} + +// CHECK-LABEL: @div_inplace_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = udiv <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t div_inplace_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a / b; +} + +// CHECK-LABEL: @div_inplace_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = udiv <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t div_inplace_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a / b; +} + +// CHECK-LABEL: @div_inplace_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = fpext <32 x half> [[A]] to <32 x float> +// CHECK-NEXT: [[CONV2:%.*]] = fpext <32 x half> [[B]] to <32 x float> +// CHECK-NEXT: [[DIV:%.*]] = fdiv <32 x float> [[CONV]], [[CONV2]] +// CHECK-NEXT: [[CONV3:%.*]] = fptrunc <32 x float> [[DIV]] to <32 x half> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8f16.v32f16( undef, <32 x half> [[CONV3]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float16_t div_inplace_f16(fixed_float16_t a, fixed_float16_t b) { + return a / b; +} + +// CHECK-LABEL: @div_inplace_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = fdiv <16 x float> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.v16f32( undef, <16 x float> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float32_t div_inplace_f32(fixed_float32_t a, fixed_float32_t b) { + return a / b; +} + +// CHECK-LABEL: @div_inplace_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[DIV:%.*]] = fdiv <8 x double> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2f64.v8f64( undef, <8 x double> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float64_t div_inplace_f64(fixed_float64_t a, fixed_float64_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = sdiv <64 x i8> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t div_scalar_i8(fixed_int8_t a, int8_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = sdiv <32 x i16> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t div_scalar_i16(fixed_int16_t a, int16_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = sdiv <16 x i32> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t div_scalar_i32(fixed_int32_t a, int32_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = sdiv <8 x i64> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t div_scalar_i64(fixed_int64_t a, int64_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = udiv <64 x i8> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t div_scalar_u8(fixed_uint8_t a, uint8_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = udiv <32 x i16> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t div_scalar_u16(fixed_uint16_t a, uint16_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = udiv <16 x i32> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t div_scalar_u32(fixed_uint32_t a, uint32_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = udiv <8 x i64> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t div_scalar_u64(fixed_uint64_t a, uint64_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x half> poison, half [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x half> [[SPLAT_SPLATINSERT]], <32 x half> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = fdiv <32 x half> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8f16.v32f16( undef, <32 x half> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float16_t div_scalar_f16(fixed_float16_t a, __fp16 b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x float> poison, float [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x float> [[SPLAT_SPLATINSERT]], <16 x float> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = fdiv <16 x float> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.v16f32( undef, <16 x float> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float32_t div_scalar_f32(fixed_float32_t a, float b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x double> poison, double [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x double> [[SPLAT_SPLATINSERT]], <8 x double> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = fdiv <8 x double> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2f64.v8f64( undef, <8 x double> [[DIV]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_float64_t div_scalar_f64(fixed_float64_t a, double b) { + return a / b; +} + +// REMAINDER + +// CHECK-LABEL: @rem_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = srem <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t rem_i8(fixed_int8_t a, fixed_int8_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = srem <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t rem_i16(fixed_int16_t a, fixed_int16_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = srem <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t rem_i32(fixed_int32_t a, fixed_int32_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = srem <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t rem_i64(fixed_int64_t a, fixed_int64_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = urem <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t rem_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = urem <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t rem_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = urem <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t rem_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = urem <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t rem_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_inplace_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = srem <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t rem_inplace_i8(fixed_int8_t a, fixed_int8_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_inplace_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = srem <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t rem_inplace_i16(fixed_int16_t a, fixed_int16_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_inplace_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = srem <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t rem_inplace_i32(fixed_int32_t a, fixed_int32_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_inplace_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = srem <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t rem_inplace_i64(fixed_int64_t a, fixed_int64_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_inplace_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = urem <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t rem_inplace_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_inplace_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = urem <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t rem_inplace_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_inplace_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = urem <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t rem_inplace_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_inplace_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[REM:%.*]] = urem <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t rem_inplace_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = srem <64 x i8> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t rem_scalar_i8(fixed_int8_t a, int8_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = srem <32 x i16> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t rem_scalar_i16(fixed_int16_t a, int16_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = srem <16 x i32> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t rem_scalar_i32(fixed_int32_t a, int32_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = srem <8 x i64> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t rem_scalar_i64(fixed_int64_t a, int64_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = urem <64 x i8> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t rem_scalar_u8(fixed_uint8_t a, uint8_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = urem <32 x i16> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t rem_scalar_u16(fixed_uint16_t a, uint16_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = urem <16 x i32> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t rem_scalar_u32(fixed_uint32_t a, uint32_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = urem <8 x i64> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[REM]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t rem_scalar_u64(fixed_uint64_t a, uint64_t b) { + return a % b; +} diff --git a/clang/test/CodeGen/aarch64-sve-vls-bitwise-ops.c b/clang/test/CodeGen/aarch64-sve-vls-bitwise-ops.c new file mode 100644 index 0000000000000..b77d2bd63c3bd --- /dev/null +++ b/clang/test/CodeGen/aarch64-sve-vls-bitwise-ops.c @@ -0,0 +1,468 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \ +// RUN: -fallow-half-arguments-and-returns -disable-O0-optnone -mvscale-min=4 -mvscale-max=4 \ +// RUN: -emit-llvm -o - %s | opt -S -sroa | FileCheck %s + +// REQUIRES: aarch64-registered-target + +#include + +#define N 512 + +typedef svint8_t fixed_int8_t __attribute__((arm_sve_vector_bits(N))); +typedef svint16_t fixed_int16_t __attribute__((arm_sve_vector_bits(N))); +typedef svint32_t fixed_int32_t __attribute__((arm_sve_vector_bits(N))); +typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svuint8_t fixed_uint8_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint16_t fixed_uint16_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint32_t fixed_uint32_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint64_t fixed_uint64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svfloat16_t fixed_float16_t __attribute__((arm_sve_vector_bits(N))); +typedef svfloat32_t fixed_float32_t __attribute__((arm_sve_vector_bits(N))); +typedef svfloat64_t fixed_float64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N))); + +// AND + +// CHECK-LABEL: @and_bool( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_COERCE:%.*]] = bitcast [[TMP0:%.*]] to +// CHECK-NEXT: [[A:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[A_COERCE]], i64 0) +// CHECK-NEXT: [[B_COERCE:%.*]] = bitcast [[TMP1:%.*]] to +// CHECK-NEXT: [[B:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[B_COERCE]], i64 0) +// CHECK-NEXT: [[AND:%.*]] = and <8 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[AND]], i64 0) +// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CASTSCALABLESVE]] to +// CHECK-NEXT: ret [[TMP2]] +// +fixed_bool_t and_bool(fixed_bool_t a, fixed_bool_t b) { + return a & b; +} + +// CHECK-LABEL: @and_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[AND:%.*]] = and <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[AND]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t and_i8(fixed_int8_t a, fixed_int8_t b) { + return a & b; +} + +// CHECK-LABEL: @and_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[AND:%.*]] = and <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[AND]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t and_i16(fixed_int16_t a, fixed_int16_t b) { + return a & b; +} + +// CHECK-LABEL: @and_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[AND:%.*]] = and <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[AND]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t and_i32(fixed_int32_t a, fixed_int32_t b) { + return a & b; +} + +// CHECK-LABEL: @and_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[AND:%.*]] = and <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[AND]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t and_i64(fixed_int64_t a, fixed_int64_t b) { + return a & b; +} + +// CHECK-LABEL: @and_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[AND:%.*]] = and <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[AND]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t and_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a & b; +} + +// CHECK-LABEL: @and_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[AND:%.*]] = and <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[AND]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t and_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a & b; +} + +// CHECK-LABEL: @and_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[AND:%.*]] = and <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[AND]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t and_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a & b; +} + +// CHECK-LABEL: @and_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[AND:%.*]] = and <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[AND]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t and_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a & b; +} + +// OR + +// CHECK-LABEL: @or_bool( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_COERCE:%.*]] = bitcast [[TMP0:%.*]] to +// CHECK-NEXT: [[A:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[A_COERCE]], i64 0) +// CHECK-NEXT: [[B_COERCE:%.*]] = bitcast [[TMP1:%.*]] to +// CHECK-NEXT: [[B:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[B_COERCE]], i64 0) +// CHECK-NEXT: [[OR:%.*]] = or <8 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[OR]], i64 0) +// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CASTSCALABLESVE]] to +// CHECK-NEXT: ret [[TMP2]] +// +fixed_bool_t or_bool(fixed_bool_t a, fixed_bool_t b) { + return a | b; +} + +// CHECK-LABEL: @or_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[OR:%.*]] = or <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[OR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t or_i8(fixed_int8_t a, fixed_int8_t b) { + return a | b; +} + +// CHECK-LABEL: @or_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[OR:%.*]] = or <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[OR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t or_i16(fixed_int16_t a, fixed_int16_t b) { + return a | b; +} + +// CHECK-LABEL: @or_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[OR:%.*]] = or <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[OR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t or_i32(fixed_int32_t a, fixed_int32_t b) { + return a | b; +} + +// CHECK-LABEL: @or_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[OR:%.*]] = or <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[OR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t or_i64(fixed_int64_t a, fixed_int64_t b) { + return a | b; +} + +// CHECK-LABEL: @or_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[OR:%.*]] = or <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[OR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t or_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a | b; +} + +// CHECK-LABEL: @or_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[OR:%.*]] = or <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[OR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t or_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a | b; +} + +// CHECK-LABEL: @or_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[OR:%.*]] = or <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[OR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t or_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a | b; +} + +// CHECK-LABEL: @or_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[OR:%.*]] = or <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[OR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t or_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a | b; +} + +// XOR + +// CHECK-LABEL: @xor_bool( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_COERCE:%.*]] = bitcast [[TMP0:%.*]] to +// CHECK-NEXT: [[A:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[A_COERCE]], i64 0) +// CHECK-NEXT: [[B_COERCE:%.*]] = bitcast [[TMP1:%.*]] to +// CHECK-NEXT: [[B:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[B_COERCE]], i64 0) +// CHECK-NEXT: [[XOR:%.*]] = xor <8 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[XOR]], i64 0) +// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CASTSCALABLESVE]] to +// CHECK-NEXT: ret [[TMP2]] +// +fixed_bool_t xor_bool(fixed_bool_t a, fixed_bool_t b) { + return a ^ b; +} + +// CHECK-LABEL: @xor_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[XOR:%.*]] = xor <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t xor_i8(fixed_int8_t a, fixed_int8_t b) { + return a ^ b; +} + +// CHECK-LABEL: @xor_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[XOR:%.*]] = xor <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t xor_i16(fixed_int16_t a, fixed_int16_t b) { + return a ^ b; +} + +// CHECK-LABEL: @xor_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[XOR:%.*]] = xor <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t xor_i32(fixed_int32_t a, fixed_int32_t b) { + return a ^ b; +} + +// CHECK-LABEL: @xor_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[XOR:%.*]] = xor <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t xor_i64(fixed_int64_t a, fixed_int64_t b) { + return a ^ b; +} + +// CHECK-LABEL: @xor_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[XOR:%.*]] = xor <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t xor_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a ^ b; +} + +// CHECK-LABEL: @xor_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[XOR:%.*]] = xor <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t xor_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a ^ b; +} + +// CHECK-LABEL: @xor_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[XOR:%.*]] = xor <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t xor_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a ^ b; +} + +// CHECK-LABEL: @xor_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[XOR:%.*]] = xor <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t xor_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a ^ b; +} + +// NEG + +// CHECK-LABEL: @neg_bool( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_COERCE:%.*]] = bitcast [[TMP0:%.*]] to +// CHECK-NEXT: [[A:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[A_COERCE]], i64 0) +// CHECK-NEXT: [[NEG:%.*]] = xor <8 x i8> [[A]], +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[NEG]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = bitcast [[CASTSCALABLESVE]] to +// CHECK-NEXT: ret [[TMP1]] +// +fixed_bool_t neg_bool(fixed_bool_t a) { + return ~a; +} + +// CHECK-LABEL: @neg_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[NEG:%.*]] = xor <64 x i8> [[A]], +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[NEG]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t neg_i8(fixed_int8_t a) { + return ~a; +} + +// CHECK-LABEL: @neg_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[NEG:%.*]] = xor <32 x i16> [[A]], +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[NEG]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t neg_i16(fixed_int16_t a) { + return ~a; +} + +// CHECK-LABEL: @neg_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[NEG:%.*]] = xor <16 x i32> [[A]], +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[NEG]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t neg_i32(fixed_int32_t a) { + return ~a; +} + +// CHECK-LABEL: @neg_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[NEG:%.*]] = xor <8 x i64> [[A]], +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[NEG]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t neg_i64(fixed_int64_t a) { + return ~a; +} + +// CHECK-LABEL: @neg_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[NEG:%.*]] = xor <64 x i8> [[A]], +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[NEG]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t neg_u8(fixed_uint8_t a) { + return ~a; +} + +// CHECK-LABEL: @neg_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[NEG:%.*]] = xor <32 x i16> [[A]], +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[NEG]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t neg_u16(fixed_uint16_t a) { + return ~a; +} + +// CHECK-LABEL: @neg_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[NEG:%.*]] = xor <16 x i32> [[A]], +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[NEG]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t neg_u32(fixed_uint32_t a) { + return ~a; +} + +// CHECK-LABEL: @neg_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[NEG:%.*]] = xor <8 x i64> [[A]], +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[NEG]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t neg_u64(fixed_uint64_t a) { + return ~a; +} diff --git a/clang/test/CodeGen/aarch64-sve-vls-compare-ops.c b/clang/test/CodeGen/aarch64-sve-vls-compare-ops.c new file mode 100644 index 0000000000000..f6c6672336dde --- /dev/null +++ b/clang/test/CodeGen/aarch64-sve-vls-compare-ops.c @@ -0,0 +1,1010 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \ +// RUN: -fallow-half-arguments-and-returns -disable-O0-optnone -mvscale-min=4 -mvscale-max=4 \ +// RUN: -emit-llvm -o - %s | opt -S -sroa | FileCheck %s + +// REQUIRES: aarch64-registered-target + +#include + +#define N 512 + +typedef svint8_t fixed_int8_t __attribute__((arm_sve_vector_bits(N))); +typedef svint16_t fixed_int16_t __attribute__((arm_sve_vector_bits(N))); +typedef svint32_t fixed_int32_t __attribute__((arm_sve_vector_bits(N))); +typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svuint8_t fixed_uint8_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint16_t fixed_uint16_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint32_t fixed_uint32_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint64_t fixed_uint64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svfloat16_t fixed_float16_t __attribute__((arm_sve_vector_bits(N))); +typedef svfloat32_t fixed_float32_t __attribute__((arm_sve_vector_bits(N))); +typedef svfloat64_t fixed_float64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N))); + +// EQ + +// CHECK-LABEL: @eq_bool( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_COERCE:%.*]] = bitcast [[TMP0:%.*]] to +// CHECK-NEXT: [[A:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[A_COERCE]], i64 0) +// CHECK-NEXT: [[B_COERCE:%.*]] = bitcast [[TMP1:%.*]] to +// CHECK-NEXT: [[B:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[B_COERCE]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp eq <8 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CASTSCALABLESVE]] to +// CHECK-NEXT: ret [[TMP2]] +// +fixed_bool_t eq_bool(fixed_bool_t a, fixed_bool_t b) { + return a == b; +} + +// CHECK-LABEL: @eq_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp eq <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <64 x i1> [[CMP]] to <64 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t eq_i8(fixed_int8_t a, fixed_int8_t b) { + return a == b; +} + +// CHECK-LABEL: @eq_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp eq <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t eq_i16(fixed_int16_t a, fixed_int16_t b) { + return a == b; +} + +// CHECK-LABEL: @eq_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp eq <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t eq_i32(fixed_int32_t a, fixed_int32_t b) { + return a == b; +} + +// CHECK-LABEL: @eq_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp eq <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t eq_i64(fixed_int64_t a, fixed_int64_t b) { + return a == b; +} + +// CHECK-LABEL: @eq_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp eq <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <64 x i1> [[CMP]] to <64 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t eq_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a == b; +} + +// CHECK-LABEL: @eq_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp eq <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t eq_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a == b; +} + +// CHECK-LABEL: @eq_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp eq <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t eq_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a == b; +} + +// CHECK-LABEL: @eq_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp eq <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t eq_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a == b; +} + +// CHECK-LABEL: @eq_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = fpext <32 x half> [[A]] to <32 x float> +// CHECK-NEXT: [[CONV2:%.*]] = fpext <32 x half> [[B]] to <32 x float> +// CHECK-NEXT: [[CMP:%.*]] = fcmp oeq <32 x float> [[CONV]], [[CONV2]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i32> +// CHECK-NEXT: [[CONV3:%.*]] = trunc <32 x i32> [[SEXT]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[CONV3]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t eq_f16(fixed_float16_t a, fixed_float16_t b) { + return a == b; +} + +// CHECK-LABEL: @eq_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = fcmp oeq <16 x float> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t eq_f32(fixed_float32_t a, fixed_float32_t b) { + return a == b; +} + +// CHECK-LABEL: @eq_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = fcmp oeq <8 x double> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t eq_f64(fixed_float64_t a, fixed_float64_t b) { + return a == b; +} + +// NEQ + +// CHECK-LABEL: @neq_bool( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_COERCE:%.*]] = bitcast [[TMP0:%.*]] to +// CHECK-NEXT: [[A:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[A_COERCE]], i64 0) +// CHECK-NEXT: [[B_COERCE:%.*]] = bitcast [[TMP1:%.*]] to +// CHECK-NEXT: [[B:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[B_COERCE]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ne <8 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CASTSCALABLESVE]] to +// CHECK-NEXT: ret [[TMP2]] +// +fixed_bool_t neq_bool(fixed_bool_t a, fixed_bool_t b) { + return a != b; +} + +// CHECK-LABEL: @neq_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ne <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <64 x i1> [[CMP]] to <64 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t neq_i8(fixed_int8_t a, fixed_int8_t b) { + return a != b; +} + +// CHECK-LABEL: @neq_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ne <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t neq_i16(fixed_int16_t a, fixed_int16_t b) { + return a != b; +} + +// CHECK-LABEL: @neq_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ne <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t neq_i32(fixed_int32_t a, fixed_int32_t b) { + return a != b; +} + +// CHECK-LABEL: @neq_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ne <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t neq_i64(fixed_int64_t a, fixed_int64_t b) { + return a != b; +} + +// CHECK-LABEL: @neq_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ne <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <64 x i1> [[CMP]] to <64 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t neq_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a != b; +} + +// CHECK-LABEL: @neq_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ne <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t neq_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a != b; +} + +// CHECK-LABEL: @neq_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ne <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t neq_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a != b; +} + +// CHECK-LABEL: @neq_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ne <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t neq_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a != b; +} + +// CHECK-LABEL: @neq_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = fpext <32 x half> [[A]] to <32 x float> +// CHECK-NEXT: [[CONV2:%.*]] = fpext <32 x half> [[B]] to <32 x float> +// CHECK-NEXT: [[CMP:%.*]] = fcmp une <32 x float> [[CONV]], [[CONV2]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i32> +// CHECK-NEXT: [[CONV3:%.*]] = trunc <32 x i32> [[SEXT]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[CONV3]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t neq_f16(fixed_float16_t a, fixed_float16_t b) { + return a != b; +} + +// CHECK-LABEL: @neq_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = fcmp une <16 x float> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t neq_f32(fixed_float32_t a, fixed_float32_t b) { + return a != b; +} + +// CHECK-LABEL: @neq_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = fcmp une <8 x double> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t neq_f64(fixed_float64_t a, fixed_float64_t b) { + return a != b; +} + +// LT + +// CHECK-LABEL: @lt_bool( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_COERCE:%.*]] = bitcast [[TMP0:%.*]] to +// CHECK-NEXT: [[A:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[A_COERCE]], i64 0) +// CHECK-NEXT: [[B_COERCE:%.*]] = bitcast [[TMP1:%.*]] to +// CHECK-NEXT: [[B:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[B_COERCE]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ult <8 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CASTSCALABLESVE]] to +// CHECK-NEXT: ret [[TMP2]] +// +fixed_bool_t lt_bool(fixed_bool_t a, fixed_bool_t b) { + return a < b; +} + +// CHECK-LABEL: @lt_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp slt <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <64 x i1> [[CMP]] to <64 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t lt_i8(fixed_int8_t a, fixed_int8_t b) { + return a < b; +} + +// CHECK-LABEL: @lt_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp slt <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t lt_i16(fixed_int16_t a, fixed_int16_t b) { + return a < b; +} + +// CHECK-LABEL: @lt_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp slt <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t lt_i32(fixed_int32_t a, fixed_int32_t b) { + return a < b; +} + +// CHECK-LABEL: @lt_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp slt <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t lt_i64(fixed_int64_t a, fixed_int64_t b) { + return a < b; +} + +// CHECK-LABEL: @lt_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ult <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <64 x i1> [[CMP]] to <64 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t lt_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a < b; +} + +// CHECK-LABEL: @lt_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ult <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t lt_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a < b; +} + +// CHECK-LABEL: @lt_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ult <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t lt_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a < b; +} + +// CHECK-LABEL: @lt_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ult <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t lt_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a < b; +} + +// CHECK-LABEL: @lt_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = fpext <32 x half> [[A]] to <32 x float> +// CHECK-NEXT: [[CONV2:%.*]] = fpext <32 x half> [[B]] to <32 x float> +// CHECK-NEXT: [[CMP:%.*]] = fcmp olt <32 x float> [[CONV]], [[CONV2]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i32> +// CHECK-NEXT: [[CONV3:%.*]] = trunc <32 x i32> [[SEXT]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[CONV3]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t lt_f16(fixed_float16_t a, fixed_float16_t b) { + return a < b; +} + +// CHECK-LABEL: @lt_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = fcmp olt <16 x float> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t lt_f32(fixed_float32_t a, fixed_float32_t b) { + return a < b; +} + +// CHECK-LABEL: @lt_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = fcmp olt <8 x double> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t lt_f64(fixed_float64_t a, fixed_float64_t b) { + return a < b; +} + +// LEQ + +// CHECK-LABEL: @leq_bool( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_COERCE:%.*]] = bitcast [[TMP0:%.*]] to +// CHECK-NEXT: [[A:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[A_COERCE]], i64 0) +// CHECK-NEXT: [[B_COERCE:%.*]] = bitcast [[TMP1:%.*]] to +// CHECK-NEXT: [[B:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[B_COERCE]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ule <8 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CASTSCALABLESVE]] to +// CHECK-NEXT: ret [[TMP2]] +// +fixed_bool_t leq_bool(fixed_bool_t a, fixed_bool_t b) { + return a <= b; +} + +// CHECK-LABEL: @leq_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp sle <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <64 x i1> [[CMP]] to <64 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t leq_i8(fixed_int8_t a, fixed_int8_t b) { + return a <= b; +} + +// CHECK-LABEL: @leq_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp sle <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t leq_i16(fixed_int16_t a, fixed_int16_t b) { + return a <= b; +} + +// CHECK-LABEL: @leq_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp sle <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t leq_i32(fixed_int32_t a, fixed_int32_t b) { + return a <= b; +} + +// CHECK-LABEL: @leq_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp sle <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t leq_i64(fixed_int64_t a, fixed_int64_t b) { + return a <= b; +} + +// CHECK-LABEL: @leq_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ule <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <64 x i1> [[CMP]] to <64 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t leq_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a <= b; +} + +// CHECK-LABEL: @leq_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ule <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t leq_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a <= b; +} + +// CHECK-LABEL: @leq_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ule <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t leq_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a <= b; +} + +// CHECK-LABEL: @leq_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ule <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t leq_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a <= b; +} + +// CHECK-LABEL: @leq_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = fpext <32 x half> [[A]] to <32 x float> +// CHECK-NEXT: [[CONV2:%.*]] = fpext <32 x half> [[B]] to <32 x float> +// CHECK-NEXT: [[CMP:%.*]] = fcmp ole <32 x float> [[CONV]], [[CONV2]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i32> +// CHECK-NEXT: [[CONV3:%.*]] = trunc <32 x i32> [[SEXT]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[CONV3]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t leq_f16(fixed_float16_t a, fixed_float16_t b) { + return a <= b; +} + +// CHECK-LABEL: @leq_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = fcmp ole <16 x float> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t leq_f32(fixed_float32_t a, fixed_float32_t b) { + return a <= b; +} + +// CHECK-LABEL: @leq_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = fcmp ole <8 x double> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t leq_f64(fixed_float64_t a, fixed_float64_t b) { + return a <= b; +} + +// GT + +// CHECK-LABEL: @gt_bool( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_COERCE:%.*]] = bitcast [[TMP0:%.*]] to +// CHECK-NEXT: [[A:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[A_COERCE]], i64 0) +// CHECK-NEXT: [[B_COERCE:%.*]] = bitcast [[TMP1:%.*]] to +// CHECK-NEXT: [[B:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[B_COERCE]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ugt <8 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CASTSCALABLESVE]] to +// CHECK-NEXT: ret [[TMP2]] +// +fixed_bool_t gt_bool(fixed_bool_t a, fixed_bool_t b) { + return a > b; +} + +// CHECK-LABEL: @gt_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp sgt <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <64 x i1> [[CMP]] to <64 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t gt_i8(fixed_int8_t a, fixed_int8_t b) { + return a > b; +} + +// CHECK-LABEL: @gt_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp sgt <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t gt_i16(fixed_int16_t a, fixed_int16_t b) { + return a > b; +} + +// CHECK-LABEL: @gt_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp sgt <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t gt_i32(fixed_int32_t a, fixed_int32_t b) { + return a > b; +} + +// CHECK-LABEL: @gt_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp sgt <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t gt_i64(fixed_int64_t a, fixed_int64_t b) { + return a > b; +} + +// CHECK-LABEL: @gt_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ugt <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <64 x i1> [[CMP]] to <64 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t gt_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a > b; +} + +// CHECK-LABEL: @gt_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ugt <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t gt_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a > b; +} + +// CHECK-LABEL: @gt_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ugt <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t gt_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a > b; +} + +// CHECK-LABEL: @gt_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp ugt <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t gt_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a > b; +} + +// CHECK-LABEL: @gt_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = fpext <32 x half> [[A]] to <32 x float> +// CHECK-NEXT: [[CONV2:%.*]] = fpext <32 x half> [[B]] to <32 x float> +// CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <32 x float> [[CONV]], [[CONV2]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i32> +// CHECK-NEXT: [[CONV3:%.*]] = trunc <32 x i32> [[SEXT]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[CONV3]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t gt_f16(fixed_float16_t a, fixed_float16_t b) { + return a > b; +} + +// CHECK-LABEL: @gt_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <16 x float> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t gt_f32(fixed_float32_t a, fixed_float32_t b) { + return a > b; +} + +// CHECK-LABEL: @gt_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <8 x double> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t gt_f64(fixed_float64_t a, fixed_float64_t b) { + return a > b; +} + +// GEQ + +// CHECK-LABEL: @geq_bool( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_COERCE:%.*]] = bitcast [[TMP0:%.*]] to +// CHECK-NEXT: [[A:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[A_COERCE]], i64 0) +// CHECK-NEXT: [[B_COERCE:%.*]] = bitcast [[TMP1:%.*]] to +// CHECK-NEXT: [[B:%.*]] = call <8 x i8> @llvm.experimental.vector.extract.v8i8.nxv2i8( [[B_COERCE]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp uge <8 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CASTSCALABLESVE]] to +// CHECK-NEXT: ret [[TMP2]] +// +fixed_bool_t geq_bool(fixed_bool_t a, fixed_bool_t b) { + return a >= b; +} + +// CHECK-LABEL: @geq_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp sge <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <64 x i1> [[CMP]] to <64 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t geq_i8(fixed_int8_t a, fixed_int8_t b) { + return a >= b; +} + +// CHECK-LABEL: @geq_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp sge <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t geq_i16(fixed_int16_t a, fixed_int16_t b) { + return a >= b; +} + +// CHECK-LABEL: @geq_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp sge <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t geq_i32(fixed_int32_t a, fixed_int32_t b) { + return a >= b; +} + +// CHECK-LABEL: @geq_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp sge <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t geq_i64(fixed_int64_t a, fixed_int64_t b) { + return a >= b; +} + +// CHECK-LABEL: @geq_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp uge <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <64 x i1> [[CMP]] to <64 x i8> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t geq_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a >= b; +} + +// CHECK-LABEL: @geq_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp uge <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t geq_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a >= b; +} + +// CHECK-LABEL: @geq_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp uge <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t geq_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a >= b; +} + +// CHECK-LABEL: @geq_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = icmp uge <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t geq_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a >= b; +} + +// CHECK-LABEL: @geq_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = fpext <32 x half> [[A]] to <32 x float> +// CHECK-NEXT: [[CONV2:%.*]] = fpext <32 x half> [[B]] to <32 x float> +// CHECK-NEXT: [[CMP:%.*]] = fcmp oge <32 x float> [[CONV]], [[CONV2]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <32 x i1> [[CMP]] to <32 x i32> +// CHECK-NEXT: [[CONV3:%.*]] = trunc <32 x i32> [[SEXT]] to <32 x i16> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[CONV3]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t geq_f16(fixed_float16_t a, fixed_float16_t b) { + return a >= b; +} + +// CHECK-LABEL: @geq_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = fcmp oge <16 x float> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i32> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t geq_f32(fixed_float32_t a, fixed_float32_t b) { + return a >= b; +} + +// CHECK-LABEL: @geq_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CMP:%.*]] = fcmp oge <8 x double> [[A]], [[B]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <8 x i1> [[CMP]] to <8 x i64> +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SEXT]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t geq_f64(fixed_float64_t a, fixed_float64_t b) { + return a >= b; +} diff --git a/clang/test/CodeGen/aarch64-sve-vls-shift-ops.c b/clang/test/CodeGen/aarch64-sve-vls-shift-ops.c new file mode 100644 index 0000000000000..b431649cc7395 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sve-vls-shift-ops.c @@ -0,0 +1,650 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \ +// RUN: -fallow-half-arguments-and-returns -disable-O0-optnone -mvscale-min=4 -mvscale-max=4 \ +// RUN: -emit-llvm -o - %s | opt -S -sroa | FileCheck %s + +// REQUIRES: aarch64-registered-target + +#include + +#define N 512 + +typedef svint8_t fixed_int8_t __attribute__((arm_sve_vector_bits(N))); +typedef svint16_t fixed_int16_t __attribute__((arm_sve_vector_bits(N))); +typedef svint32_t fixed_int32_t __attribute__((arm_sve_vector_bits(N))); +typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svuint8_t fixed_uint8_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint16_t fixed_uint16_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint32_t fixed_uint32_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint64_t fixed_uint64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svfloat16_t fixed_float16_t __attribute__((arm_sve_vector_bits(N))); +typedef svfloat32_t fixed_float32_t __attribute__((arm_sve_vector_bits(N))); +typedef svfloat64_t fixed_float64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N))); + +// CHECK-LABEL: @lshift_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHL:%.*]] = shl <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t lshift_i8(fixed_int8_t a, fixed_int8_t b) { + return a << b; +} + +// CHECK-LABEL: @rshift_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHR:%.*]] = ashr <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t rshift_i8(fixed_int8_t a, fixed_int8_t b) { + return a >> b; +} + +// CHECK-LABEL: @lshift_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHL:%.*]] = shl <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t lshift_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a << b; +} + +// CHECK-LABEL: @rshift_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHR:%.*]] = lshr <64 x i8> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t rshift_u8(fixed_uint8_t a, fixed_uint8_t b) { + return a >> b; +} + +// CHECK-LABEL: @lshift_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHL:%.*]] = shl <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t lshift_i16(fixed_int16_t a, fixed_int16_t b) { + return a << b; +} + +// CHECK-LABEL: @rshift_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHR:%.*]] = ashr <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t rshift_i16(fixed_int16_t a, fixed_int16_t b) { + return a >> b; +} + +// CHECK-LABEL: @lshift_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHL:%.*]] = shl <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t lshift_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a << b; +} + +// CHECK-LABEL: @rshift_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHR:%.*]] = lshr <32 x i16> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t rshift_u16(fixed_uint16_t a, fixed_uint16_t b) { + return a >> b; +} + +// CHECK-LABEL: @lshift_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHL:%.*]] = shl <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t lshift_i32(fixed_int32_t a, fixed_int32_t b) { + return a << b; +} + +// CHECK-LABEL: @rshift_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHR:%.*]] = ashr <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t rshift_i32(fixed_int32_t a, fixed_int32_t b) { + return a >> b; +} + +// CHECK-LABEL: @lshift_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHL:%.*]] = shl <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t lshift_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a << b; +} + +// CHECK-LABEL: @rshift_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHR:%.*]] = lshr <16 x i32> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t rshift_u32(fixed_uint32_t a, fixed_uint32_t b) { + return a >> b; +} + +// CHECK-LABEL: @lshift_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHL:%.*]] = shl <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t lshift_i64(fixed_int64_t a, fixed_int64_t b) { + return a << b; +} + +// CHECK-LABEL: @rshift_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHR:%.*]] = ashr <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t rshift_i64(fixed_int64_t a, fixed_int64_t b) { + return a >> b; +} + +// CHECK-LABEL: @lshift_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHL:%.*]] = shl <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t lshift_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a << b; +} + +// CHECK-LABEL: @rshift_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SHR:%.*]] = lshr <8 x i64> [[A]], [[B]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t rshift_u64(fixed_uint64_t a, fixed_uint64_t b) { + return a >> b; +} + +// CHECK-LABEL: @lshift_i8_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = sext i8 [[B:%.*]] to i32 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i32> poison, i32 [[CONV]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i32> [[SPLAT_SPLATINSERT]], <64 x i32> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM:%.*]] = trunc <64 x i32> [[SPLAT_SPLAT]] to <64 x i8> +// CHECK-NEXT: [[SHL:%.*]] = shl <64 x i8> [[A]], [[SH_PROM]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t lshift_i8_rsplat(fixed_int8_t a, int8_t b) { + return a << b; +} + +// CHECK-LABEL: @lshift_i8_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[SHL:%.*]] = shl <64 x i8> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t lshift_i8_lsplat(fixed_int8_t a, int8_t b) { + return b << a; +} + +// CHECK-LABEL: @rshift_i8_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = sext i8 [[B:%.*]] to i32 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i32> poison, i32 [[CONV]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i32> [[SPLAT_SPLATINSERT]], <64 x i32> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM:%.*]] = trunc <64 x i32> [[SPLAT_SPLAT]] to <64 x i8> +// CHECK-NEXT: [[SHR:%.*]] = ashr <64 x i8> [[A]], [[SH_PROM]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t rshift_i8_rsplat(fixed_int8_t a, int8_t b) { + return a >> b; +} + +// CHECK-LABEL: @rshift_i8_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[SHR:%.*]] = ashr <64 x i8> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int8_t rshift_i8_lsplat(fixed_int8_t a, int8_t b) { + return b >> a; +} + +// CHECK-LABEL: @lshift_u8_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = zext i8 [[B:%.*]] to i32 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i32> poison, i32 [[CONV]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i32> [[SPLAT_SPLATINSERT]], <64 x i32> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM:%.*]] = trunc <64 x i32> [[SPLAT_SPLAT]] to <64 x i8> +// CHECK-NEXT: [[SHL:%.*]] = shl <64 x i8> [[A]], [[SH_PROM]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t lshift_u8_rsplat(fixed_uint8_t a, uint8_t b) { + return a << b; +} + +// CHECK-LABEL: @lshift_u8_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[SHL:%.*]] = shl <64 x i8> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t lshift_u8_lsplat(fixed_uint8_t a, uint8_t b) { + return b << a; +} + +// CHECK-LABEL: @rshift_u8_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = zext i8 [[B:%.*]] to i32 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i32> poison, i32 [[CONV]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i32> [[SPLAT_SPLATINSERT]], <64 x i32> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM:%.*]] = trunc <64 x i32> [[SPLAT_SPLAT]] to <64 x i8> +// CHECK-NEXT: [[SHR:%.*]] = lshr <64 x i8> [[A]], [[SH_PROM]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t rshift_u8_rsplat(fixed_uint8_t a, uint8_t b) { + return a >> b; +} + +// CHECK-LABEL: @rshift_u8_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.experimental.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer +// CHECK-NEXT: [[SHR:%.*]] = lshr <64 x i8> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint8_t rshift_u8_lsplat(fixed_uint8_t a, uint8_t b) { + return b >> a; +} + +// CHECK-LABEL: @lshift_i16_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = sext i16 [[B:%.*]] to i32 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i32> poison, i32 [[CONV]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i32> [[SPLAT_SPLATINSERT]], <32 x i32> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM:%.*]] = trunc <32 x i32> [[SPLAT_SPLAT]] to <32 x i16> +// CHECK-NEXT: [[SHL:%.*]] = shl <32 x i16> [[A]], [[SH_PROM]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t lshift_i16_rsplat(fixed_int16_t a, int16_t b) { + return a << b; +} + +// CHECK-LABEL: @lshift_i16_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[SHL:%.*]] = shl <32 x i16> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t lshift_i16_lsplat(fixed_int16_t a, int16_t b) { + return b << a; +} + +// CHECK-LABEL: @rshift_i16_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = sext i16 [[B:%.*]] to i32 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i32> poison, i32 [[CONV]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i32> [[SPLAT_SPLATINSERT]], <32 x i32> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM:%.*]] = trunc <32 x i32> [[SPLAT_SPLAT]] to <32 x i16> +// CHECK-NEXT: [[SHR:%.*]] = ashr <32 x i16> [[A]], [[SH_PROM]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t rshift_i16_rsplat(fixed_int16_t a, int16_t b) { + return a >> b; +} + +// CHECK-LABEL: @rshift_i16_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[SHR:%.*]] = ashr <32 x i16> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int16_t rshift_i16_lsplat(fixed_int16_t a, int16_t b) { + return b >> a; +} + +// CHECK-LABEL: @lshift_u16_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = zext i16 [[B:%.*]] to i32 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i32> poison, i32 [[CONV]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i32> [[SPLAT_SPLATINSERT]], <32 x i32> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM:%.*]] = trunc <32 x i32> [[SPLAT_SPLAT]] to <32 x i16> +// CHECK-NEXT: [[SHL:%.*]] = shl <32 x i16> [[A]], [[SH_PROM]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t lshift_u16_rsplat(fixed_uint16_t a, uint16_t b) { + return a << b; +} + +// CHECK-LABEL: @lshift_u16_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[SHL:%.*]] = shl <32 x i16> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t lshift_u16_lsplat(fixed_uint16_t a, uint16_t b) { + return b << a; +} + +// CHECK-LABEL: @rshift_u16_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[CONV:%.*]] = zext i16 [[B:%.*]] to i32 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i32> poison, i32 [[CONV]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i32> [[SPLAT_SPLATINSERT]], <32 x i32> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM:%.*]] = trunc <32 x i32> [[SPLAT_SPLAT]] to <32 x i16> +// CHECK-NEXT: [[SHR:%.*]] = lshr <32 x i16> [[A]], [[SH_PROM]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t rshift_u16_rsplat(fixed_uint16_t a, uint16_t b) { + return a >> b; +} + +// CHECK-LABEL: @rshift_u16_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer +// CHECK-NEXT: [[SHR:%.*]] = lshr <32 x i16> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint16_t rshift_u16_lsplat(fixed_uint16_t a, uint16_t b) { + return b >> a; +} + +// CHECK-LABEL: @lshift_i32_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SHL:%.*]] = shl <16 x i32> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t lshift_i32_rsplat(fixed_int32_t a, int32_t b) { + return a << b; +} + +// CHECK-LABEL: @lshift_i32_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SHL:%.*]] = shl <16 x i32> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t lshift_i32_lsplat(fixed_int32_t a, int32_t b) { + return b << a; +} + +// CHECK-LABEL: @rshift_i32_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SHR:%.*]] = ashr <16 x i32> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t rshift_i32_rsplat(fixed_int32_t a, int32_t b) { + return a >> b; +} + +// CHECK-LABEL: @rshift_i32_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SHR:%.*]] = ashr <16 x i32> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int32_t rshift_i32_lsplat(fixed_int32_t a, int32_t b) { + return b >> a; +} + +// CHECK-LABEL: @lshift_u32_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SHL:%.*]] = shl <16 x i32> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t lshift_u32_rsplat(fixed_uint32_t a, uint32_t b) { + return a << b; +} + +// CHECK-LABEL: @lshift_u32_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SHL:%.*]] = shl <16 x i32> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t lshift_u32_lsplat(fixed_uint32_t a, uint32_t b) { + return b << a; +} + +// CHECK-LABEL: @rshift_u32_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SHR:%.*]] = lshr <16 x i32> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t rshift_u32_rsplat(fixed_uint32_t a, uint32_t b) { + return a >> b; +} + +// CHECK-LABEL: @rshift_u32_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SHR:%.*]] = lshr <16 x i32> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint32_t rshift_u32_lsplat(fixed_uint32_t a, uint32_t b) { + return b >> a; +} + +// CHECK-LABEL: @lshift_i64_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SHL:%.*]] = shl <8 x i64> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t lshift_i64_rsplat(fixed_int64_t a, int64_t b) { + return a << b; +} + +// CHECK-LABEL: @lshift_i64_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SHL:%.*]] = shl <8 x i64> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t lshift_i64_lsplat(fixed_int64_t a, int64_t b) { + return b << a; +} + +// CHECK-LABEL: @rshift_i64_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SHR:%.*]] = ashr <8 x i64> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t rshift_i64_rsplat(fixed_int64_t a, int64_t b) { + return a >> b; +} + +// CHECK-LABEL: @rshift_i64_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SHR:%.*]] = ashr <8 x i64> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_int64_t rshift_i64_lsplat(fixed_int64_t a, int64_t b) { + return b >> a; +} + +// CHECK-LABEL: @lshift_u64_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SHL:%.*]] = shl <8 x i64> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t lshift_u64_rsplat(fixed_uint64_t a, uint64_t b) { + return a << b; +} + +// CHECK-LABEL: @lshift_u64_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SHL:%.*]] = shl <8 x i64> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SHL]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t lshift_u64_lsplat(fixed_uint64_t a, uint64_t b) { + return b << a; +} + +// CHECK-LABEL: @rshift_u64_rsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SHR:%.*]] = lshr <8 x i64> [[A]], [[SPLAT_SPLAT]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t rshift_u64_rsplat(fixed_uint64_t a, uint64_t b) { + return a >> b; +} + +// CHECK-LABEL: @rshift_u64_lsplat( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SHR:%.*]] = lshr <8 x i64> [[SPLAT_SPLAT]], [[A]] +// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[SHR]], i64 0) +// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// +fixed_uint64_t rshift_u64_lsplat(fixed_uint64_t a, uint64_t b) { + return b >> a; +} diff --git a/clang/test/CodeGen/aarch64-sve-vls-subscript-ops.c b/clang/test/CodeGen/aarch64-sve-vls-subscript-ops.c new file mode 100644 index 0000000000000..444fab942d782 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sve-vls-subscript-ops.c @@ -0,0 +1,117 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \ +// RUN: -fallow-half-arguments-and-returns -disable-O0-optnone -mvscale-min=4 -mvscale-max=4 \ +// RUN: -emit-llvm -o - %s | opt -S -sroa | FileCheck %s + +// REQUIRES: aarch64-registered-target + +#include +#include + +#define N 512 + +typedef svint8_t fixed_int8_t __attribute__((arm_sve_vector_bits(N))); +typedef svint16_t fixed_int16_t __attribute__((arm_sve_vector_bits(N))); +typedef svint32_t fixed_int32_t __attribute__((arm_sve_vector_bits(N))); +typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svuint8_t fixed_uint8_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint16_t fixed_uint16_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint32_t fixed_uint32_t __attribute__((arm_sve_vector_bits(N))); +typedef svuint64_t fixed_uint64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svfloat16_t fixed_float16_t __attribute__((arm_sve_vector_bits(N))); +typedef svfloat32_t fixed_float32_t __attribute__((arm_sve_vector_bits(N))); +typedef svfloat64_t fixed_float64_t __attribute__((arm_sve_vector_bits(N))); + +typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N))); + +// CHECK-LABEL: @subscript_int16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <32 x i16> [[A]], i64 [[B:%.*]] +// CHECK-NEXT: ret i16 [[VECEXT]] +// +int16_t subscript_int16(fixed_int16_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_uint16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.experimental.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <32 x i16> [[A]], i64 [[B:%.*]] +// CHECK-NEXT: ret i16 [[VECEXT]] +// +uint16_t subscript_uint16(fixed_uint16_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_int32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <16 x i32> [[A]], i64 [[B:%.*]] +// CHECK-NEXT: ret i32 [[VECEXT]] +// +int32_t subscript_int32(fixed_int32_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_uint32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.experimental.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <16 x i32> [[A]], i64 [[B:%.*]] +// CHECK-NEXT: ret i32 [[VECEXT]] +// +uint32_t subscript_uint32(fixed_uint32_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_int64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <8 x i64> [[A]], i64 [[B:%.*]] +// CHECK-NEXT: ret i64 [[VECEXT]] +// +int64_t subscript_int64(fixed_int64_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_uint64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.experimental.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <8 x i64> [[A]], i64 [[B:%.*]] +// CHECK-NEXT: ret i64 [[VECEXT]] +// +uint64_t subscript_uint64(fixed_uint64_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_float16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <32 x half> @llvm.experimental.vector.extract.v32f16.nxv8f16( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <32 x half> [[A]], i64 [[B:%.*]] +// CHECK-NEXT: ret half [[VECEXT]] +// +__fp16 subscript_float16(fixed_float16_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_float32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <16 x float> @llvm.experimental.vector.extract.v16f32.nxv4f32( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <16 x float> [[A]], i64 [[B:%.*]] +// CHECK-NEXT: ret float [[VECEXT]] +// +float subscript_float32(fixed_float32_t a, size_t b) { + return a[b]; +} + +// CHECK-LABEL: @subscript_float64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A:%.*]] = call <8 x double> @llvm.experimental.vector.extract.v8f64.nxv2f64( [[A_COERCE:%.*]], i64 0) +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <8 x double> [[A]], i64 [[B:%.*]] +// CHECK-NEXT: ret double [[VECEXT]] +// +double subscript_float64(fixed_float64_t a, size_t b) { + return a[b]; +} diff --git a/clang/test/CodeGen/arm-swiftcall.c b/clang/test/CodeGen/arm-swiftcall.c index bd85e7a9aed04..000602819ee01 100644 --- a/clang/test/CodeGen/arm-swiftcall.c +++ b/clang/test/CodeGen/arm-swiftcall.c @@ -121,7 +121,7 @@ TEST(struct_1); // CHECK: [[THIRD:%.*]] = load float, float* [[T0]], align // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 4 // CHECK: [[FOURTH:%.*]] = load float, float* [[T0]], align -// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i16, float, float }]] undef, i32 [[FIRST]], 0 +// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i16, float, float }]] poison, i32 [[FIRST]], 0 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i16 [[SECOND]], 1 // CHECK: [[T2:%.*]] = insertvalue [[UAGG]] [[T1]], float [[THIRD]], 2 // CHECK: [[T3:%.*]] = insertvalue [[UAGG]] [[T2]], float [[FOURTH]], 3 @@ -186,7 +186,7 @@ TEST(struct_2); // CHECK: [[THIRD:%.*]] = load float, float* [[T0]], align // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 3 // CHECK: [[FOURTH:%.*]] = load float, float* [[T0]], align -// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i32, float, float }]] undef, i32 [[FIRST]], 0 +// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i32, float, float }]] poison, i32 [[FIRST]], 0 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1 // CHECK: [[T2:%.*]] = insertvalue [[UAGG]] [[T1]], float [[THIRD]], 2 // CHECK: [[T3:%.*]] = insertvalue [[UAGG]] [[T2]], float [[FOURTH]], 3 @@ -250,7 +250,7 @@ TEST(struct_misaligned_1) // CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 // CHECK: [[SECOND:%.*]] = load i8, i8* [[T0]], align -// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i8 }]] undef, i32 [[FIRST]], 0 +// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i8 }]] poison, i32 [[FIRST]], 0 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i8 [[SECOND]], 1 // CHECK: ret [[UAGG]] [[T1]] // CHECK-LABEL: define{{.*}} @take_struct_misaligned_1(i32 %0, i8 %1) @@ -290,7 +290,7 @@ TEST(union_het_fp) // CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align {{(4|8)}} // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align {{(4|8)}} -// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i32 }]] undef, i32 [[FIRST]], 0 +// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i32 }]] poison, i32 [[FIRST]], 0 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1 // CHECK: ret [[UAGG]] [[T1]] // CHECK-LABEL: define{{.*}} @take_union_het_fp(i32 %0, i32 %1) @@ -422,7 +422,7 @@ TEST(int8) // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 // CHECK: [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align -// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, <4 x i32> }]] undef, <4 x i32> [[FIRST]], 0 +// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, <4 x i32> }]] poison, <4 x i32> [[FIRST]], 0 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], <4 x i32> [[SECOND]], 1 // CHECK: ret [[UAGG]] [[T1]] // CHECK-LABEL: define{{.*}} @take_int8(<4 x i32> %0, <4 x i32> %1) @@ -465,7 +465,7 @@ TEST(int5) // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align -// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, i32 }]] undef, <4 x i32> [[FIRST]], 0 +// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, i32 }]] poison, <4 x i32> [[FIRST]], 0 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1 // CHECK: ret [[UAGG]] [[T1]] // CHECK-LABEL: define{{.*}} @take_int5(<4 x i32> %0, i32 %1) diff --git a/clang/test/CodeGen/asan-globals.cpp b/clang/test/CodeGen/asan-globals.cpp index 0b17038a5f15a..80194f753e0fe 100644 --- a/clang/test/CodeGen/asan-globals.cpp +++ b/clang/test/CodeGen/asan-globals.cpp @@ -23,6 +23,9 @@ void func() { const char *literal = "Hello, world!"; } +// ASAN: @{{.*}}dyn_init_global{{.*}} ={{.*}} global {{.*}}, sanitize_address_dyninit +// KASAN: @{{.*}}dyn_init_global{{.*}} ={{.*}} global {{.*}}, sanitize_address_dyninit + // ASAN: sectioned_global{{.*}} global { i32, [28 x i8] }{{.*}}, align 32 // KASAN: sectioned_global{{.*}} global i32 // ASAN: @__special_global{{.*}} global { i32, [28 x i8] }{{.*}}, align 32 diff --git a/clang/test/CodeGen/attr-btf_type_tag-func.c b/clang/test/CodeGen/attr-btf_type_tag-func.c index 016e1064eb861..a4a22f36c1bb9 100644 --- a/clang/test/CodeGen/attr-btf_type_tag-func.c +++ b/clang/test/CodeGen/attr-btf_type_tag-func.c @@ -1,9 +1,17 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -DDOUBLE_BRACKET_ATTRS=1 -fdouble-square-bracket-attributes -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck %s +#if DOUBLE_BRACKET_ATTRS +#define __tag1 [[clang::btf_type_tag("tag1")]] +#define __tag2 [[clang::btf_type_tag("tag2")]] +#define __tag3 [[clang::btf_type_tag("tag3")]] +#define __tag4 [[clang::btf_type_tag("tag4")]] +#else #define __tag1 __attribute__((btf_type_tag("tag1"))) #define __tag2 __attribute__((btf_type_tag("tag2"))) #define __tag3 __attribute__((btf_type_tag("tag3"))) #define __tag4 __attribute__((btf_type_tag("tag4"))) +#endif int __tag1 * __tag2 *foo(int __tag1 * __tag2 *arg) { return arg; } diff --git a/clang/test/CodeGen/attr-btf_type_tag-var.c b/clang/test/CodeGen/attr-btf_type_tag-var.c index 3493d8f6d3666..0bb0a61728109 100644 --- a/clang/test/CodeGen/attr-btf_type_tag-var.c +++ b/clang/test/CodeGen/attr-btf_type_tag-var.c @@ -1,5 +1,16 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -DDOUBLE_BRACKET_ATTRS=1 -fdouble-square-bracket-attributes -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck %s +#if DOUBLE_BRACKET_ATTRS +#define __tag1 [[clang::btf_type_tag("tag1")]] +#define __tag2 [[clang::btf_type_tag("tag2")]] +#define __tag3 [[clang::btf_type_tag("tag3")]] +#define __tag4 [[clang::btf_type_tag("tag4")]] +#define __tag5 [[clang::btf_type_tag("tag5")]] +#define __tag6 [[clang::btf_type_tag("tag6")]] + +const volatile int __tag1 __tag2 * __tag3 __tag4 const volatile * __tag5 __tag6 const volatile * g; +#else #define __tag1 __attribute__((btf_type_tag("tag1"))) #define __tag2 __attribute__((btf_type_tag("tag2"))) #define __tag3 __attribute__((btf_type_tag("tag3"))) @@ -8,6 +19,7 @@ #define __tag6 __attribute__((btf_type_tag("tag6"))) const int __tag1 __tag2 volatile * const __tag3 __tag4 volatile * __tag5 __tag6 const volatile * g; +#endif // CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L6:[0-9]+]] // CHECK: ![[L6]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L7:[0-9]+]], size: [[#]], annotations: ![[L22:[0-9]+]] diff --git a/clang/test/CodeGen/builtin-sponentry.c b/clang/test/CodeGen/builtin-sponentry.c index ce389f6aee374..7487f602f36b8 100644 --- a/clang/test/CodeGen/builtin-sponentry.c +++ b/clang/test/CodeGen/builtin-sponentry.c @@ -1,8 +1,9 @@ // RUN: %clang_cc1 -no-opaque-pointers -triple aarch64-windows-gnu -Oz -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -no-opaque-pointers -triple thumbv7-windows-gnu -Oz -emit-llvm %s -o - | FileCheck %s void *test_sponentry(void) { return __builtin_sponentry(); } -// CHECK-LABEL: define dso_local i8* @test_sponentry() +// CHECK-LABEL: define dso_local {{(arm_aapcs_vfpcc )?}}i8* @test_sponentry() // CHECK: = tail call i8* @llvm.sponentry.p0i8() // CHECK: ret i8* diff --git a/clang/test/CodeGen/builtin_Float16.c b/clang/test/CodeGen/builtin_Float16.c new file mode 100644 index 0000000000000..099d2ad5697e3 --- /dev/null +++ b/clang/test/CodeGen/builtin_Float16.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -emit-llvm -o - -triple x86_64-linux-pc -target-feature +avx512fp16 %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -o - -triple spir-unknown-unknown %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -o - -triple armv7a--none-eabi %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -o - -triple aarch64-linux-gnu %s | FileCheck %s + +void test_float16_builtins(void) { + volatile _Float16 res; + + // CHECK: store volatile half 0xH7C00, ptr %res, align 2 + res = __builtin_huge_valf16(); + // CHECK: store volatile half 0xH7C00, ptr %res, align 2 + res = __builtin_inff16(); + // CHECK: store volatile half 0xH7E00, ptr %res, align 2 + res = __builtin_nanf16(""); + // CHECK: store volatile half 0xH7D00, ptr %res, align 2 + res = __builtin_nansf16(""); +} diff --git a/clang/test/CodeGen/builtins-memcpy-inline.c b/clang/test/CodeGen/builtins-memcpy-inline.c index d4eb8c62ff2fa..c9ea43ed96225 100644 --- a/clang/test/CodeGen/builtins-memcpy-inline.c +++ b/clang/test/CodeGen/builtins-memcpy-inline.c @@ -21,6 +21,6 @@ void test_memcpy_inline_4(void *dst, const void *src) { // CHECK-LABEL: define{{.*}} void @test_memcpy_inline_aligned_buffers(i64* noundef %dst, i64* noundef %src) void test_memcpy_inline_aligned_buffers(unsigned long long *dst, const unsigned long long *src) { - // CHECK: call void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* align 8 %2, i8* align 8 %3, i64 4, i1 false) + // CHECK: call void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* align 8 %1, i8* align 8 %3, i64 4, i1 false) __builtin_memcpy_inline(dst, src, 4); } diff --git a/clang/test/CodeGen/builtins-memset-inline.c b/clang/test/CodeGen/builtins-memset-inline.c new file mode 100644 index 0000000000000..0647186992fd6 --- /dev/null +++ b/clang/test/CodeGen/builtins-memset-inline.c @@ -0,0 +1,21 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: x86-registered-target +// RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-unknown-linux -emit-llvm %s -o - | FileCheck %s + +// CHECK-LABEL: define{{.*}} void @test_memset_inline_0(i8* noundef %dst, i8 noundef signext %value) +void test_memset_inline_0(void *dst, char value) { + // CHECK: call void @llvm.memset.inline.p0i8.i64(i8* align 1 %0, i8 %2, i64 0, i1 false) + __builtin_memset_inline(dst, value, 0); +} + +// CHECK-LABEL: define{{.*}} void @test_memset_inline_1(i8* noundef %dst, i8 noundef signext %value) +void test_memset_inline_1(void *dst, char value) { + // CHECK: call void @llvm.memset.inline.p0i8.i64(i8* align 1 %0, i8 %2, i64 1, i1 false) + __builtin_memset_inline(dst, value, 1); +} + +// CHECK-LABEL: define{{.*}} void @test_memset_inline_4(i8* noundef %dst, i8 noundef signext %value) +void test_memset_inline_4(void *dst, char value) { + // CHECK: call void @llvm.memset.inline.p0i8.i64(i8* align 1 %0, i8 %2, i64 4, i1 false) + __builtin_memset_inline(dst, value, 4); +} diff --git a/clang/test/CodeGen/builtins-wasm.c b/clang/test/CodeGen/builtins-wasm.c index 6ea97e293077a..d9ea753ee86a2 100644 --- a/clang/test/CodeGen/builtins-wasm.c +++ b/clang/test/CodeGen/builtins-wasm.c @@ -777,3 +777,24 @@ u32x4 relaxed_trunc_u_zero_i32x4_f64x2(f64x2 x) { // WEBASSEMBLY: call <4 x i32> @llvm.wasm.relaxed.trunc.unsigned.zero(<2 x double> %x) // WEBASSEMBLY-NEXT: ret } + +i16x8 relaxed_q15mulr_s_i16x8(i16x8 a, i16x8 b) { + return __builtin_wasm_relaxed_q15mulr_s_i16x8(a, b); + // WEBASSEMBLY: call <8 x i16> @llvm.wasm.relaxed.q15mulr.signed( + // WEBASSEMBLY-SAME: <8 x i16> %a, <8 x i16> %b) + // WEBASSEMBLY-NEXT: ret +} + +i16x8 dot_i8x16_i7x16_s_i16x8(i8x16 a, i8x16 b) { + return __builtin_wasm_dot_i8x16_i7x16_s_i16x8(a, b); + // WEBASSEMBLY: call <8 x i16> @llvm.wasm.dot.i8x16.i7x16.signed( + // WEBASSEMBLY-SAME: <16 x i8> %a, <16 x i8> %b) + // WEBASSEMBLY-NEXT: ret +} + +i32x4 dot_i8x16_i7x16_add_s_i32x4(i8x16 a, i8x16 b, i32x4 c) { + return __builtin_wasm_dot_i8x16_i7x16_add_s_i32x4(a, b, c); + // WEBASSEMBLY: call <4 x i32> @llvm.wasm.dot.i8x16.i7x16.add.signed( + // WEBASSEMBLY-SAME: <16 x i8> %a, <16 x i8> %b, <4 x i32> %c) + // WEBASSEMBLY-NEXT: ret +} diff --git a/clang/test/CodeGen/cmse-clear-arg.c b/clang/test/CodeGen/cmse-clear-arg.c index 39caa4cebe260..b393a0a26abb3 100644 --- a/clang/test/CodeGen/cmse-clear-arg.c +++ b/clang/test/CodeGen/cmse-clear-arg.c @@ -27,7 +27,7 @@ void f0(void) { g0(t0); } // CHECK: define {{.*}} @f0() // CHECK-LE: %[[V0:.*]] = and i32 {{.*}}, 1 // CHECK-BE: %[[V0:.*]] = and i32 {{.*}}, -2147483648 -// CHECK: %[[V1:.*]] = insertvalue [1 x i32] undef, i32 %[[V0]], 0 +// CHECK: %[[V1:.*]] = insertvalue [1 x i32] poison, i32 %[[V0]], 0 // CHECK: call {{.*}} void %0([1 x i32] %[[V1]]) // LE: 11111111 111111.. 11111111 11111111 0xfffffcff/-769 @@ -46,7 +46,7 @@ void f8(void) { g8(t8); } // CHECK: define {{.*}} @f8() // CHECK-LE: %[[V0:.*]] = and i32 {{.*}}, -769 // CHECK-BE: %[[V0:.*]] = and i32 {{.*}}, -12582913 -// CHECK: %[[V1:.*]] = insertvalue [1 x i32] undef, i32 %[[V0]], 0 +// CHECK: %[[V1:.*]] = insertvalue [1 x i32] poison, i32 %[[V0]], 0 // CHECK: call {{.*}} void %0([1 x i32] %[[V1]]) // LE(0): 11111111 ........ 11111111 11111111 0xffff00ff/-65281 @@ -69,7 +69,7 @@ void f15_0(void) { // CHECK: %[[FN:.*]] = load {{.*}} @g15_0 // CHECK-LE: %cmse.clear = and i32 {{.*}}, -65281 // CHECK-BE: %cmse.clear = and i32 {{.*}}, -16711681 -// CHECK: %[[R0:.*]] = insertvalue [2 x i32] undef, i32 %cmse.clear, 0 +// CHECK: %[[R0:.*]] = insertvalue [2 x i32] poison, i32 %cmse.clear, 0 // CHECK-LE: %cmse.clear1 = and i32 {{.*}}, 134215708 // CHECK-BE: %cmse.clear1 = and i32 {{.*}}, 941621216 // CHECK: %[[R1:.*]] = insertvalue [2 x i32] %[[R0]], i32 %cmse.clear1, 1 @@ -83,7 +83,7 @@ void f15_1(void) { // CHECK: %[[FN:.*]] = load {{.*}} @g15_1 // CHECK-LE: %cmse.clear = and i32 {{.*}}, -65281 // CHECK-BE: %cmse.clear = and i32 {{.*}}, -16711681 -// CHECK: %[[R0:.*]] = insertvalue [2 x i32] undef, i32 %cmse.clear, 0 +// CHECK: %[[R0:.*]] = insertvalue [2 x i32] poison, i32 %cmse.clear, 0 // CHECK-LE: %cmse.clear1 = and i32 {{.*}}, 134215708 // CHECK-BE: %cmse.clear1 = and i32 {{.*}}, 941621216 // CHECK: %[[R1:.*]] = insertvalue [2 x i32] %[[R0]], i32 %cmse.clear1, 1 @@ -110,7 +110,7 @@ void f16_0(void) { // CHECK: %[[FN:.*]] = load {{.*}} @g16_0 // CHECK-LE: %cmse.clear = and i64 {{.*}}, 9079291968726434047 // CHECK-BE: %cmse.clear = and i64 {{.*}}, -71776123088273282 -// CHECK: %[[R:.*]] = insertvalue [1 x i64] undef, i64 %cmse.clear, 0 +// CHECK: %[[R:.*]] = insertvalue [1 x i64] poison, i64 %cmse.clear, 0 // CHECK: call {{.*}} void %0([1 x i64] %[[R]]) @@ -140,7 +140,7 @@ void f18(void) { // CHECK: %[[FN:.*]] = load {{.*}} @g18 // CHECK-LE: %cmse.clear = and i32 {{.*}}, 32702963 // CHECK-BE: %cmse.clear = and i32 {{.*}}, -813641856 -// CHECK: %[[R0:.*]] = insertvalue [4 x i32] undef, i32 %cmse.clear, 0 +// CHECK: %[[R0:.*]] = insertvalue [4 x i32] poison, i32 %cmse.clear, 0 // CHECK-LE: %cmse.clear1 = and i32 {{.*}}, 32702963 // CHECK-BE: %cmse.clear1 = and i32 {{.*}}, -813641856 // CHECK: %[[R1:.*]] = insertvalue [4 x i32] %[[R0]], i32 %cmse.clear1, 1 @@ -170,7 +170,7 @@ void f19(void) { // CHECK: %[[FN:.*]] = load {{.*}} @g19 // CHECK-LE: %cmse.clear = and i32 {{.*}}, 943259647 // CHECK-BE: %cmse.clear = and i32 {{.*}}, -58340 -// CHECK: %[[R:.*]] = insertvalue [1 x i32] undef, i32 %cmse.clear, 0 +// CHECK: %[[R:.*]] = insertvalue [1 x i32] poison, i32 %cmse.clear, 0 // CHECK: call {{.*}} void %[[FN]]([1 x i32] %[[R]]) diff --git a/clang/test/CodeGen/global-init.c b/clang/test/CodeGen/global-init.c index 11e214ade9956..a69f028856110 100644 --- a/clang/test/CodeGen/global-init.c +++ b/clang/test/CodeGen/global-init.c @@ -9,14 +9,20 @@ int a = 242; // This should get normal weak linkage. int c __attribute__((weak))= 0; -// CHECK: @c = weak{{.*}} global i32 0 +// CHECK: @c = weak global i32 0 - -// Since this is marked const, it should get weak_odr linkage, since all -// definitions have to be the same. -// CHECK: @d = weak_odr constant i32 0 +// Even though is marked const, it should get still get "weak" +// linkage, not "weak_odr" as the weak attribute makes it possible +// that there is a strong definition that changes the value linktime, +// so the value must not be considered constant. +// CHECK: @d = weak constant i32 0 const int d __attribute__((weak))= 0; +// However, "selectany" is similar to "weak", but isn't interposable +// by a strong definition, and should appear as weak_odr. +// CHECK: @e = weak_odr constant i32 17 +const int e __attribute__((selectany)) = 17; + // PR6168 "too many undefs" struct ManyFields { int a; diff --git a/clang/test/CodeGen/homogeneous-aggregates.c b/clang/test/CodeGen/homogeneous-aggregates.c new file mode 100644 index 0000000000000..bf3751b10ba65 --- /dev/null +++ b/clang/test/CodeGen/homogeneous-aggregates.c @@ -0,0 +1,95 @@ +// REQUIRES: arm-registered-target,aarch64-registered-target,powerpc-registered-target +// RUN: %clang_cc1 -triple thumbv7-none-none -mfloat-abi hard -x c -emit-llvm -o - %s | FileCheck %s --check-prefix=AAPCS +// RUN: %clang_cc1 -triple thumbv7-none-none -mfloat-abi hard -x c++ -emit-llvm -o - %s | FileCheck %s --check-prefix=AAPCS +// RUN: %clang_cc1 -triple thumbv7-none-none -mfloat-abi hard -x c++ -DEXTERN_C -emit-llvm -o - %s | FileCheck %s --check-prefix=AAPCS +// RUN: %clang_cc1 -triple aarch64-none-none -mfloat-abi hard -x c -emit-llvm -o - %s | FileCheck %s --check-prefix=AAPCS +// RUN: %clang_cc1 -triple aarch64-none-none -mfloat-abi hard -x c++ -emit-llvm -o - %s | FileCheck %s --check-prefix=AAPCS +// RUN: %clang_cc1 -triple aarch64-none-none -mfloat-abi hard -x c++ -DEXTERN_C -emit-llvm -o - %s | FileCheck %s --check-prefix=AAPCS +// RUN: %clang_cc1 -triple powerpc64le-none-none -mfloat-abi hard -x c -emit-llvm -o - %s | FileCheck %s --check-prefix=PPC --check-prefix=PPC-C +// RUN: %clang_cc1 -triple powerpc64le-none-none -mfloat-abi hard -x c++ -emit-llvm -o - %s | FileCheck %s --check-prefix=PPC --check-prefix=PPC-CXX +// RUN: %clang_cc1 -triple powerpc64le-none-none -mfloat-abi hard -x c++ -DEXTERN_C -emit-llvm -o - %s | FileCheck %s --check-prefix=PPC --check-prefix=PPC-CXX + +// The aim here is to test whether each of these structure types is +// regarded as a homogeneous aggregate of a single kind of +// floating-point item, because in all of these ABIs, that changes the +// calling convention. +// +// We expect that 'Floats' and 'Doubles' are homogeneous, and 'Mixed' +// is not. But the next two structures, with separating zero-size +// bitfields, are more interesting. +// +// For the Arm architecture, AAPCS says that the homogeneity rule is +// applied _after_ data layout is completed, so that it's unaffected +// by anything that was completely discarded during data layout. So we +// expect that FloatsBF and DoublesBF still count as homogeneous. +// +// But on PowerPC, it depends on whether the source language is C or +// C++, because that's consistent with the decisions gcc makes. + +struct Floats { + float a; + float b; +}; + +struct Doubles { + double a; + double b; +}; + +struct Mixed { + double a; + float b; +}; + +struct FloatsBF { + float a; + int : 0; + float b; +}; + +struct DoublesBF { + double a; + int : 0; + double b; +}; + +// In C++ mode, we test both with and without extern "C", to ensure +// that doesn't make a difference. +#ifdef EXTERN_C +#define LINKAGE extern "C" +#else +#define LINKAGE +#endif + +// For Arm backends, the IR emitted for the homogeneous-aggregate +// return convention uses the actual structure type, so that +// HandleFloats returns a %struct.Floats, and so on. To check that +// 'Mixed' is not treated as homogeneous, it's enough to check that +// its return type is _not_ %struct.Mixed. (The fallback handling +// varies between AArch32 and AArch64.) +// +// For PowerPC, homogeneous structure types are lowered to an IR array +// types like [2 x float], and the non-homogeneous Mixed is lowered to +// a pair of i64. + +// AAPCS: define{{.*}} %struct.Floats @{{.*HandleFloats.*}} +// PPC: define{{.*}} [2 x float] @{{.*HandleFloats.*}} +LINKAGE struct Floats HandleFloats(struct Floats x) { return x; } + +// AAPCS: define{{.*}} %struct.Doubles @{{.*HandleDoubles.*}} +// PPC: define{{.*}} [2 x double] @{{.*HandleDoubles.*}} +LINKAGE struct Doubles HandleDoubles(struct Doubles x) { return x; } + +// AAPCS-NOT: define{{.*}} %struct.Mixed @{{.*HandleMixed.*}} +// PPC: define{{.*}} { i64, i64 } @{{.*HandleMixed.*}} +LINKAGE struct Mixed HandleMixed(struct Mixed x) { return x; } + +// AAPCS: define{{.*}} %struct.FloatsBF @{{.*HandleFloatsBF.*}} +// PPC-C-NOT: define{{.*}} [2 x float] @{{.*HandleFloatsBF.*}} +// PPC-CXX: define{{.*}} [2 x float] @{{.*HandleFloatsBF.*}} +LINKAGE struct FloatsBF HandleFloatsBF(struct FloatsBF x) { return x; } + +// AAPCS: define{{.*}} %struct.DoublesBF @{{.*HandleDoublesBF.*}} +// PPC-C-NOT: define{{.*}} [2 x double] @{{.*HandleDoublesBF.*}} +// PPC-CXX: define{{.*}} [2 x double] @{{.*HandleDoublesBF.*}} +LINKAGE struct DoublesBF HandleDoublesBF(struct DoublesBF x) { return x; } diff --git a/clang/test/CodeGen/mdefault-visibility-export-mapping.c b/clang/test/CodeGen/mdefault-visibility-export-mapping.c new file mode 100644 index 0000000000000..18c6302d9f655 --- /dev/null +++ b/clang/test/CodeGen/mdefault-visibility-export-mapping.c @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=UNSPECIFIED-DEF,EXPLICIT-DEF %s +// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -mdefault-visibility-export-mapping=none -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=UNSPECIFIED-DEF,EXPLICIT-DEF %s +// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -mdefault-visibility-export-mapping=explicit -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=UNSPECIFIED-DEF,EXPLICIT-EXP %s +// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -mdefault-visibility-export-mapping=all -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=UNSPECIFIED-EXP,EXPLICIT-EXP %s +// RUN: %clang -target powerpc-ibm-aix %s -mdefault-visibility-export-mapping=all -fvisibility=hidden -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=UNSPECIFIED-HID,EXPLICIT-EXP %s + +// RUN: not %clang -mdefault-visibility-export-mapping=explicit -target powerpc-unknown-linux %s 2>&1 | \ +// RUN: FileCheck -check-prefix=ERROR %s +// ERROR: unsupported option '-mdefault-visibility-export-mapping=explicit' for target 'powerpc-unknown-linux' + +// UNSPECIFIED-DEF: define void @func() +// UNSPECIFIED-HID: define hidden void @func() +// UNSPECIFIED-EXP: define dllexport void @func() +void func() {} + +#pragma GCC visibility push(default) +// EXPLICIT-DEF: define void @pragmafunc() +// EXPLICIT-EXP: define dllexport void @pragmafunc() +void pragmafunc() {} +#pragma GCC visibility pop + +// EXPLICIT-DEF: define void @explicitfunc() +// EXPLICIT-EXP: define dllexport void @explicitfunc() +void __attribute__((visibility("default"))) explicitfunc() {} diff --git a/clang/test/CodeGen/pragma-comment.c b/clang/test/CodeGen/pragma-comment.c index 25675d94c5a4d..a4746f5c47bf6 100644 --- a/clang/test/CodeGen/pragma-comment.c +++ b/clang/test/CodeGen/pragma-comment.c @@ -4,6 +4,7 @@ // RUN: %clang_cc1 %s -triple thumbv7-linux-gnueabihf -fms-extensions -emit-llvm -o - | FileCheck -check-prefix ELF %s --implicit-check-not llvm.linker.options // RUN: %clang_cc1 %s -triple i686-pc-linux -fms-extensions -emit-llvm -o - | FileCheck -check-prefix ELF %s --implicit-check-not llvm.linker.options // RUN: %clang_cc1 %s -triple x86_64-scei-ps4 -fms-extensions -emit-llvm -o - | FileCheck -check-prefix ELF %s --implicit-check-not llvm.linker.options +// RUN: %clang_cc1 %s -triple x86_64-sie-ps5 -fms-extensions -emit-llvm -o - | FileCheck -check-prefix ELF %s --implicit-check-not llvm.linker.options // RUN: %clang_cc1 %s -triple aarch64-windows-msvc -fms-extensions -emit-llvm -o - | FileCheck %s #pragma comment(lib, "msvcrt.lib") diff --git a/clang/test/CodeGen/sanitize-init-order.cpp b/clang/test/CodeGen/sanitize-init-order.cpp index f39d056d78d5a..dd7e3c5b4b124 100644 --- a/clang/test/CodeGen/sanitize-init-order.cpp +++ b/clang/test/CodeGen/sanitize-init-order.cpp @@ -36,12 +36,29 @@ const volatile PODWithCtor array[5][5]; // Check that ASan init-order checking ignores structs with trivial default // constructor. + +// CHECK: @{{.*}}s1{{.*}} ={{.*}} global +// CHECK-NOT: sanitize_address_dyninit +// CHECK: @{{.*}}s2{{.*}} ={{.*}} global +// CHECK-NOT: sanitize_address_dyninit +// CHECK: @{{.*}}s3{{.*}} ={{.*}} global {{.*}}, sanitize_address_dyninit +// CHECK: @{{.*}}array{{.*}} ={{.*}} global {{.*}}, sanitize_address_dyninit + // CHECK: !llvm.asan.globals = !{![[GLOB_1:[0-9]+]], ![[GLOB_2:[0-9]+]], ![[GLOB_3:[0-9]+]], ![[GLOB_4:[0-9]+]] // CHECK: ![[GLOB_1]] = !{%struct.PODStruct* {{.*}}, i1 false, i1 false} // CHECK: ![[GLOB_2]] = !{%struct.PODWithDtor* {{.*}}, i1 false, i1 false} // CHECK: ![[GLOB_3]] = !{%struct.PODWithCtorAndDtor* {{.*}}, i1 true, i1 false} // CHECK: ![[GLOB_4]] = !{{{.*}}class.NS::PODWithCtor{{.*}}, i1 true, i1 false} +// IGNORELIST: @{{.*}}s1{{.*}} ={{.*}} global +// IGNORELIST-NOT: sanitize_address_dyninit +// IGNORELIST: @{{.*}}s2{{.*}} ={{.*}} global +// IGNORELIST-NOT: sanitize_address_dyninit +// IGNORELIST: @{{.*}}s3{{.*}} ={{.*}} global +// IGNORELIST-NOT: sanitize_address_dyninit +// IGNORELIST: @{{.*}}array{{.*}} ={{.*}} global +// IGNORELIST-NOT: sanitize_address_dyninit + // IGNORELIST: !llvm.asan.globals = !{![[GLOB_1:[0-9]+]], ![[GLOB_2:[0-9]+]], ![[GLOB_3:[0-9]+]], ![[GLOB_4:[0-9]+]]} // IGNORELIST: ![[GLOB_1]] = !{%struct.PODStruct* {{.*}}, i1 false, i1 false} // IGNORELIST: ![[GLOB_2]] = !{%struct.PODWithDtor* {{.*}}, i1 false, i1 false} diff --git a/clang/test/CodeGen/sanitizer-special-case-list-globals.c b/clang/test/CodeGen/sanitizer-special-case-list-globals.c new file mode 100644 index 0000000000000..5497aef221686 --- /dev/null +++ b/clang/test/CodeGen/sanitizer-special-case-list-globals.c @@ -0,0 +1,91 @@ +/// Verify that ignorelist sections correctly select sanitizers to apply +/// ignorelist entries to. + +// RUN: %clang_cc1 -emit-llvm %s -o -\ +// RUN: -fsanitize-ignorelist=%S/Inputs/sanitizer-special-case-list-globals.txt \ +// RUN: | FileCheck %s --check-prefix=NONE + +// RUN: %clang_cc1 -fsanitize=address -emit-llvm %s -o -\ +// RUN: -fsanitize-ignorelist=%S/Inputs/sanitizer-special-case-list-globals.txt \ +// RUN: | FileCheck %s --check-prefix=ASAN + +/// Note: HWASan effectively reorders globals (it puts the unsanitized ones +/// first), which is hard to check for, as 'CHECK-DAG' doesn't play terribly +/// nicely with 'CHECK-NOT'. This is why the 'always_ignored' and +/// 'hwasan_ignored' comes first in this file. +// RUN: %clang_cc1 -fsanitize=hwaddress -emit-llvm %s -o -\ +// RUN: -fsanitize-ignorelist=%S/Inputs/sanitizer-special-case-list-globals.txt \ +// RUN: | FileCheck %s --check-prefix=HWASAN + +/// TODO(hctim): Move over to memtag-globals when it's implemented. For now +/// though, it's fine, the frontend still annotates based on any memtag sanitizer +/// being used. +// RUN: %clang_cc1 -fsanitize=memtag-heap -triple=aarch64-linux-android31 -emit-llvm %s -o -\ +// RUN: -fsanitize-ignorelist=%S/Inputs/sanitizer-special-case-list-globals.txt \ +// RUN: | FileCheck %s --check-prefix=MEMTAG + +/// Check that the '[cfi-vcall|cfi-icall] src:*' rule in the ignorelist doesn't change +/// anything for ASan. +// RUN: %clang_cc1 -fsanitize=address -emit-llvm %s -o -\ +// RUN: -fsanitize-ignorelist=%S/Inputs/sanitizer-special-case-list-globals.txt \ +// RUN: | FileCheck %s --check-prefix=ASAN + +/// Check that -fsanitize=kernel-address picks up the '[address]' groups. +// RUN: %clang_cc1 -fsanitize=kernel-address -mllvm -hwasan-kernel=1 -emit-llvm %s -o -\ +// RUN: -fsanitize-ignorelist=%S/Inputs/sanitizer-special-case-list-globals.txt \ +// RUN: | FileCheck %s --check-prefix=ASAN + +/// KHWASan doesn't instrument global variables. +// RUN: %clang_cc1 -fsanitize=kernel-hwaddress -mllvm -hwasan-kernel=1 -emit-llvm %s -o -\ +// RUN: -fsanitize-ignorelist=%S/Inputs/sanitizer-special-case-list-globals.txt \ +// RUN: | FileCheck %s --check-prefix=NONE + +/// Check that the '[cfi-vcall|cfi-icall] src:*' rule doesnt' emit anything for +/// GVs. +// RUN: %clang_cc1 -fsanitize=cfi-vcall,cfi-icall -emit-llvm %s -o -\ +// RUN: -fsanitize-ignorelist=%S/Inputs/sanitizer-special-case-list-globals.txt \ +// RUN: | FileCheck %s --check-prefix=NONE + +// NONE: @always_ignored ={{.*}} global +// NONE-NOT: no_sanitize +// ASAN: @always_ignored ={{.*}} global {{.*}}, no_sanitize_address +// HWASAN: @always_ignored ={{.*}} global {{.*}}, no_sanitize_hwaddress +// MEMTAG: @always_ignored ={{.*}} global {{.*}}, no_sanitize_memtag +unsigned always_ignored; + +// NONE: @hwasan_ignored ={{.*}} global +// NONE-NOT: no_sanitize +// ASAN: @hwasan_ignored ={{.*}} global +// ASAN-NOT: no_sanitize_address +// HWASAN: @hwasan_ignored ={{.*}} global {{.*}}, no_sanitize_hwaddress +// MEMTAG: @hwasan_ignored ={{.*}} global +// MEMTAG-NOT: no_sanitize_memtag +unsigned hwasan_ignored; + +// NONE: @asan_ignored ={{.*}} global +// NONE-NOT: asan_ignored +// ASAN: @asan_ignored ={{.*}} global {{.*}}, no_sanitize_address +// HWASAN: @asan_ignored.hwasan = {{.*}} global +// HWASAN-NOT: no_sanitize_hwaddress +// MEMTAG: @asan_ignored ={{.*}} global +// MEMTAG-NOT: no_sanitize_memtag +unsigned asan_ignored; + +// NONE: @memtag_ignored ={{.*}} global +// NONE-NOT: memtag_ignored +// ASAN: @memtag_ignored ={{.*}} global +// ASAN-NOT: no_sanitize_address +// HWASAN: @memtag_ignored.hwasan = {{.*}} global +// HWASAN-NOT: no_sanitize_hwaddress +// MEMTAG: @memtag_ignored ={{.*}} global {{.*}}, no_sanitize_memtag +unsigned memtag_ignored; + +// NONE: @never_ignored ={{.*}} global +// NONE-NOT: never_ignored +// ASAN: @never_ignored ={{.*}} global +// ASAN-NOT: no_sanitize_address +// HWASAN: @never_ignored.hwasan ={{.*}} global +// HWASAN-NOT: no_sanitize_hwaddress +// MEMTAG: @never_ignored ={{.*}} global +// MEMTAG-NOT: no_sanitize_memtag +unsigned never_ignored; diff --git a/clang/test/CodeGen/stmtexpr-init.c b/clang/test/CodeGen/stmtexpr-init.c new file mode 100644 index 0000000000000..e2db75518e9a4 --- /dev/null +++ b/clang/test/CodeGen/stmtexpr-init.c @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +void escape(const void *); + +// CHECK-DAG: internal global i8 99 + +void T1(void) { + const char *x[1] = {({static char _x = 99; &_x; })}; + escape(x); +} + +struct sized_array { + int count; + int entries[]; +}; + +#define N_ARGS(...) (sizeof((int[]){__VA_ARGS__}) / sizeof(int)) + +#define ARRAY_PTR(...) ({ \ + static const struct sized_array _a = {N_ARGS(__VA_ARGS__), {__VA_ARGS__}}; \ + &_a; \ +}) + +struct outer { + const struct sized_array *a; +}; + +void T2(void) { + // CHECK-DAG: internal constant { i32, [2 x i32] } { i32 2, [2 x i32] [i32 50, i32 60] } + const struct sized_array *A = ARRAY_PTR(50, 60); + + // CHECK-DAG: internal constant { i32, [3 x i32] } { i32 3, [3 x i32] [i32 10, i32 20, i32 30] } + struct outer X = {ARRAY_PTR(10, 20, 30)}; + + escape(A); + escape(&X); +} diff --git a/clang/test/CodeGen/thinlto-inline-asm2.c b/clang/test/CodeGen/thinlto-inline-asm2.c index 5d7bbc097de7c..7606b27deac87 100644 --- a/clang/test/CodeGen/thinlto-inline-asm2.c +++ b/clang/test/CodeGen/thinlto-inline-asm2.c @@ -5,7 +5,7 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -flto=thin -emit-llvm-bc %t/b.c -o %t/b.bc // RUN: llvm-nm %t/a.bc | FileCheck %s --check-prefix=NM -// RUN: llvm-lto2 run %t/a.bc %t/b.bc -o %t/out -save-temps -r=%t/a.bc,ref,plx -r=%t/b.bc,ff_h264_cabac_tables,pl +// RUN: llvm-lto2 run -lto-opaque-pointers %t/a.bc %t/b.bc -o %t/out -save-temps -r=%t/a.bc,ref,plx -r=%t/b.bc,ff_h264_cabac_tables,pl // RUN: llvm-dis < %t/out.2.2.internalize.bc | FileCheck %s //--- a.c diff --git a/clang/test/CodeGen/thinlto_backend.ll b/clang/test/CodeGen/thinlto_backend.ll index c8b840e400066..dea1a8ac54cd3 100644 --- a/clang/test/CodeGen/thinlto_backend.ll +++ b/clang/test/CodeGen/thinlto_backend.ll @@ -53,12 +53,12 @@ target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16 target triple = "x86_64-unknown-linux-gnu" declare void @f2() -declare i8* @f3() +declare ptr @f3() define void @f1() { call void @f2() ; Make sure that the backend can handle undefined references. ; Do an indirect call so that the undefined ref shows up in the combined index. - call void bitcast (i8*()* @f3 to void()*)() + call void @f3() ret void } diff --git a/clang/test/CodeGen/weak_constant.c b/clang/test/CodeGen/weak_constant.c index 726d2ef122e10..67bdd919684d1 100644 --- a/clang/test/CodeGen/weak_constant.c +++ b/clang/test/CodeGen/weak_constant.c @@ -1,13 +1,31 @@ // RUN: %clang_cc1 -w -emit-llvm %s -O1 -o - | FileCheck %s -// Check for bug compatibility with gcc. +// This used to "check for bug compatibility with gcc". +// Now it checks that that the "weak" declaration makes the value +// fully interposable whereas a "selectany" one is handled as constant +// and propagated. +// CHECK: @x = weak {{.*}}constant i32 123 const int x __attribute((weak)) = 123; +// CHECK: @y = weak_odr {{.*}}constant i32 234 +const int y __attribute((selectany)) = 234; + int* f(void) { return &x; } int g(void) { - // CHECK: ret i32 123 + // CHECK: load i32, ptr @x + // CHECK-NOT: ret i32 123 return *f(); } + +int *k(void) { + return &y; +} + +int l(void) { + // CHECK-NOT: load i32, ptr @y + // CHECK: ret i32 234 + return *k(); +} diff --git a/clang/test/CodeGen/windows-swiftcall.c b/clang/test/CodeGen/windows-swiftcall.c index 697d4f8ac4f63..0aa93fae0581d 100644 --- a/clang/test/CodeGen/windows-swiftcall.c +++ b/clang/test/CodeGen/windows-swiftcall.c @@ -105,7 +105,7 @@ TEST(struct_1); // CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4 // CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 // CHECK: [[T1:%.*]] = load i64, i64* [[GEP1]], align 4 -// CHECK: [[R0:%.*]] = insertvalue { i64, i64 } undef, i64 [[T0]], 0 +// CHECK: [[R0:%.*]] = insertvalue { i64, i64 } poison, i64 [[T0]], 0 // CHECK: [[R1:%.*]] = insertvalue { i64, i64 } [[R0]], i64 [[T1]], 1 // CHECK: ret { i64, i64 } [[R1]] // CHECK: } @@ -154,7 +154,7 @@ TEST(struct_2); // CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4 // CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 // CHECK: [[T1:%.*]] = load i64, i64* [[GEP1]], align 4 -// CHECK: [[R0:%.*]] = insertvalue { i64, i64 } undef, i64 [[T0]], 0 +// CHECK: [[R0:%.*]] = insertvalue { i64, i64 } poison, i64 [[T0]], 0 // CHECK: [[R1:%.*]] = insertvalue { i64, i64 } [[R0]], i64 [[T1]], 1 // CHECK: ret { i64, i64 } [[R1]] // CHECK: } @@ -375,7 +375,7 @@ TEST(int8) // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 // CHECK: [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align -// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, <4 x i32> }]] undef, <4 x i32> [[FIRST]], 0 +// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, <4 x i32> }]] poison, <4 x i32> [[FIRST]], 0 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], <4 x i32> [[SECOND]], 1 // CHECK: ret [[UAGG]] [[T1]] // CHECK-LABEL: define {{.*}} @take_int8(<4 x i32> noundef %0, <4 x i32> noundef %1) @@ -419,7 +419,7 @@ TEST(int5) // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align -// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, i32 }]] undef, <4 x i32> [[FIRST]], 0 +// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, i32 }]] poison, <4 x i32> [[FIRST]], 0 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1 // CHECK: ret [[UAGG]] [[T1]] // CHECK-LABEL: define {{.*}} @take_int5(<4 x i32> %0, i32 %1) diff --git a/clang/test/CodeGen/xcore-stringtype.c b/clang/test/CodeGen/xcore-stringtype.c index 365a36dc60ccd..4b9429caa1df3 100644 --- a/clang/test/CodeGen/xcore-stringtype.c +++ b/clang/test/CodeGen/xcore-stringtype.c @@ -42,8 +42,8 @@ double _Complex Complex; // not supported // CHECK: !{{[0-9]+}} = !{void ()* @eV, !"f{0}(0)"} // CHECK: !{{[0-9]+}} = !{void (i32, ...)* @gVA, !"f{0}(si,va)"} // CHECK: !{{[0-9]+}} = !{void (i32, ...)* @eVA, !"f{0}(si,va)"} -// CHECK: !{{[0-9]+}} = !{i32* (i32*)* @gQ, !"f{p(cv:si)}(p(cv:si))"} -// CHECK: !{{[0-9]+}} = !{i32* (i32*)* @eQ, !"f{p(cv:si)}(p(cv:si))"} +// CHECK: !{{[0-9]+}} = !{i32* (i32*)* @gQ, !"f{crv:p(cv:si)}(p(cv:si))"} +// CHECK: !{{[0-9]+}} = !{i32* (i32*)* @eQ, !"f{crv:p(cv:si)}(p(cv:si))"} extern void eI(); void gI() {eI();}; extern void eV(void); diff --git a/clang/test/CodeGenCUDA/amdgpu-asan.cu b/clang/test/CodeGenCUDA/amdgpu-asan.cu index 7d2431b520d6b..9c505fe2346ba 100644 --- a/clang/test/CodeGenCUDA/amdgpu-asan.cu +++ b/clang/test/CodeGenCUDA/amdgpu-asan.cu @@ -1,29 +1,29 @@ // Create a sample address sanitizer bitcode library. -// RUN: %clang_cc1 -no-opaque-pointers -x ir -fcuda-is-device -triple amdgcn-amd-amdhsa -emit-llvm-bc \ +// RUN: %clang_cc1 -x ir -fcuda-is-device -triple amdgcn-amd-amdhsa -emit-llvm-bc \ // RUN: -disable-llvm-passes -o %t.asanrtl.bc %S/Inputs/amdgpu-asanrtl.ll // Check sanitizer runtime library functions survive // optimizations without being removed or parameters altered. -// RUN: %clang_cc1 -no-opaque-pointers %s -emit-llvm -o - -triple=amdgcn-amd-amdhsa \ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=amdgcn-amd-amdhsa \ // RUN: -fcuda-is-device -target-cpu gfx906 -fsanitize=address \ // RUN: -mlink-bitcode-file %t.asanrtl.bc -x hip \ // RUN: | FileCheck -check-prefixes=ASAN %s -// RUN: %clang_cc1 -no-opaque-pointers %s -emit-llvm -o - -triple=amdgcn-amd-amdhsa \ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=amdgcn-amd-amdhsa \ // RUN: -fcuda-is-device -target-cpu gfx906 -fsanitize=address \ // RUN: -O3 -mlink-bitcode-file %t.asanrtl.bc -x hip \ // RUN: | FileCheck -check-prefixes=ASAN %s -// RUN: %clang_cc1 -no-opaque-pointers %s -emit-llvm -o - -triple=amdgcn-amd-amdhsa \ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=amdgcn-amd-amdhsa \ // RUN: -fcuda-is-device -target-cpu gfx906 -x hip \ // RUN: | FileCheck %s // REQUIRES: amdgpu-registered-target // ASAN-DAG: define weak void @__amdgpu_device_library_preserve_asan_functions() -// ASAN-DAG: @__amdgpu_device_library_preserve_asan_functions_ptr = weak addrspace(1) constant void ()* @__amdgpu_device_library_preserve_asan_functions +// ASAN-DAG: @__amdgpu_device_library_preserve_asan_functions_ptr = weak addrspace(1) constant ptr @__amdgpu_device_library_preserve_asan_functions // ASAN-DAG: @llvm.compiler.used = {{.*}}@__amdgpu_device_library_preserve_asan_functions_ptr // ASAN-DAG: define weak void @__asan_report_load1(i64 %{{.*}}) diff --git a/clang/test/CodeGenCUDA/long-double.cu b/clang/test/CodeGenCUDA/long-double.cu new file mode 100644 index 0000000000000..454a93ce5f6b6 --- /dev/null +++ b/clang/test/CodeGenCUDA/long-double.cu @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -target-cpu gfx906 \ +// RUN: -aux-triple x86_64-unknown-gnu-linux -fcuda-is-device \ +// RUN: -emit-llvm -o - -x hip %s 2>&1 | FileCheck %s + +// RUN: %clang_cc1 -triple nvptx \ +// RUN: -aux-triple x86_64-unknown-gnu-linux -fcuda-is-device \ +// RUN: -emit-llvm -o - %s 2>&1 | FileCheck %s + +// CHECK: @_ZN15infinity_helperIeE5valueE = {{.*}} double 0x47EFFFFFD586B834, align 8 +// CHECK: @size = {{.*}} i32 8 + +#include "Inputs/cuda.h" + +template struct infinity_helper {}; +template <> struct infinity_helper { static constexpr long double value = 3.4028234e38L; }; +constexpr long double infinity_helper::value; +__device__ int size = sizeof(long double); diff --git a/clang/test/CodeGenCXX/alignment.cpp b/clang/test/CodeGenCXX/alignment.cpp index ffa4d873b5d76..98ce2fa28540f 100644 --- a/clang/test/CodeGenCXX/alignment.cpp +++ b/clang/test/CodeGenCXX/alignment.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -no-opaque-pointers %s -emit-llvm -o - -triple=x86_64-apple-darwin10 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOCOMPAT // RUN: %clang_cc1 -no-opaque-pointers %s -emit-llvm -o - -triple=x86_64-apple-darwin10 -fclang-abi-compat=6.0 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V6COMPAT // RUN: %clang_cc1 -no-opaque-pointers %s -emit-llvm -o - -triple=x86_64-scei-ps4 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V6COMPAT +// RUN: %clang_cc1 -no-opaque-pointers %s -emit-llvm -o - -triple=x86_64-sie-ps5 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V6COMPAT extern int int_source(); extern void int_sink(int x); diff --git a/clang/test/CodeGenCXX/annotate-type.cpp b/clang/test/CodeGenCXX/annotate-type.cpp new file mode 100644 index 0000000000000..456888b1ecd97 --- /dev/null +++ b/clang/test/CodeGenCXX/annotate-type.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -emit-llvm -o - | FileCheck %s + +// Test that `annotate_type` does not affect mangled names. + +int *[[clang::annotate_type("foo")]] f(int *[[clang::annotate_type("foo")]], + int [[clang::annotate_type("foo")]]) { + return nullptr; +} +// CHECK: @_Z1fPii + +template struct S {}; + +S +g(S) { + return {}; +} +// CHECK: @_Z1g1SIPiE diff --git a/clang/test/CodeGenCXX/arm-swiftcall.cpp b/clang/test/CodeGenCXX/arm-swiftcall.cpp index 0d6c9832cd5e1..45cfd260a5d50 100644 --- a/clang/test/CodeGenCXX/arm-swiftcall.cpp +++ b/clang/test/CodeGenCXX/arm-swiftcall.cpp @@ -58,7 +58,7 @@ TEST(struct_1); // CHECK: [[THIRD:%.*]] = load float, float* [[T0]], align 4 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 5 // CHECK: [[FOURTH:%.*]] = load float, float* [[T0]], align 4 -// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i8, float, float }]] undef, i32 [[FIRST]], 0 +// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i8, float, float }]] poison, i32 [[FIRST]], 0 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i8 [[SECOND]], 1 // CHECK: [[T2:%.*]] = insertvalue [[UAGG]] [[T1]], float [[THIRD]], 2 // CHECK: [[T3:%.*]] = insertvalue [[UAGG]] [[T2]], float [[FOURTH]], 3 diff --git a/clang/test/CodeGenCXX/externc-used-not-replaced.cpp b/clang/test/CodeGenCXX/externc-used-not-replaced.cpp new file mode 100644 index 0000000000000..133b3a66c53f4 --- /dev/null +++ b/clang/test/CodeGenCXX/externc-used-not-replaced.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple x86_64-windows -emit-llvm -o - %s | FileCheck %s + +extern "C" { + const char a __attribute__((used)){}; +} + +// CHECK: @a = internal constant i8 0 +// CHECK: @llvm.used = appending global [1 x ptr] [ptr @a] diff --git a/clang/test/CodeGenCXX/mdefault-visibility-export-mapping-alias.cpp b/clang/test/CodeGenCXX/mdefault-visibility-export-mapping-alias.cpp new file mode 100644 index 0000000000000..0d6c4ee1e2ee4 --- /dev/null +++ b/clang/test/CodeGenCXX/mdefault-visibility-export-mapping-alias.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -mdefault-visibility-export-mapping=none -mconstructor-aliases -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=UNSPECIFIED-DEF,EXPLICIT-DEF %s +// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -mdefault-visibility-export-mapping=explicit -mconstructor-aliases -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=UNSPECIFIED-DEF,EXPLICIT-EXP %s +// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -mdefault-visibility-export-mapping=all -mconstructor-aliases -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=UNSPECIFIED-EXP,EXPLICIT-EXP %s + +class A { +public: + ~A(); +}; + +A::~A() {} + +class __attribute__((visibility("default"))) B { +public: + ~B(); +}; + +B::~B() {} + +void func() { + A x; + B y; +} + +// A::~A() (complete object destructor) +// UNSPECIFIED-DEF: @_ZN1AD1Ev = unnamed_addr alias +// UNSPECIFIED-EXP: @_ZN1AD1Ev = dllexport unnamed_addr alias + +// B::~B() (complete object destructor) +// EXPLICIT-DEF: @_ZN1BD1Ev = unnamed_addr alias +// EXPLICIT-EXP: @_ZN1BD1Ev = dllexport unnamed_addr alias + +// A::~A() (base object destructor) +// UNSPECIFIED-DEF: define void @_ZN1AD2Ev( +// UNSPECIFIED-EXP: define dllexport void @_ZN1AD2Ev( + +// B::~B() (base object destructor) +// EXPLICIT-DEF: define void @_ZN1BD2Ev( +// EXPLICIT-EXP: define dllexport void @_ZN1BD2Ev( diff --git a/clang/test/CodeGenCXX/mdefault-visibility-export-mapping-rtti.cpp b/clang/test/CodeGenCXX/mdefault-visibility-export-mapping-rtti.cpp new file mode 100644 index 0000000000000..e26c75e69e8fc --- /dev/null +++ b/clang/test/CodeGenCXX/mdefault-visibility-export-mapping-rtti.cpp @@ -0,0 +1,596 @@ +// RUN: %clang_cc1 -triple powerpc64-ibm-aix %s -internal-isystem %S -mdefault-visibility-export-mapping=none -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=CHECK,UNSPECIFIED-DEF,EXPLICIT-DEF,FUND-DEF %s +// RUN: %clang_cc1 -triple powerpc64-ibm-aix %s -internal-isystem %S -mdefault-visibility-export-mapping=explicit -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=CHECK,UNSPECIFIED-DEF,EXPLICIT-EXP,FUND-DEF %s +// RUN: %clang_cc1 -triple powerpc64-ibm-aix %s -internal-isystem %S -mdefault-visibility-export-mapping=explicit -DFUNDAMENTAL_IS_EXPLICIT -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=CHECK,UNSPECIFIED-DEF,EXPLICIT-EXP,FUND-EXP %s +// RUN: %clang_cc1 -triple powerpc64-ibm-aix %s -internal-isystem %S -mdefault-visibility-export-mapping=all -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=CHECK,UNSPECIFIED-EXP,EXPLICIT-EXP,FUND-EXP %s +// RUN: %clang_cc1 -triple powerpc64-ibm-aix %s -internal-isystem %S -mdefault-visibility-export-mapping=all -fvisibility hidden -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=CHECK,UNSPECIFIED-HID,EXPLICIT-EXP,FUND-HID %s +// RUN: %clang_cc1 -triple powerpc64-ibm-aix %s -internal-isystem %S -mdefault-visibility-export-mapping=all -DFUNDAMENTAL_IS_EXPLICIT -fvisibility hidden -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=CHECK,UNSPECIFIED-HID,EXPLICIT-EXP,FUND-EXP %s + +#include + +// C is an incomplete class type, so any direct or indirect pointer types should have +// internal linkage, as should the type info for C itself. +struct C; +// CHECK: @_ZTSP1C = internal constant +// CHECK: @_ZTS1C = internal constant +// CHECK: @_ZTI1C = internal constant +// CHECK: @_ZTIP1C = internal constant +// CHECK: @_ZTSPP1C = internal constant +// CHECK: @_ZTIPP1C = internal constant + +struct __attribute__((type_visibility("default"))) D; +// CHECK: @_ZTSP1D = internal constant +// CHECK: @_ZTS1D = internal constant +// CHECK: @_ZTI1D = internal constant +// CHECK: @_ZTIP1D = internal constant +// CHECK: @_ZTSPP1D = internal constant +// CHECK: @_ZTIPP1D = internal constant + +void __attribute__((visibility("default"))) tfunc() { + (void)typeid(C *); + (void)typeid(C **); + (void)typeid(D *); + (void)typeid(D **); +} + +// unspecified visibility RTTI & vtable +struct s { + virtual void foo(); +}; +void s::foo() {} +// UNSPECIFIED-DEF: @_ZTV1s = unnamed_addr constant +// UNSPECIFIED-HID: @_ZTV1s = hidden unnamed_addr constant +// UNSPECIFIED-EXP: @_ZTV1s = dllexport unnamed_addr constant +// UNSPECIFIED-DEF: @_ZTS1s = constant +// UNSPECIFIED-HID: @_ZTS1s = hidden constant +// UNSPECIFIED-EXP: @_ZTS1s = dllexport constant +// UNSPECIFIED-DEF: @_ZTI1s = constant +// UNSPECIFIED-HID: @_ZTI1s = hidden constant +// UNSPECIFIED-EXP: @_ZTI1s = dllexport constant + +// explicit default visibility RTTI & vtable +struct __attribute__((type_visibility("default"))) t { + virtual void foo(); +}; +void t::foo() {} +// EXPLICIT-DEF: @_ZTV1t = unnamed_addr constant +// EXPLICIT-HID: @_ZTV1t = hidden unnamed_addr constant +// EXPLICIT-EXP: @_ZTV1t = dllexport unnamed_addr constant +// EXPLICIT-DEF: @_ZTS1t = constant +// EXPLICIT-HID: @_ZTS1t = hidden constant +// EXPLICIT-EXP: @_ZTS1t = dllexport constant +// EXPLICIT-DEF: @_ZTI1t = constant +// EXPLICIT-HID: @_ZTI1t = hidden constant +// EXPLICIT-EXP: @_ZTI1t = dllexport constant + +#ifdef FUNDAMENTAL_IS_EXPLICIT +#define TYPE_VIS __attribute__((type_visibility("default"))) +#else +#define TYPE_VIS +#endif + +// Invoke the compiler magic to emit RTTI for fundamental types. +namespace __cxxabiv1 { +class TYPE_VIS __fundamental_type_info { + __attribute__((visibility("hidden"))) virtual ~__fundamental_type_info(); +}; + +__fundamental_type_info::~__fundamental_type_info() {} + +} // namespace __cxxabiv1 + +// __cxxabiv1::__fundamental_type_info +// FUND-DEF: @_ZTVN10__cxxabiv123__fundamental_type_infoE = unnamed_addr constant +// FUND-DEF: @_ZTSN10__cxxabiv123__fundamental_type_infoE = constant +// FUND-DEF: @_ZTIN10__cxxabiv123__fundamental_type_infoE = constant +// FUND-HID: @_ZTVN10__cxxabiv123__fundamental_type_infoE = hidden unnamed_addr constant +// FUND-HID: @_ZTSN10__cxxabiv123__fundamental_type_infoE = hidden constant +// FUND-HID: @_ZTIN10__cxxabiv123__fundamental_type_infoE = hidden constant +// FUND-EXP: @_ZTVN10__cxxabiv123__fundamental_type_infoE = dllexport unnamed_addr constant +// FUND-EXP: @_ZTSN10__cxxabiv123__fundamental_type_infoE = dllexport constant +// FUND-EXP: @_ZTIN10__cxxabiv123__fundamental_type_infoE = dllexport constant + +// void +// FUND-DEF: @_ZTSv = constant +// FUND-DEF: @_ZTIv = constant +// FUND-DEF: @_ZTSPv = constant +// FUND-DEF: @_ZTIPv = constant +// FUND-DEF: @_ZTSPKv = constant +// FUND-DEF: @_ZTIPKv = constant +// FUND-HID: @_ZTSv = hidden constant +// FUND-HID: @_ZTIv = hidden constant +// FUND-HID: @_ZTSPv = hidden constant +// FUND-HID: @_ZTIPv = hidden constant +// FUND-HID: @_ZTSPKv = hidden constant +// FUND-HID: @_ZTIPKv = hidden constant +// FUND-EXP: @_ZTSv = dllexport constant +// FUND-EXP: @_ZTIv = dllexport constant +// FUND-EXP: @_ZTSPv = dllexport constant +// FUND-EXP: @_ZTIPv = dllexport constant +// FUND-EXP: @_ZTSPKv = dllexport constant +// FUND-EXP: @_ZTIPKv = dllexport constant + +// std::nullptr_t +// FUND-DEF: @_ZTSDn = constant +// FUND-DEF: @_ZTIDn = constant +// FUND-DEF: @_ZTSPDn = constant +// FUND-DEF: @_ZTIPDn = constant +// FUND-DEF: @_ZTSPKDn = constant +// FUND-DEF: @_ZTIPKDn = constant +// FUND-HID: @_ZTSDn = hidden constant +// FUND-HID: @_ZTIDn = hidden constant +// FUND-HID: @_ZTSPDn = hidden constant +// FUND-HID: @_ZTIPDn = hidden constant +// FUND-HID: @_ZTSPKDn = hidden constant +// FUND-HID: @_ZTIPKDn = hidden constant +// FUND-EXP: @_ZTSDn = dllexport constant +// FUND-EXP: @_ZTIDn = dllexport constant +// FUND-EXP: @_ZTSPDn = dllexport constant +// FUND-EXP: @_ZTIPDn = dllexport constant +// FUND-EXP: @_ZTSPKDn = dllexport constant +// FUND-EXP: @_ZTIPKDn = dllexport constant + +// bool +// FUND-DEF: @_ZTSb = constant +// FUND-DEF: @_ZTIb = constant +// FUND-DEF: @_ZTSPb = constant +// FUND-DEF: @_ZTIPb = constant +// FUND-DEF: @_ZTSPKb = constant +// FUND-DEF: @_ZTIPKb = constant +// FUND-HID: @_ZTSb = hidden constant +// FUND-HID: @_ZTIb = hidden constant +// FUND-HID: @_ZTSPb = hidden constant +// FUND-HID: @_ZTIPb = hidden constant +// FUND-HID: @_ZTSPKb = hidden constant +// FUND-HID: @_ZTIPKb = hidden constant +// FUND-EXP: @_ZTSb = dllexport constant +// FUND-EXP: @_ZTIb = dllexport constant +// FUND-EXP: @_ZTSPb = dllexport constant +// FUND-EXP: @_ZTIPb = dllexport constant +// FUND-EXP: @_ZTSPKb = dllexport constant +// FUND-EXP: @_ZTIPKb = dllexport constant + +// wchar_t +// FUND-DEF: @_ZTSw = constant +// FUND-DEF: @_ZTIw = constant +// FUND-DEF: @_ZTSPw = constant +// FUND-DEF: @_ZTIPw = constant +// FUND-DEF: @_ZTSPKw = constant +// FUND-DEF: @_ZTIPKw = constant +// FUND-HID: @_ZTSw = hidden constant +// FUND-HID: @_ZTIw = hidden constant +// FUND-HID: @_ZTSPw = hidden constant +// FUND-HID: @_ZTIPw = hidden constant +// FUND-HID: @_ZTSPKw = hidden constant +// FUND-HID: @_ZTIPKw = hidden constant +// FUND-EXP: @_ZTSw = dllexport constant +// FUND-EXP: @_ZTIw = dllexport constant +// FUND-EXP: @_ZTSPw = dllexport constant +// FUND-EXP: @_ZTIPw = dllexport constant +// FUND-EXP: @_ZTSPKw = dllexport constant +// FUND-EXP: @_ZTIPKw = dllexport constant + +// char +// FUND-DEF: @_ZTSc = constant +// FUND-DEF: @_ZTIc = constant +// FUND-DEF: @_ZTSPc = constant +// FUND-DEF: @_ZTIPc = constant +// FUND-DEF: @_ZTSPKc = constant +// FUND-DEF: @_ZTIPKc = constant +// FUND-HID: @_ZTSc = hidden constant +// FUND-HID: @_ZTIc = hidden constant +// FUND-HID: @_ZTSPc = hidden constant +// FUND-HID: @_ZTIPc = hidden constant +// FUND-HID: @_ZTSPKc = hidden constant +// FUND-HID: @_ZTIPKc = hidden constant +// FUND-EXP: @_ZTSc = dllexport constant +// FUND-EXP: @_ZTIc = dllexport constant +// FUND-EXP: @_ZTSPc = dllexport constant +// FUND-EXP: @_ZTIPc = dllexport constant +// FUND-EXP: @_ZTSPKc = dllexport constant +// FUND-EXP: @_ZTIPKc = dllexport constant + +// unsigned char +// FUND-DEF: @_ZTSh = constant +// FUND-DEF: @_ZTIh = constant +// FUND-DEF: @_ZTSPh = constant +// FUND-DEF: @_ZTIPh = constant +// FUND-DEF: @_ZTSPKh = constant +// FUND-DEF: @_ZTIPKh = constant +// FUND-HID: @_ZTSh = hidden constant +// FUND-HID: @_ZTIh = hidden constant +// FUND-HID: @_ZTSPh = hidden constant +// FUND-HID: @_ZTIPh = hidden constant +// FUND-HID: @_ZTSPKh = hidden constant +// FUND-HID: @_ZTIPKh = hidden constant +// FUND-EXP: @_ZTSh = dllexport constant +// FUND-EXP: @_ZTIh = dllexport constant +// FUND-EXP: @_ZTSPh = dllexport constant +// FUND-EXP: @_ZTIPh = dllexport constant +// FUND-EXP: @_ZTSPKh = dllexport constant +// FUND-EXP: @_ZTIPKh = dllexport constant + +// signed char +// FUND-DEF: @_ZTSa = constant +// FUND-DEF: @_ZTIa = constant +// FUND-DEF: @_ZTSPa = constant +// FUND-DEF: @_ZTIPa = constant +// FUND-DEF: @_ZTSPKa = constant +// FUND-DEF: @_ZTIPKa = constant +// FUND-HID: @_ZTSa = hidden constant +// FUND-HID: @_ZTIa = hidden constant +// FUND-HID: @_ZTSPa = hidden constant +// FUND-HID: @_ZTIPa = hidden constant +// FUND-HID: @_ZTSPKa = hidden constant +// FUND-HID: @_ZTIPKa = hidden constant +// FUND-EXP: @_ZTSa = dllexport constant +// FUND-EXP: @_ZTIa = dllexport constant +// FUND-EXP: @_ZTSPa = dllexport constant +// FUND-EXP: @_ZTIPa = dllexport constant +// FUND-EXP: @_ZTSPKa = dllexport constant +// FUND-EXP: @_ZTIPKa = dllexport constant + +// short +// FUND-DEF: @_ZTSs = constant +// FUND-DEF: @_ZTIs = constant +// FUND-DEF: @_ZTSPs = constant +// FUND-DEF: @_ZTIPs = constant +// FUND-DEF: @_ZTSPKs = constant +// FUND-DEF: @_ZTIPKs = constant +// FUND-HID: @_ZTSs = hidden constant +// FUND-HID: @_ZTIs = hidden constant +// FUND-HID: @_ZTSPs = hidden constant +// FUND-HID: @_ZTIPs = hidden constant +// FUND-HID: @_ZTSPKs = hidden constant +// FUND-HID: @_ZTIPKs = hidden constant +// FUND-EXP: @_ZTSs = dllexport constant +// FUND-EXP: @_ZTIs = dllexport constant +// FUND-EXP: @_ZTSPs = dllexport constant +// FUND-EXP: @_ZTIPs = dllexport constant +// FUND-EXP: @_ZTSPKs = dllexport constant +// FUND-EXP: @_ZTIPKs = dllexport constant + +// unsigned short +// FUND-DEF: @_ZTSt = constant +// FUND-DEF: @_ZTIt = constant +// FUND-DEF: @_ZTSPt = constant +// FUND-DEF: @_ZTIPt = constant +// FUND-DEF: @_ZTSPKt = constant +// FUND-DEF: @_ZTIPKt = constant +// FUND-HID: @_ZTSt = hidden constant +// FUND-HID: @_ZTIt = hidden constant +// FUND-HID: @_ZTSPt = hidden constant +// FUND-HID: @_ZTIPt = hidden constant +// FUND-HID: @_ZTSPKt = hidden constant +// FUND-HID: @_ZTIPKt = hidden constant +// FUND-EXP: @_ZTSt = dllexport constant +// FUND-EXP: @_ZTIt = dllexport constant +// FUND-EXP: @_ZTSPt = dllexport constant +// FUND-EXP: @_ZTIPt = dllexport constant +// FUND-EXP: @_ZTSPKt = dllexport constant +// FUND-EXP: @_ZTIPKt = dllexport constant + +// int +// FUND-DEF: @_ZTSi = constant +// FUND-DEF: @_ZTIi = constant +// FUND-DEF: @_ZTSPi = constant +// FUND-DEF: @_ZTIPi = constant +// FUND-DEF: @_ZTSPKi = constant +// FUND-DEF: @_ZTIPKi = constant +// FUND-HID: @_ZTSi = hidden constant +// FUND-HID: @_ZTIi = hidden constant +// FUND-HID: @_ZTSPi = hidden constant +// FUND-HID: @_ZTIPi = hidden constant +// FUND-HID: @_ZTSPKi = hidden constant +// FUND-HID: @_ZTIPKi = hidden constant +// FUND-EXP: @_ZTSi = dllexport constant +// FUND-EXP: @_ZTIi = dllexport constant +// FUND-EXP: @_ZTSPi = dllexport constant +// FUND-EXP: @_ZTIPi = dllexport constant +// FUND-EXP: @_ZTSPKi = dllexport constant +// FUND-EXP: @_ZTIPKi = dllexport constant + +// unsigned int +// FUND-DEF: @_ZTSj = constant +// FUND-DEF: @_ZTIj = constant +// FUND-DEF: @_ZTSPj = constant +// FUND-DEF: @_ZTIPj = constant +// FUND-DEF: @_ZTSPKj = constant +// FUND-DEF: @_ZTIPKj = constant +// FUND-HID: @_ZTSj = hidden constant +// FUND-HID: @_ZTIj = hidden constant +// FUND-HID: @_ZTSPj = hidden constant +// FUND-HID: @_ZTIPj = hidden constant +// FUND-HID: @_ZTSPKj = hidden constant +// FUND-HID: @_ZTIPKj = hidden constant +// FUND-EXP: @_ZTSj = dllexport constant +// FUND-EXP: @_ZTIj = dllexport constant +// FUND-EXP: @_ZTSPj = dllexport constant +// FUND-EXP: @_ZTIPj = dllexport constant +// FUND-EXP: @_ZTSPKj = dllexport constant +// FUND-EXP: @_ZTIPKj = dllexport constant + +// long +// FUND-DEF: @_ZTSl = constant +// FUND-DEF: @_ZTIl = constant +// FUND-DEF: @_ZTSPl = constant +// FUND-DEF: @_ZTIPl = constant +// FUND-DEF: @_ZTSPKl = constant +// FUND-DEF: @_ZTIPKl = constant +// FUND-HID: @_ZTSl = hidden constant +// FUND-HID: @_ZTIl = hidden constant +// FUND-HID: @_ZTSPl = hidden constant +// FUND-HID: @_ZTIPl = hidden constant +// FUND-HID: @_ZTSPKl = hidden constant +// FUND-HID: @_ZTIPKl = hidden constant +// FUND-EXP: @_ZTSl = dllexport constant +// FUND-EXP: @_ZTIl = dllexport constant +// FUND-EXP: @_ZTSPl = dllexport constant +// FUND-EXP: @_ZTIPl = dllexport constant +// FUND-EXP: @_ZTSPKl = dllexport constant +// FUND-EXP: @_ZTIPKl = dllexport constant + +// unsigned long +// FUND-DEF: @_ZTSm = constant +// FUND-DEF: @_ZTIm = constant +// FUND-DEF: @_ZTSPm = constant +// FUND-DEF: @_ZTIPm = constant +// FUND-DEF: @_ZTSPKm = constant +// FUND-DEF: @_ZTIPKm = constant +// FUND-HID: @_ZTSm = hidden constant +// FUND-HID: @_ZTIm = hidden constant +// FUND-HID: @_ZTSPm = hidden constant +// FUND-HID: @_ZTIPm = hidden constant +// FUND-HID: @_ZTSPKm = hidden constant +// FUND-HID: @_ZTIPKm = hidden constant +// FUND-EXP: @_ZTSm = dllexport constant +// FUND-EXP: @_ZTIm = dllexport constant +// FUND-EXP: @_ZTSPm = dllexport constant +// FUND-EXP: @_ZTIPm = dllexport constant +// FUND-EXP: @_ZTSPKm = dllexport constant +// FUND-EXP: @_ZTIPKm = dllexport constant + +// long long +// FUND-DEF: @_ZTSx = constant +// FUND-DEF: @_ZTIx = constant +// FUND-DEF: @_ZTSPx = constant +// FUND-DEF: @_ZTIPx = constant +// FUND-DEF: @_ZTSPKx = constant +// FUND-DEF: @_ZTIPKx = constant +// FUND-HID: @_ZTSx = hidden constant +// FUND-HID: @_ZTIx = hidden constant +// FUND-HID: @_ZTSPx = hidden constant +// FUND-HID: @_ZTIPx = hidden constant +// FUND-HID: @_ZTSPKx = hidden constant +// FUND-HID: @_ZTIPKx = hidden constant +// FUND-EXP: @_ZTSx = dllexport constant +// FUND-EXP: @_ZTIx = dllexport constant +// FUND-EXP: @_ZTSPx = dllexport constant +// FUND-EXP: @_ZTIPx = dllexport constant +// FUND-EXP: @_ZTSPKx = dllexport constant +// FUND-EXP: @_ZTIPKx = dllexport constant + +// unsigned long long +// FUND-DEF: @_ZTSy = constant +// FUND-DEF: @_ZTIy = constant +// FUND-DEF: @_ZTSPy = constant +// FUND-DEF: @_ZTIPy = constant +// FUND-DEF: @_ZTSPKy = constant +// FUND-DEF: @_ZTIPKy = constant +// FUND-HID: @_ZTSy = hidden constant +// FUND-HID: @_ZTIy = hidden constant +// FUND-HID: @_ZTSPy = hidden constant +// FUND-HID: @_ZTIPy = hidden constant +// FUND-HID: @_ZTSPKy = hidden constant +// FUND-HID: @_ZTIPKy = hidden constant +// FUND-EXP: @_ZTSy = dllexport constant +// FUND-EXP: @_ZTIy = dllexport constant +// FUND-EXP: @_ZTSPy = dllexport constant +// FUND-EXP: @_ZTIPy = dllexport constant +// FUND-EXP: @_ZTSPKy = dllexport constant +// FUND-EXP: @_ZTIPKy = dllexport constant + +// __int128 +// FUND-DEF: @_ZTSn = constant +// FUND-DEF: @_ZTIn = constant +// FUND-DEF: @_ZTSPn = constant +// FUND-DEF: @_ZTIPn = constant +// FUND-DEF: @_ZTSPKn = constant +// FUND-DEF: @_ZTIPKn = constant +// FUND-HID: @_ZTSn = hidden constant +// FUND-HID: @_ZTIn = hidden constant +// FUND-HID: @_ZTSPn = hidden constant +// FUND-HID: @_ZTIPn = hidden constant +// FUND-HID: @_ZTSPKn = hidden constant +// FUND-HID: @_ZTIPKn = hidden constant +// FUND-EXP: @_ZTSn = dllexport constant +// FUND-EXP: @_ZTIn = dllexport constant +// FUND-EXP: @_ZTSPn = dllexport constant +// FUND-EXP: @_ZTIPn = dllexport constant +// FUND-EXP: @_ZTSPKn = dllexport constant +// FUND-EXP: @_ZTIPKn = dllexport constant + +// unsigned __int128 +// FUND-DEF: @_ZTSo = constant +// FUND-DEF: @_ZTIo = constant +// FUND-DEF: @_ZTSPo = constant +// FUND-DEF: @_ZTIPo = constant +// FUND-DEF: @_ZTSPKo = constant +// FUND-DEF: @_ZTIPKo = constant +// FUND-HID: @_ZTSo = hidden constant +// FUND-HID: @_ZTIo = hidden constant +// FUND-HID: @_ZTSPo = hidden constant +// FUND-HID: @_ZTIPo = hidden constant +// FUND-HID: @_ZTSPKo = hidden constant +// FUND-HID: @_ZTIPKo = hidden constant +// FUND-EXP: @_ZTSo = dllexport constant +// FUND-EXP: @_ZTIo = dllexport constant +// FUND-EXP: @_ZTSPo = dllexport constant +// FUND-EXP: @_ZTIPo = dllexport constant +// FUND-EXP: @_ZTSPKo = dllexport constant +// FUND-EXP: @_ZTIPKo = dllexport constant + +// half +// FUND-DEF: @_ZTSDh = constant +// FUND-DEF: @_ZTIDh = constant +// FUND-DEF: @_ZTSPDh = constant +// FUND-DEF: @_ZTIPDh = constant +// FUND-DEF: @_ZTSPKDh = constant +// FUND-DEF: @_ZTIPKDh = constant +// FUND-HID: @_ZTSDh = hidden constant +// FUND-HID: @_ZTIDh = hidden constant +// FUND-HID: @_ZTSPDh = hidden constant +// FUND-HID: @_ZTIPDh = hidden constant +// FUND-HID: @_ZTSPKDh = hidden constant +// FUND-HID: @_ZTIPKDh = hidden constant +// FUND-EXP: @_ZTSDh = dllexport constant +// FUND-EXP: @_ZTIDh = dllexport constant +// FUND-EXP: @_ZTSPDh = dllexport constant +// FUND-EXP: @_ZTIPDh = dllexport constant +// FUND-EXP: @_ZTSPKDh = dllexport constant +// FUND-EXP: @_ZTIPKDh = dllexport constant + +// float +// FUND-DEF: @_ZTSf = constant +// FUND-DEF: @_ZTIf = constant +// FUND-DEF: @_ZTSPf = constant +// FUND-DEF: @_ZTIPf = constant +// FUND-DEF: @_ZTSPKf = constant +// FUND-DEF: @_ZTIPKf = constant +// FUND-HID: @_ZTSf = hidden constant +// FUND-HID: @_ZTIf = hidden constant +// FUND-HID: @_ZTSPf = hidden constant +// FUND-HID: @_ZTIPf = hidden constant +// FUND-HID: @_ZTSPKf = hidden constant +// FUND-HID: @_ZTIPKf = hidden constant +// FUND-EXP: @_ZTSf = dllexport constant +// FUND-EXP: @_ZTIf = dllexport constant +// FUND-EXP: @_ZTSPf = dllexport constant +// FUND-EXP: @_ZTIPf = dllexport constant +// FUND-EXP: @_ZTSPKf = dllexport constant +// FUND-EXP: @_ZTIPKf = dllexport constant + +// double +// FUND-DEF: @_ZTSd = constant +// FUND-DEF: @_ZTId = constant +// FUND-DEF: @_ZTSPd = constant +// FUND-DEF: @_ZTIPd = constant +// FUND-DEF: @_ZTSPKd = constant +// FUND-DEF: @_ZTIPKd = constant +// FUND-HID: @_ZTSd = hidden constant +// FUND-HID: @_ZTId = hidden constant +// FUND-HID: @_ZTSPd = hidden constant +// FUND-HID: @_ZTIPd = hidden constant +// FUND-HID: @_ZTSPKd = hidden constant +// FUND-HID: @_ZTIPKd = hidden constant +// FUND-EXP: @_ZTSd = dllexport constant +// FUND-EXP: @_ZTId = dllexport constant +// FUND-EXP: @_ZTSPd = dllexport constant +// FUND-EXP: @_ZTIPd = dllexport constant +// FUND-EXP: @_ZTSPKd = dllexport constant +// FUND-EXP: @_ZTIPKd = dllexport constant + +// long double +// FUND-DEF: @_ZTSe = constant +// FUND-DEF: @_ZTIe = constant +// FUND-DEF: @_ZTSPe = constant +// FUND-DEF: @_ZTIPe = constant +// FUND-DEF: @_ZTSPKe = constant +// FUND-DEF: @_ZTIPKe = constant +// FUND-HID: @_ZTSe = hidden constant +// FUND-HID: @_ZTIe = hidden constant +// FUND-HID: @_ZTSPe = hidden constant +// FUND-HID: @_ZTIPe = hidden constant +// FUND-HID: @_ZTSPKe = hidden constant +// FUND-HID: @_ZTIPKe = hidden constant +// FUND-EXP: @_ZTSe = dllexport constant +// FUND-EXP: @_ZTIe = dllexport constant +// FUND-EXP: @_ZTSPe = dllexport constant +// FUND-EXP: @_ZTIPe = dllexport constant +// FUND-EXP: @_ZTSPKe = dllexport constant +// FUND-EXP: @_ZTIPKe = dllexport constant + +// __ieee128 +// FUND-DEF: @_ZTSu9__ieee128 = constant +// FUND-DEF: @_ZTIu9__ieee128 = constant +// FUND-DEF: @_ZTSPu9__ieee128 = constant +// FUND-DEF: @_ZTIPu9__ieee128 = constant +// FUND-DEF: @_ZTSPKu9__ieee128 = constant +// FUND-DEF: @_ZTIPKu9__ieee128 = constant +// FUND-HID: @_ZTSu9__ieee128 = hidden constant +// FUND-HID: @_ZTIu9__ieee128 = hidden constant +// FUND-HID: @_ZTSPu9__ieee128 = hidden constant +// FUND-HID: @_ZTIPu9__ieee128 = hidden constant +// FUND-HID: @_ZTSPKu9__ieee128 = hidden constant +// FUND-HID: @_ZTIPKu9__ieee128 = hidden constant +// FUND-EXP: @_ZTSu9__ieee128 = dllexport constant +// FUND-EXP: @_ZTIu9__ieee128 = dllexport constant +// FUND-EXP: @_ZTSPu9__ieee128 = dllexport constant +// FUND-EXP: @_ZTIPu9__ieee128 = dllexport constant +// FUND-EXP: @_ZTSPKu9__ieee128 = dllexport constant +// FUND-EXP: @_ZTIPKu9__ieee128 = dllexport constant + +// char8_t +// FUND-DEF: @_ZTSDu = constant +// FUND-DEF: @_ZTIDu = constant +// FUND-DEF: @_ZTSPDu = constant +// FUND-DEF: @_ZTIPDu = constant +// FUND-DEF: @_ZTSPKDu = constant +// FUND-DEF: @_ZTIPKDu = constant +// FUND-HID: @_ZTSDu = hidden constant +// FUND-HID: @_ZTIDu = hidden constant +// FUND-HID: @_ZTSPDu = hidden constant +// FUND-HID: @_ZTIPDu = hidden constant +// FUND-HID: @_ZTSPKDu = hidden constant +// FUND-HID: @_ZTIPKDu = hidden constant +// FUND-EXP: @_ZTSDu = dllexport constant +// FUND-EXP: @_ZTIDu = dllexport constant +// FUND-EXP: @_ZTSPDu = dllexport constant +// FUND-EXP: @_ZTIPDu = dllexport constant +// FUND-EXP: @_ZTSPKDu = dllexport constant +// FUND-EXP: @_ZTIPKDu = dllexport constant + +// char16_t +// FUND-DEF: @_ZTSDs = constant +// FUND-DEF: @_ZTIDs = constant +// FUND-DEF: @_ZTSPDs = constant +// FUND-DEF: @_ZTIPDs = constant +// FUND-DEF: @_ZTSPKDs = constant +// FUND-DEF: @_ZTIPKDs = constant +// FUND-HID: @_ZTSDs = hidden constant +// FUND-HID: @_ZTIDs = hidden constant +// FUND-HID: @_ZTSPDs = hidden constant +// FUND-HID: @_ZTIPDs = hidden constant +// FUND-HID: @_ZTSPKDs = hidden constant +// FUND-HID: @_ZTIPKDs = hidden constant +// FUND-EXP: @_ZTSDs = dllexport constant +// FUND-EXP: @_ZTIDs = dllexport constant +// FUND-EXP: @_ZTSPDs = dllexport constant +// FUND-EXP: @_ZTIPDs = dllexport constant +// FUND-EXP: @_ZTSPKDs = dllexport constant +// FUND-EXP: @_ZTIPKDs = dllexport constant + +// char32_t +// FUND-DEF: @_ZTSDi = constant +// FUND-DEF: @_ZTIDi = constant +// FUND-DEF: @_ZTSPDi = constant +// FUND-DEF: @_ZTIPDi = constant +// FUND-DEF: @_ZTSPKDi = constant +// FUND-DEF: @_ZTIPKDi = constant +// FUND-HID: @_ZTSDi = hidden constant +// FUND-HID: @_ZTIDi = hidden constant +// FUND-HID: @_ZTSPDi = hidden constant +// FUND-HID: @_ZTIPDi = hidden constant +// FUND-HID: @_ZTSPKDi = hidden constant +// FUND-HID: @_ZTIPKDi = hidden constant +// FUND-EXP: @_ZTSDi = dllexport constant +// FUND-EXP: @_ZTIDi = dllexport constant +// FUND-EXP: @_ZTSPDi = dllexport constant +// FUND-EXP: @_ZTIPDi = dllexport constant +// FUND-EXP: @_ZTSPKDi = dllexport constant +// FUND-EXP: @_ZTIPKDi = dllexport constant diff --git a/clang/test/CodeGenCXX/mdefault-visibility-export-mapping.cpp b/clang/test/CodeGenCXX/mdefault-visibility-export-mapping.cpp new file mode 100644 index 0000000000000..6e61f1812f57b --- /dev/null +++ b/clang/test/CodeGenCXX/mdefault-visibility-export-mapping.cpp @@ -0,0 +1,119 @@ +// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=CHECK,UNSPECIFIED-DEF,EXPLICIT-DEF %s +// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -mdefault-visibility-export-mapping=none -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=CHECK,UNSPECIFIED-DEF,EXPLICIT-DEF %s +// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -mdefault-visibility-export-mapping=explicit -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=CHECK,UNSPECIFIED-DEF,EXPLICIT-EXP %s +// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -mdefault-visibility-export-mapping=all -S -emit-llvm -o - | \ +// RUN: FileCheck -check-prefixes=CHECK,UNSPECIFIED-EXP,EXPLICIT-EXP %s + +struct A {}; + +template +class B { +public: + T x; + B(T _x) : x(_x) {} + ~B() {} + void func(T x) {} +}; + +template +class __attribute__((visibility("default"))) C { +public: + T x; + C(T _x) : x(_x) {} + ~C() {} + void func(T x) {} +}; + +class D { +public: + ~D(); +}; + +D::~D() {} + +extern template class B; +extern template class C; + +void func() { + B x({}); + C y({}); + x.func({}); + y.func({}); + B xi(0); + C yi(0); + xi.func(0); + yi.func(0); + D z; +} + +// D::~D() (base object destructor) +// UNSPECIFIED-DEF: define void @_ZN1DD2Ev( +// UNSPECIFIED-EXP: define dllexport void @_ZN1DD2Ev( + +// D::~D() (complete object destructor) +// UNSPECIFIED-DEF: define void @_ZN1DD1Ev( +// UNSPECIFIED-EXP: define dllexport void @_ZN1DD1Ev( + +// UNSPECIFIED-DEF: define void @_Z4funcv( +// UNSPECIFIED-EXP: define dllexport void @_Z4funcv( + +// B::B(A) (complete object constructor) +// UNSPECIFIED-DEF: define linkonce_odr void @_ZN1BI1AEC1ES0_( +// UNSPECIFIED-EXP: define linkonce_odr dllexport void @_ZN1BI1AEC1ES0_( + +// C::C(A) (complete object constructor) +// EXPLICIT-DEF: define linkonce_odr void @_ZN1CI1AEC1ES0_( +// EXPLICIT-EXP: define linkonce_odr dllexport void @_ZN1CI1AEC1ES0_( + +// B::func(A) +// UNSPECIFIED-DEF: define linkonce_odr void @_ZN1BI1AE4funcES0_( +// UNSPECIFIED-EXP: define linkonce_odr dllexport void @_ZN1BI1AE4funcES0_( + +// C::func(A) +// EXPLICIT-DEF: define linkonce_odr void @_ZN1CI1AE4funcES0_( +// EXPLICIT-EXP: define linkonce_odr dllexport void @_ZN1CI1AE4funcES0_( + +// B::B(int) (complete object constructor) +// CHECK: declare void @_ZN1BIiEC1Ei + +// C::C(int) (complete object constructor) +// CHECK: declare void @_ZN1CIiEC1Ei + +// B::func(int) +// CHECK: declare void @_ZN1BIiE4funcEi + +// C::func(int) +// CHECK: declare void @_ZN1CIiE4funcEi + +// C::~C() (complete object destructor) +// CHECK: declare void @_ZN1CIiED1Ev + +// B::~B() (complete object destructor) +// CHECK: declare void @_ZN1BIiED1Ev + +// C::~c() (complete object destructor) +// EXPLICIT-DEF: define linkonce_odr void @_ZN1CI1AED1Ev( +// EXPLICIT-EXP: define linkonce_odr dllexport void @_ZN1CI1AED1Ev( + +// B::~B() (complete object destructor) +// UNSPECIFIED-DEF: define linkonce_odr void @_ZN1BI1AED1Ev( +// UNSPECIFIED-EXP: define linkonce_odr dllexport void @_ZN1BI1AED1Ev( + +// B::B(A) (base object constructor) +// UNSPECIFIED-DEF: define linkonce_odr void @_ZN1BI1AEC2ES0_( +// UNSPECIFIED-EXP: define linkonce_odr dllexport void @_ZN1BI1AEC2ES0_( + +// B::~B() (base object destructor) +// UNSPECIFIED-DEF: define linkonce_odr void @_ZN1BI1AED2Ev( +// UNSPECIFIED-EXP: define linkonce_odr dllexport void @_ZN1BI1AED2Ev( + +// C::C(A) (base object constructor) +// EXPLICIT-DEF: define linkonce_odr void @_ZN1CI1AEC2ES0_( +// EXPLICIT-EXP: define linkonce_odr dllexport void @_ZN1CI1AEC2ES0_( + +// C::~C() (base object destructor) +// EXPLICIT-DEF: define linkonce_odr void @_ZN1CI1AED2Ev( +// EXPLICIT-EXP: define linkonce_odr dllexport void @_ZN1CI1AED2Ev( diff --git a/clang/test/CodeGenCXX/weak-init.cpp b/clang/test/CodeGenCXX/weak-init.cpp new file mode 100644 index 0000000000000..634021f38f854 --- /dev/null +++ b/clang/test/CodeGenCXX/weak-init.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s + +extern const int W __attribute__((weak)) = 99; +const int S = 77; + +// CHECK: @C1 = {{.*}} 77 +extern const int C1 = S; + +// CHECK: %0 = load {{.*}} @W +// CHECK-NEXT: store {{.*}} %0, {{.*}} @C2 +extern const int C2 = W; diff --git a/clang/test/CodeGenCoroutines/coro-attributes.cpp b/clang/test/CodeGenCoroutines/coro-attributes.cpp index df18e0c046bf0..ecd298e6b4b57 100644 --- a/clang/test/CodeGenCoroutines/coro-attributes.cpp +++ b/clang/test/CodeGenCoroutines/coro-attributes.cpp @@ -14,7 +14,7 @@ struct coro { }; // CHECK: void @_Z3foov() #[[FOO_ATTR_NUM:[0-9]+]] -// CHECK: attributes #[[FOO_ATTR_NUM]] = { {{.*}} "coroutine.presplit"="0" +// CHECK: attributes #[[FOO_ATTR_NUM]] = { {{.*}} presplitcoroutine coro foo() { co_await suspend_always{}; } diff --git a/clang/test/CodeGenHLSL/basic_types.hlsl b/clang/test/CodeGenHLSL/basic_types.hlsl new file mode 100644 index 0000000000000..fcb0815c3af57 --- /dev/null +++ b/clang/test/CodeGenHLSL/basic_types.hlsl @@ -0,0 +1,76 @@ +// RUN: %clang_dxc -Tlib_6_7 -fcgl -Fo - %s | FileCheck %s + +// FIXME: check 16bit types once enable-16bit-types is ready. + +// CHECK:@uint_Val = global i32 0, align 4 +// CHECK:@uint64_t_Val = global i64 0, align 8 +// CHECK:@int64_t_Val = global i64 0, align 8 +// CHECK:@int2_Val = global <2 x i32> zeroinitializer, align 8 +// CHECK:@int3_Val = global <3 x i32> zeroinitializer, align 16 +// CHECK:@int4_Val = global <4 x i32> zeroinitializer, align 16 +// CHECK:@uint2_Val = global <2 x i32> zeroinitializer, align 8 +// CHECK:@uint3_Val = global <3 x i32> zeroinitializer, align 16 +// CHECK:@uint4_Val = global <4 x i32> zeroinitializer, align 16 +// CHECK:@int64_t2_Val = global <2 x i64> zeroinitializer, align 16 +// CHECK:@int64_t3_Val = global <3 x i64> zeroinitializer, align 32 +// CHECK:@int64_t4_Val = global <4 x i64> zeroinitializer, align 32 +// CHECK:@uint64_t2_Val = global <2 x i64> zeroinitializer, align 16 +// CHECK:@uint64_t3_Val = global <3 x i64> zeroinitializer, align 32 +// CHECK:@uint64_t4_Val = global <4 x i64> zeroinitializer, align 32 +// CHECK:@float2_Val = global <2 x float> zeroinitializer, align 8 +// CHECK:@float3_Val = global <3 x float> zeroinitializer, align 16 +// CHECK:@float4_Val = global <4 x float> zeroinitializer, align 16 +// CHECK:@double2_Val = global <2 x double> zeroinitializer, align 16 +// CHECK:@double3_Val = global <3 x double> zeroinitializer, align 32 +// CHECK:@double4_Val = global <4 x double> zeroinitializer, align 32 + +#define TYPE_DECL(T) T T##_Val + +#ifdef __HLSL_ENABLE_16_BIT +TYPE_DECL(uint16_t); +TYPE_DECL(int16_t); +#endif + +// unsigned 32-bit integer. +TYPE_DECL(uint); + +// 64-bit integer. +TYPE_DECL(uint64_t); +TYPE_DECL(int64_t); + +// built-in vector data types: + +#ifdef __HLSL_ENABLE_16_BIT +TYPE_DECL(int16_t2 ); +TYPE_DECL(int16_t3 ); +TYPE_DECL(int16_t4 ); +TYPE_DECL( uint16_t2 ); +TYPE_DECL( uint16_t3 ); +TYPE_DECL( uint16_t4 ); +#endif + +TYPE_DECL( int2 ); +TYPE_DECL( int3 ); +TYPE_DECL( int4 ); +TYPE_DECL( uint2 ); +TYPE_DECL( uint3 ); +TYPE_DECL( uint4 ); +TYPE_DECL( int64_t2 ); +TYPE_DECL( int64_t3 ); +TYPE_DECL( int64_t4 ); +TYPE_DECL( uint64_t2 ); +TYPE_DECL( uint64_t3 ); +TYPE_DECL( uint64_t4 ); + +#ifdef __HLSL_ENABLE_16_BIT +TYPE_DECL(half2 ); +TYPE_DECL(half3 ); +TYPE_DECL(half4 ); +#endif + +TYPE_DECL( float2 ); +TYPE_DECL( float3 ); +TYPE_DECL( float4 ); +TYPE_DECL( double2 ); +TYPE_DECL( double3 ); +TYPE_DECL( double4 ); diff --git a/clang/test/Driver/Inputs/basic_avr_tree/usr/bin/ld.lld b/clang/test/Driver/Inputs/basic_avr_tree/usr/bin/ld.lld new file mode 100755 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/ananas.c b/clang/test/Driver/ananas.c index a6cabed9b190a..463797470f534 100644 --- a/clang/test/Driver/ananas.c +++ b/clang/test/Driver/ananas.c @@ -21,4 +21,4 @@ // RUN: | FileCheck %s --check-prefix=CHECK-RELOCATABLE // CHECK-RELOCATABLE: "-r" // CHECK-RELOCATABLE-NOT: "-l -// CHECK-RELOCATABLE-NOT: {{.*}}crt{{[^.]+}}.o +// CHECK-RELOCATABLE-NOT: /crt{{[^.]+}}.o diff --git a/clang/test/Driver/android-ndk-standalone.cpp b/clang/test/Driver/android-ndk-standalone.cpp index d070250913b2f..aeb2678c9caae 100644 --- a/clang/test/Driver/android-ndk-standalone.cpp +++ b/clang/test/Driver/android-ndk-standalone.cpp @@ -1,12 +1,12 @@ // Test header and library paths when Clang is used with Android standalone // toolchain. // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm-linux-androideabi21 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=arm-linux-androideabi21 \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck %s -// CHECK: {{.*}}clang{{.*}}" "-cc1" +// CHECK: "-cc1" // CHECK: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK: "-internal-isystem" "{{.*}}/include/c++/v1" // CHECK: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include" @@ -32,20 +32,20 @@ // CHECK-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a" // CHECK-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/thumb" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm-linux-androideabi14 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=arm-linux-androideabi14 \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-14 %s // CHECK-14: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi/14" // CHECK-14: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=arm-linux-androideabi21 -stdlib=libstdc++ \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-STDCXX %s -// CHECK-STDCXX: {{.*}}clang{{.*}}" "-cc1" +// CHECK-STDCXX: "-cc1" // CHECK-STDCXX: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-STDCXX: "-internal-isystem" "{{.*}}/include/c++/4.9" // CHECK-STDCXX-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a/thumb" @@ -74,12 +74,12 @@ // CHECK-STDCXX-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a" // CHECK-STDCXX-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/thumb" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target armv7a-none-linux-androideabi21 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=armv7a-none-linux-androideabi21 \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7 %s -// CHECK-ARMV7: {{.*}}clang{{.*}}" "-cc1" +// CHECK-ARMV7: "-cc1" // CHECK-ARMV7: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-ARMV7: "-internal-isystem" "{{.*}}/include/c++/v1" // CHECK-ARMV7: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include" @@ -106,33 +106,33 @@ // CHECK-ARMV7-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib" // // Other flags that can trigger armv7 mode. -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm-linux-androideabi21 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=arm-linux-androideabi21 \ // RUN: -march=armv7 \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7 %s -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm-linux-androideabi21 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=arm-linux-androideabi21 \ // RUN: -march=armv7a \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7 %s -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm-linux-androideabi21 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=arm-linux-androideabi21 \ // RUN: -march=armv7-a \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7 %s // // ARM thumb mode. -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm-linux-androideabi21 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=arm-linux-androideabi21 \ // RUN: -mthumb \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-THUMB %s -// CHECK-THUMB: {{.*}}clang{{.*}}" "-cc1" +// CHECK-THUMB: "-cc1" // CHECK-THUMB: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-THUMB: "-internal-isystem" "{{.*}}/include/c++/v1" // CHECK-THUMB: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include" @@ -160,13 +160,13 @@ // CHECK-THUMB: "-L{{.*}}/sysroot/usr/lib" // // ARM V7 thumb mode. -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm-linux-androideabi21 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=arm-linux-androideabi21 \ // RUN: -march=armv7-a -mthumb \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7THUMB %s -// CHECK-ARMV7THUMB: {{.*}}clang{{.*}}" "-cc1" +// CHECK-ARMV7THUMB: "-cc1" // CHECK-ARMV7THUMB: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-ARMV7THUMB: "-internal-isystem" "{{.*}}/include/c++/v1" // CHECK-ARMV7THUMB: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include" @@ -192,8 +192,8 @@ // CHECK-ARMV7THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a" // CHECK-ARMV7THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib" -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm-linux-androideabi21 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=arm-linux-androideabi21 \ // RUN: -march=armv7-a -mthumb \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ @@ -206,19 +206,19 @@ // CHECK-ARM-MULTILIBS-NEXT: .; // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target armv7a-none-linux-androideabi21 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=armv7a-none-linux-androideabi21 \ // RUN: -mthumb \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7THUMB %s // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target aarch64-linux-android21 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=aarch64-linux-android21 \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-AARCH64 %s -// CHECK-AARCH64: {{.*}}clang{{.*}}" "-cc1" +// CHECK-AARCH64: "-cc1" // CHECK-AARCH64: "-internal-isystem" "{{.*}}/include/c++/v1" // CHECK-AARCH64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/aarch64-linux-android" // CHECK-AARCH64: "-internal-externc-isystem" "{{.*}}/sysroot/include" @@ -229,12 +229,12 @@ // CHECK-AARCH64: "-L{{.*}}/sysroot/usr/lib/aarch64-linux-android" // CHECK-AARCH64: "-L{{.*}}/lib/gcc/aarch64-linux-android/4.9/../../../../aarch64-linux-android/lib" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm64-linux-android21 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=arm64-linux-android21 \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ARM64 %s -// CHECK-ARM64: {{.*}}clang{{.*}}" "-cc1" +// CHECK-ARM64: "-cc1" // CHECK-ARM64: "-internal-isystem" "{{.*}}/include/c++/v1" // CHECK-ARM64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/aarch64-linux-android" // CHECK-ARM64: "-internal-externc-isystem" "{{.*}}/sysroot/include" @@ -245,13 +245,13 @@ // CHECK-ARM64: "-L{{.*}}/sysroot/usr/lib/aarch64-linux-android" // CHECK-ARM64: "-L{{.*}}/lib/gcc/aarch64-linux-android/4.9/../../../../aarch64-linux-android/lib" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target mipsel-linux-android21 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=mipsel-linux-android21 \ // RUN: -mips32 \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-MIPS %s -// CHECK-MIPS: {{.*}}clang{{.*}}" "-cc1" +// CHECK-MIPS: "-cc1" // CHECK-MIPS: "-internal-isystem" "{{.*}}/include/c++/v1" // CHECK-MIPS: "-internal-externc-isystem" "{{.*}}/sysroot/include" // CHECK-MIPS: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include" @@ -261,12 +261,12 @@ // CHECK-MIPS: "-L{{.*}}/sysroot/usr/lib/mipsel-linux-android" // CHECK-MIPS: "-L{{.*}}/lib/gcc/mipsel-linux-android/4.9/../../../../mipsel-linux-android/lib" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target i686-linux-android21 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=i686-linux-android21 \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-I686 %s -// CHECK-I686: {{.*}}clang{{.*}}" "-cc1" +// CHECK-I686: "-cc1" // CHECK-I686: "-internal-isystem" "{{.*}}/include/c++/v1" // CHECK-I686: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/i686-linux-android" // CHECK-I686: "-internal-externc-isystem" "{{.*}}/sysroot/include" @@ -277,12 +277,12 @@ // CHECK-I686: "-L{{.*}}/sysroot/usr/lib/i686-linux-android" // CHECK-I686: "-L{{.*}}/lib/gcc/i686-linux-android/4.9/../../../../i686-linux-android/lib" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target x86_64-linux-android21 \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=x86_64-linux-android21 \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree \ // RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-X86_64 %s -// CHECK-X86_64: {{.*}}clang{{.*}}" "-cc1" +// CHECK-X86_64: "-cc1" // CHECK-X86_64: "-internal-isystem" "{{.*}}/include/c++/v1" // CHECK-X86_64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/x86_64-linux-android" // CHECK-X86_64: "-internal-externc-isystem" "{{.*}}/sysroot/include" diff --git a/clang/test/Driver/android-standalone.cpp b/clang/test/Driver/android-standalone.cpp index c238fc7347169..7363497c880a5 100644 --- a/clang/test/Driver/android-standalone.cpp +++ b/clang/test/Driver/android-standalone.cpp @@ -1,12 +1,12 @@ // Test header and library paths when Clang is used with Android standalone // toolchain. // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm-linux-androideabi -stdlib=libstdc++ \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=arm-linux-androideabi -stdlib=libstdc++ \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_tree \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck %s -// CHECK: {{.*}}clang{{.*}}" "-cc1" +// CHECK: "-cc1" // CHECK: "-internal-isystem" "{{.*}}/arm-linux-androideabi/include/c++/4.4.3" // CHECK: "-internal-isystem" "{{.*}}/arm-linux-androideabi/include/c++/4.4.3/arm-linux-androideabi" // CHECK: "-internal-externc-isystem" "{{.*}}/sysroot/include" @@ -16,12 +16,12 @@ // CHECK: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/lib" // CHECK: "-L{{.*}}/sysroot/usr/lib" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target aarch64-linux-android -stdlib=libstdc++ \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=aarch64-linux-android -stdlib=libstdc++ \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_tree \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-AARCH64 %s -// CHECK-AARCH64: {{.*}}clang{{.*}}" "-cc1" +// CHECK-AARCH64: "-cc1" // CHECK-AARCH64: "-internal-isystem" "{{.*}}/aarch64-linux-android/include/c++/4.8" // CHECK-AARCH64: "-internal-isystem" "{{.*}}/aarch64-linux-android/include/c++/4.8/aarch64-linux-android" // CHECK-AARCH64: "-internal-externc-isystem" "{{.*}}/sysroot/include" @@ -31,12 +31,12 @@ // CHECK-AARCH64: "-L{{.*}}/lib/gcc/aarch64-linux-android/4.8/../../../../aarch64-linux-android/lib" // CHECK-AARCH64: "-L{{.*}}/sysroot/usr/lib" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm64-linux-android -stdlib=libstdc++ \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=arm64-linux-android -stdlib=libstdc++ \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_tree \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ARM64 %s -// CHECK-ARM64: {{.*}}clang{{.*}}" "-cc1" +// CHECK-ARM64: "-cc1" // CHECK-ARM64: "-internal-isystem" "{{.*}}/aarch64-linux-android/include/c++/4.8" // CHECK-ARM64: "-internal-isystem" "{{.*}}/aarch64-linux-android/include/c++/4.8/aarch64-linux-android" // CHECK-ARM64: "-internal-externc-isystem" "{{.*}}/sysroot/include" @@ -46,13 +46,13 @@ // CHECK-ARM64: "-L{{.*}}/lib/gcc/aarch64-linux-android/4.8/../../../../aarch64-linux-android/lib" // CHECK-ARM64: "-L{{.*}}/sysroot/usr/lib" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target mipsel-linux-android \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=mipsel-linux-android \ // RUN: -mips32 -stdlib=libstdc++ \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_tree \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-MIPS %s -// CHECK-MIPS: {{.*}}clang{{.*}}" "-cc1" +// CHECK-MIPS: "-cc1" // CHECK-MIPS: "-internal-isystem" "{{.*}}/mipsel-linux-android/include/c++/4.4.3" // CHECK-MIPS: "-internal-isystem" "{{.*}}/mipsel-linux-android/include/c++/4.4.3/mipsel-linux-android" // CHECK-MIPS: "-internal-externc-isystem" "{{.*}}/sysroot/include" @@ -62,13 +62,13 @@ // CHECK-MIPS: "-L{{.*}}/lib/gcc/mipsel-linux-android/4.4.3/../../../../mipsel-linux-android/lib" // CHECK-MIPS: "-L{{.*}}/sysroot/usr/lib" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target mipsel-linux-android \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=mipsel-linux-android \ // RUN: -march=mips32 -mips32r2 -stdlib=libstdc++ \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_tree \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-MIPSR2 %s -// CHECK-MIPSR2: {{.*}}clang{{.*}}" "-cc1" +// CHECK-MIPSR2: "-cc1" // CHECK-MIPSR2: "-internal-isystem" "{{.*}}/mipsel-linux-android/include/c++/4.4.3" // CHECK-MIPSR2: "-internal-isystem" "{{.*}}/mipsel-linux-android/include/c++/4.4.3/mipsel-linux-android" // CHECK-MIPSR2: "-internal-externc-isystem" "{{.*}}/sysroot/include" @@ -78,13 +78,13 @@ // CHECK-MIPSR2: "-L{{.*}}/lib/gcc/mipsel-linux-android/4.4.3/../../../../mipsel-linux-android/lib" // CHECK-MIPSR2: "-L{{.*}}/sysroot/usr/lib" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target mipsel-linux-android \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=mipsel-linux-android \ // RUN: -mips32 -march=mips32r2 -stdlib=libstdc++ \ // RUN: --gcc-toolchain=%S/Inputs/basic_android_tree \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-MIPSR2-A %s -// CHECK-MIPSR2-A: {{.*}}clang{{.*}}" "-cc1" +// CHECK-MIPSR2-A: "-cc1" // CHECK-MIPSR2-A: "-internal-isystem" "{{.*}}/mipsel-linux-android/include/c++/4.4.3" // CHECK-MIPSR2-A: "-internal-isystem" "{{.*}}/mipsel-linux-android/include/c++/4.4.3/mipsel-linux-android" // CHECK-MIPSR2-A: "-internal-externc-isystem" "{{.*}}/sysroot/include" diff --git a/clang/test/Driver/arm-float-abi-lto.c b/clang/test/Driver/arm-float-abi-lto.c index 83c2435d97a4d..bde61ce16441b 100644 --- a/clang/test/Driver/arm-float-abi-lto.c +++ b/clang/test/Driver/arm-float-abi-lto.c @@ -1,10 +1,12 @@ +// FIXME: Produces a segmentation fault on AIX after the introduction of opaque pointers (D125847). +// UNSUPPORTED: system-aix // REQUIRES: arm-registered-target // RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -S -o - -emit-llvm -DCALL_LIB -DDEFINE_LIB | FileCheck %s -// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=full -c -o %t.call_full.bc -DCALL_LIB -// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=full -c -o %t.define_full.bc -DDEFINE_LIB -// RUN: llvm-lto2 run -o %t.lto_full -save-temps %t.call_full.bc %t.define_full.bc \ +// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -Xclang -opaque-pointers -flto=full -c -o %t.call_full.bc -DCALL_LIB +// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -Xclang -opaque-pointers -flto=full -c -o %t.define_full.bc -DDEFINE_LIB +// RUN: llvm-lto2 run -lto-opaque-pointers -o %t.lto_full -save-temps %t.call_full.bc %t.define_full.bc \ // RUN: -r %t.call_full.bc,fn,px \ // RUN: -r %t.call_full.bc,fwrite,l \ // RUN: -r %t.call_full.bc,putchar,l \ @@ -14,9 +16,9 @@ // RUN: -r %t.define_full.bc,otherfn,px // RUN: llvm-dis %t.lto_full.0.4.opt.bc -o - | FileCheck %s -// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=thin -c -o %t.call_thin.bc -DCALL_LIB -// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=thin -c -o %t.define_thin.bc -DDEFINE_LIB -// RUN: llvm-lto2 run -o %t.lto_thin -save-temps %t.call_thin.bc %t.define_thin.bc \ +// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -Xclang -opaque-pointers -flto=thin -c -o %t.call_thin.bc -DCALL_LIB +// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -Xclang -opaque-pointers -flto=thin -c -o %t.define_thin.bc -DDEFINE_LIB +// RUN: llvm-lto2 run -lto-opaque-pointers -o %t.lto_thin -save-temps %t.call_thin.bc %t.define_thin.bc \ // RUN: -r %t.call_thin.bc,fn,px \ // RUN: -r %t.call_thin.bc,fwrite,l \ // RUN: -r %t.call_thin.bc,putchar,l \ diff --git a/clang/test/Driver/avr-toolchain.c b/clang/test/Driver/avr-toolchain.c index 5bdd644638102..4232811cf19ff 100644 --- a/clang/test/Driver/avr-toolchain.c +++ b/clang/test/Driver/avr-toolchain.c @@ -53,8 +53,22 @@ // LINKA-NOT: warning: {{.*}} data section address // RUN: %clang -### --target=avr --sysroot=%S/Inputs/ -mmcu=atmega328 %s 2>&1 | FileCheck --check-prefixes=NOGCC %s -// NOGCC: warning: no avr-gcc installation can be found on the system, cannot link standard libraries // NOGCC: warning: standard library not linked and so no interrupt vector table or compiler runtime routines will be linked // NOGCC-NOT: warning: {{.*}} microcontroller // NOGCC-NOT: warning: {{.*}} avr-libc // NOGCC-NOT: warning: {{.*}} data section address + +// RUN: %clang -### --target=avr --sysroot=%S/Inputs/basic_avr_tree -mmcu=atmega328 %s -fuse-ld=avrld 2>&1 | FileCheck --check-prefix=NOLD %s +// NOLD: error: invalid linker + +// RUN: %clang -### --target=avr --sysroot=%S/Inputs/basic_avr_tree -mmcu=atmega328 %s -fuse-ld=%S/Inputs/basic_avr_tree/usr/bin/ld.lld 2>&1 | FileCheck --check-prefix=LLD %s +// LLD: {{".*lld"}} +// LLD-NOT: "avr-ld" +// LLD-NOT: "-mavr5" + +// RUN: %clang -### --target=avr --sysroot=%S/Inputs/basic_avr_tree -mmcu=atmega328 %s -T avr.lds 2>&1 | FileCheck --check-prefix=LDS0 %s +// LDS0: "-T" "avr.lds" "-mavr5" + +// RUN: %clang -### --target=avr --sysroot=%S/Inputs/basic_avr_tree -mmcu=atmega328 %s -fuse-ld=%S/Inputs/basic_avr_tree/usr/bin/ld.lld -T avr.lds 2>&1 | FileCheck --check-prefix=LDS1 %s +// LDS1: "-T" "avr.lds" +// LDS1-NOT: "-mavr5" diff --git a/clang/test/Driver/cc-print-options.c b/clang/test/Driver/cc-print-options.c index 5a1781008337f..58375fa7327cc 100644 --- a/clang/test/Driver/cc-print-options.c +++ b/clang/test/Driver/cc-print-options.c @@ -1,8 +1,14 @@ +// RUN: rm -f %t.log // RUN: env CC_PRINT_OPTIONS=1 \ // RUN: CC_PRINT_OPTIONS_FILE=%t.log \ // RUN: %clang -S -o %t.s %s // RUN: FileCheck %s < %t.log -// CHECK: [Logging clang options] -// CHECK: {{.*}} "-S" +// RUN: rm -f %t.log +// RUN: env CC_PRINT_OPTIONS=1 \ +// RUN: CC_PRINT_OPTIONS_FILE=%t.log \ +// RUN: %clang -fdriver-only -o %t.s %s +// RUN: FileCheck %s < %t.log +// CHECK: [Logging clang options] +// CHECK: {{.*}} "-cc1" diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c index 1e518e0035ae8..a2e350a0a8355 100644 --- a/clang/test/Driver/cl-options.c +++ b/clang/test/Driver/cl-options.c @@ -65,20 +65,29 @@ // RUN: %clang_cl -### /FA -fprofile-instr-generate -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-INSTR-GENERATE %s // RUN: %clang_cl -### /FA -fprofile-instr-generate=/tmp/somefile.profraw -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-INSTR-GENERATE-FILE %s +// RUN: %clang_cl -### /FAcsu -fprofile-instr-generate -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-INSTR-GENERATE %s +// RUN: %clang_cl -### /FAcsu -fprofile-instr-generate=/tmp/somefile.profraw -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-INSTR-GENERATE-FILE %s // CHECK-PROFILE-INSTR-GENERATE: "-fprofile-instrument=clang" "--dependent-lib=clang_rt.profile{{[^"]*}}.lib" // CHECK-PROFILE-INSTR-GENERATE-FILE: "-fprofile-instrument-path=/tmp/somefile.profraw" // RUN: %clang_cl -### /FA -fprofile-generate -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE %s +// RUN: %clang_cl -### /FAcsu -fprofile-generate -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE %s // CHECK-PROFILE-GENERATE: "-fprofile-instrument=llvm" "--dependent-lib=clang_rt.profile{{[^"]*}}.lib" // RUN: %clang_cl -### /FA -fprofile-instr-generate -fprofile-instr-use -- %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MIX-GEN-USE %s // RUN: %clang_cl -### /FA -fprofile-instr-generate -fprofile-instr-use=file -- %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MIX-GEN-USE %s +// RUN: %clang_cl -### /FAcsu -fprofile-instr-generate -fprofile-instr-use -- %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MIX-GEN-USE %s +// RUN: %clang_cl -### /FAcsu -fprofile-instr-generate -fprofile-instr-use=file -- %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MIX-GEN-USE %s // CHECK-NO-MIX-GEN-USE: '{{[a-z=-]*}}' not allowed with '{{[a-z=-]*}}' // RUN: %clang_cl -### /FA -fprofile-instr-use -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-USE %s // RUN: %clang_cl -### /FA -fprofile-use -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-USE %s // RUN: %clang_cl -### /FA -fprofile-instr-use=/tmp/somefile.prof -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-USE-FILE %s // RUN: %clang_cl -### /FA -fprofile-use=/tmp/somefile.prof -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-USE-FILE %s +// RUN: %clang_cl -### /FAcsu -fprofile-instr-use -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-USE %s +// RUN: %clang_cl -### /FAcsu -fprofile-use -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-USE %s +// RUN: %clang_cl -### /FAcsu -fprofile-instr-use=/tmp/somefile.prof -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-USE-FILE %s +// RUN: %clang_cl -### /FAcsu -fprofile-use=/tmp/somefile.prof -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-USE-FILE %s // CHECK-PROFILE-USE: "-fprofile-instrument-use-path=default.profdata" // CHECK-PROFILE-USE-FILE: "-fprofile-instrument-use-path=/tmp/somefile.prof" @@ -752,4 +761,12 @@ // RUN: %clang_cl /JMC /Z7 /c -### -- %s 2>&1 | FileCheck %s --check-prefix JMC // JMC: -fjmc +// RUN: %clang_cl /external:W0 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_W0 %s +// RUN: %clang_cl /external:W1 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_Wn %s +// RUN: %clang_cl /external:W2 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_Wn %s +// RUN: %clang_cl /external:W3 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_Wn %s +// RUN: %clang_cl /external:W4 /c -### -- %s 2>&1 | FileCheck -check-prefix=EXTERNAL_Wn %s +// EXTERNAL_W0: "-Wno-system-headers" +// EXTERNAL_Wn: "-Wsystem-headers" + void f(void) { } diff --git a/clang/test/Driver/cl-outputs.c b/clang/test/Driver/cl-outputs.c index 75ff77e15910b..abca67b12e55e 100644 --- a/clang/test/Driver/cl-outputs.c +++ b/clang/test/Driver/cl-outputs.c @@ -238,6 +238,28 @@ // FaMULTIPLESOURCEOK: "-o" "cl-outputs.asm" // FaMULTIPLESOURCEOK: "-o" "cl-outputs.asm" +// Copy of the same tests above, but with /FAcsu +// RUN: %clang_cl /FAcsu -### -- %s 2>&1 | FileCheck -check-prefix=FA_CSU %s +// FA_CSU: "-o" "cl-outputs.asm" +// RUN: %clang_cl /FAcsu /Fa -### -- %s 2>&1 | FileCheck -check-prefix=FA_CSU_FaEMPTY %s +// FA_CSU_FaEMPTY: "-o" "cl-outputs.asm" +// RUN: %clang_cl /FAcsu /Fafoo -### -- %s 2>&1 | FileCheck -check-prefix=FA_CSU_FaNAME %s +// RUN: %clang_cl /Fafoo -### -- %s 2>&1 | FileCheck -check-prefix=FA_CSU_FaNAME %s +// FA_CSU_FaNAME: "-o" "foo.asm" +// RUN: %clang_cl /FAcsu /Faa.ext /Fab.ext -### -- %s 2>&1 | FileCheck -check-prefix=FA_CSU_FaNAMEEXT %s +// FA_CSU_FaNAMEEXT: "-o" "b.ext" +// RUN: %clang_cl /FAcsu /Fafoo.dir/ -### -- %s 2>&1 | FileCheck -check-prefix=FA_CSU_FaDIR %s +// FA_CSU_FaDIR: "-o" "foo.dir{{[/\\]+}}cl-outputs.asm" +// RUN: %clang_cl /FAcsu /Fafoo.dir/a -### -- %s 2>&1 | FileCheck -check-prefix=FA_CSU_FaDIRNAME %s +// FA_CSU_FaDIRNAME: "-o" "foo.dir{{[/\\]+}}a.asm" +// RUN: %clang_cl /FAcsu /Fafoo.dir/a.ext -### -- %s 2>&1 | FileCheck -check-prefix=FA_CSU_FaDIRNAMEEXT %s +// FA_CSU_FaDIRNAMEEXT: "-o" "foo.dir{{[/\\]+}}a.ext" +// RUN: %clang_cl /Faa.asm -### -- %s %s 2>&1 | FileCheck -check-prefix=FA_CSU_FaMULTIPLESOURCE %s +// FA_CSU_FaMULTIPLESOURCE: error: cannot specify '/Faa.asm' when compiling multiple source files +// RUN: %clang_cl /Fa -### -- %s %s 2>&1 | FileCheck -check-prefix=FA_CSU_FaMULTIPLESOURCEOK %s +// FA_CSU_FaMULTIPLESOURCEOK: "-o" "cl-outputs.asm" +// FA_CSU_FaMULTIPLESOURCEOK: "-o" "cl-outputs.asm" + // RUN: %clang_cl /P -### -- %s 2>&1 | FileCheck -check-prefix=P %s // P: "-E" // P: "-o" "cl-outputs.i" diff --git a/clang/test/Driver/cl-zc.cpp b/clang/test/Driver/cl-zc.cpp index 077d22d2e3cd7..9aca2b7b1d2f9 100644 --- a/clang/test/Driver/cl-zc.cpp +++ b/clang/test/Driver/cl-zc.cpp @@ -24,6 +24,33 @@ // RUN: %clang_cl /c /std:c++17 -### /Zc:alignedNew- -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-OFF %s // ALIGNED-NEW-OFF-NOT: "-faligned-allocation" +// RUN: %clang_cl /c -### /kernel -- %s 2>&1 | FileCheck -check-prefixes=KERNEL-NO-RTTI,KERNEL-NO-EXCEPTIONS %s +// KERNEL-NO-RTTI: "-fno-rtti" +// KERNEL-NO-EXCEPTIONS-NOT: "-fcxx-exceptions" "-fexceptions" + +// RUN: %clang_cl /c -### --target=i686-pc-windows-msvc /kernel /arch:SSE -- %s 2>&1 | FileCheck -check-prefixes=KERNEL-SSE %s +// RUN: %clang_cl /c -### --target=i686-pc-windows-msvc /kernel /arch:SSE2 -- %s 2>&1 | FileCheck -check-prefixes=KERNEL-SSE2 %s +// RUN: %clang_cl /c -### --target=i686-pc-windows-msvc /kernel /arch:AVX -- %s 2>&1 | FileCheck -check-prefixes=KERNEL-AVX %s +// RUN: %clang_cl /c -### --target=i686-pc-windows-msvc /kernel /arch:AVX2 -- %s 2>&1 | FileCheck -check-prefixes=KERNEL-AVX2 %s +// RUN: %clang_cl /c -### --target=i686-pc-windows-msvc /kernel /arch:AVX512 -- %s 2>&1 | FileCheck -check-prefixes=KERNEL-AVX512 %s +// KERNEL-SSE: error: invalid argument '/arch:SSE' not allowed with '/kernel' +// KERNEL-SSE2: error: invalid argument '/arch:SSE2' not allowed with '/kernel' +// KERNEL-AVX: error: invalid argument '/arch:AVX' not allowed with '/kernel' +// KERNEL-AVX2: error: invalid argument '/arch:AVX2' not allowed with '/kernel' +// KERNEL-AVX512: error: invalid argument '/arch:AVX512' not allowed with '/kernel' + +// RUN: %clang_cl /c -### /kernel /EHsc -- %s 2>&1 | FileCheck -check-prefixes=KERNEL-EHSC %s +// RUN: %clang_cl /c -### /kernel /GR -- %s 2>&1 | FileCheck -check-prefixes=KERNEL-GR %s +// KERNEL-EHSC-NOT: "-fcxx-exceptions" "-fexceptions" +// KERNEL-GR: error: invalid argument '/GR' not allowed with '/kernel' + +// RUN: %clang_cl /c -### --target=x86_64-pc-windows-msvc /kernel /arch:AVX -- %s 2>&1 | FileCheck -check-prefixes=KERNEL-X64-AVX %s +// RUN: %clang_cl /c -### --target=x86_64-pc-windows-msvc /kernel /arch:AVX2 -- %s 2>&1 | FileCheck -check-prefixes=KERNEL-X64-AVX2 %s +// RUN: %clang_cl /c -### --target=x86_64-pc-windows-msvc /kernel /arch:AVX512 -- %s 2>&1 | FileCheck -check-prefixes=KERNEL-X64-AVX512 %s +// KERNEL-X64-AVX: error: invalid argument '/arch:AVX' not allowed with '/kernel' +// KERNEL-X64-AVX2: error: invalid argument '/arch:AVX2' not allowed with '/kernel' +// KERNEL-X64-AVX512: error: invalid argument '/arch:AVX512' not allowed with '/kernel' + // RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=STRICTSTRINGS-DEFAULT %s // STRICTSTRINGS-DEFAULT-NOT: -Werror=c++11-compat-deprecated-writable-strings // RUN: %clang_cl /c -### /Zc:strictStrings -- %s 2>&1 | FileCheck -check-prefix=STRICTSTRINGS-ON %s diff --git a/clang/test/Driver/clang-offload-wrapper.c b/clang/test/Driver/clang-offload-wrapper.c index 1c84072fef80a..edc26e59781d3 100644 --- a/clang/test/Driver/clang-offload-wrapper.c +++ b/clang/test/Driver/clang-offload-wrapper.c @@ -25,9 +25,9 @@ // ELF-WARNING: is not an ELF image, so notes cannot be added to it. // CHECK-IR: target triple = "x86_64-pc-linux-gnu" -// CHECK-IR-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i{{32|64}}, i32, i32 } -// CHECK-IR-DAG: [[IMAGETY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* } -// CHECK-IR-DAG: [[DESCTY:%.+]] = type { i32, [[IMAGETY]]*, [[ENTTY]]*, [[ENTTY]]* } +// CHECK-IR-DAG: [[ENTTY:%.+]] = type { ptr, ptr, i{{32|64}}, i32, i32 } +// CHECK-IR-DAG: [[IMAGETY:%.+]] = type { ptr, ptr, ptr, ptr } +// CHECK-IR-DAG: [[DESCTY:%.+]] = type { i32, ptr, ptr, ptr } // CHECK-IR: [[ENTBEGIN:@.+]] = external hidden constant [[ENTTY]] // CHECK-IR: [[ENTEND:@.+]] = external hidden constant [[ENTTY]] @@ -36,24 +36,24 @@ // CHECK-IR: [[BIN:@.+]] = internal unnamed_addr constant [[BINTY:\[[0-9]+ x i8\]]] c"Content of device file{{.+}}" -// CHECK-IR: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[IMAGETY]]] [{{.+}} { i8* getelementptr inbounds ([[BINTY]], [[BINTY]]* [[BIN]], i64 0, i64 0), i8* getelementptr inbounds ([[BINTY]], [[BINTY]]* [[BIN]], i64 1, i64 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }] +// CHECK-IR: [[IMAGES:@.+]] = internal unnamed_addr constant [1 x [[IMAGETY]]] [{{.+}} { ptr [[BIN]], ptr getelementptr inbounds ([[BINTY]], ptr [[BIN]], i64 1, i64 0), ptr [[ENTBEGIN]], ptr [[ENTEND]] }] -// CHECK-IR: [[DESC:@.+]] = internal constant [[DESCTY]] { i32 1, [[IMAGETY]]* getelementptr inbounds ([1 x [[IMAGETY]]], [1 x [[IMAGETY]]]* [[IMAGES]], i64 0, i64 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] } +// CHECK-IR: [[DESC:@.+]] = internal constant [[DESCTY]] { i32 1, ptr [[IMAGES]], ptr [[ENTBEGIN]], ptr [[ENTEND]] } -// CHECK-IR: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* [[REGFN:@.+]], i8* null }] -// CHECK-IR: @llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* [[UNREGFN:@.+]], i8* null }] +// CHECK-IR: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr [[REGFN:@.+]], ptr null }] +// CHECK-IR: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr [[UNREGFN:@.+]], ptr null }] // CHECK-IR: define internal void [[REGFN]]() -// CHECK-IR: call void @__tgt_register_lib([[DESCTY]]* [[DESC]]) +// CHECK-IR: call void @__tgt_register_lib(ptr [[DESC]]) // CHECK-IR: ret void -// CHECK-IR: declare void @__tgt_register_lib([[DESCTY]]*) +// CHECK-IR: declare void @__tgt_register_lib(ptr) // CHECK-IR: define internal void [[UNREGFN]]() -// CHECK-IR: call void @__tgt_unregister_lib([[DESCTY]]* [[DESC]]) +// CHECK-IR: call void @__tgt_unregister_lib(ptr [[DESC]]) // CHECK-IR: ret void -// CHECK-IR: declare void @__tgt_unregister_lib([[DESCTY]]*) +// CHECK-IR: declare void @__tgt_unregister_lib(ptr) // Check that clang-offload-wrapper adds LLVMOMPOFFLOAD notes // into the ELF offload images: diff --git a/clang/test/Driver/compilation_database.c b/clang/test/Driver/compilation_database.c index 19224d22de044..879c67c59c883 100644 --- a/clang/test/Driver/compilation_database.c +++ b/clang/test/Driver/compilation_database.c @@ -2,8 +2,8 @@ // RUN: %clang -no-canonical-prefixes -fintegrated-as -MD -MP --sysroot=somewhere -c -x c %s -xc++ %s -Wall -MJ - 2>&1 | FileCheck %s // RUN: not %clang -no-canonical-prefixes -c -x c %s -MJ %s/non-existant 2>&1 | FileCheck --check-prefix=ERROR %s -// CHECK: { "directory": "{{[^"]*}}workdir", "file": "[[SRC:[^"]+[/|\\]compilation_database.c]]", "output": "compilation_database.o", "arguments": ["{{[^"]*}}clang{{[^"]*}}", "-xc", "[[SRC]]", "-no-canonical-prefixes", "-fintegrated-as", "--sysroot=somewhere", "-c", "-Wall",{{.*}} "--target={{[^"]+}}"]}, -// CHECK: { "directory": "{{.*}}", "file": "[[SRC:[^"]+[/|\\]compilation_database.c]]", "output": "compilation_database.o", "arguments": ["{{[^"]*}}clang{{[^"]*}}", "-xc++", "[[SRC]]", "-no-canonical-prefixes", "-fintegrated-as", "--sysroot=somewhere", "-c", "-Wall",{{.*}} "--target={{[^"]+}}"]}, +// CHECK: { "directory": "{{[^"]*}}workdir", "file": "[[SRC:[^"]+[/|\\]compilation_database.c]]", "output": "compilation_database.o", "arguments": ["{{[^"]*}}clang{{[^"]*}}", "-xc", "[[SRC]]", "-o", "compilation_database.o", "-no-canonical-prefixes", "-fintegrated-as", "--sysroot=somewhere", "-c", "-Wall",{{.*}} "--target={{[^"]+}}"]}, +// CHECK: { "directory": "{{.*}}", "file": "[[SRC:[^"]+[/|\\]compilation_database.c]]", "output": "compilation_database.o", "arguments": ["{{[^"]*}}clang{{[^"]*}}", "-xc++", "[[SRC]]", "-o", "compilation_database.o", "-no-canonical-prefixes", "-fintegrated-as", "--sysroot=somewhere", "-c", "-Wall",{{.*}} "--target={{[^"]+}}"]}, // ERROR: error: compilation database '{{.*}}/non-existant' could not be opened: int main(void) { diff --git a/clang/test/Driver/compilation_database_multiarch.c b/clang/test/Driver/compilation_database_multiarch.c new file mode 100644 index 0000000000000..86401503aa17c --- /dev/null +++ b/clang/test/Driver/compilation_database_multiarch.c @@ -0,0 +1,8 @@ +// REQUIRES: system-darwin + +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang -fdriver-only -o %t/out %s -mtargetos=macos12 -arch arm64 -arch x86_64 -MJ %t/compilation_database.json +// RUN: FileCheck --input-file=%t/compilation_database.json %s + +// CHECK: { "directory": "{{.*}}", "file": "{{.*}}", "output": "[[OUTPUT_X86_64:.*]]", "arguments": [{{.*}}, "-o", "[[OUTPUT_X86_64]]", {{.*}} "--target=x86_64-apple-macosx12.0.0"]}, +// CHECK-NEXT: { "directory": "{{.*}}", "file": "{{.*}}", "output": "[[OUTPUT_ARM64:.*]]", "arguments": [{{.*}}, "-o", "[[OUTPUT_ARM64]]", {{.*}} "--target=arm64-apple-macosx12.0.0"]}, diff --git a/clang/test/Driver/crash-report-crashfile.m b/clang/test/Driver/crash-report-crashfile.m index fd26246073faa..dd55b0dbb77e0 100644 --- a/clang/test/Driver/crash-report-crashfile.m +++ b/clang/test/Driver/crash-report-crashfile.m @@ -17,8 +17,8 @@ @import simple; const int x = MODULE_MACRO; -// CRASH_ENV: failing because environment variable 'FORCE_CLANG_DIAGNOSTICS_CRASH' is set // CRASH_ENV: PLEASE submit a bug report to {{.*}} and include the crash backtrace, preprocessed source, and associated run script. +// CRASH_ENV: failing because environment variable 'FORCE_CLANG_DIAGNOSTICS_CRASH' is set // CRASH_ENV: Preprocessed source(s) and associated run script(s) are located at: // CRASH_ENV-NEXT: note: diagnostic msg: {{.*}}.m // CRASH_ENV-NEXT: note: diagnostic msg: {{.*}}.cache diff --git a/clang/test/Driver/cuda-march.cu b/clang/test/Driver/cuda-march.cu index 449eb12384651..a7abbfe452701 100644 --- a/clang/test/Driver/cuda-march.cu +++ b/clang/test/Driver/cuda-march.cu @@ -5,17 +5,15 @@ // REQUIRES: x86-registered-target // REQUIRES: nvptx-registered-target -// RUN: %clang -no-canonical-prefixes -### -target x86_64-linux-gnu -c \ +// RUN: %clang -### --target=x86_64-linux-gnu -c \ // RUN: -march=haswell %s 2>&1 | FileCheck %s -// RUN: %clang -no-canonical-prefixes -### -target x86_64-linux-gnu -c \ +// RUN: %clang -### --target=x86_64-linux-gnu -c \ // RUN: -march=haswell --cuda-gpu-arch=sm_35 %s 2>&1 | FileCheck %s -// CHECK: {{.*}}clang{{.*}}" "-cc1" -// CHECK-SAME: "-triple" "nvptx +// CHECK: "-cc1"{{.*}} "-triple" "nvptx // CHECK-SAME: "-target-cpu" "sm_35" // CHECK: ptxas // CHECK-SAME: "--gpu-name" "sm_35" -// CHECK: {{.*}}clang{{.*}}" "-cc1" -// CHECK-SAME: "-target-cpu" "haswell" +// CHECK: "-cc1"{{.*}} "-target-cpu" "haswell" diff --git a/clang/test/Driver/cuda-unused-arg-warning.cu b/clang/test/Driver/cuda-unused-arg-warning.cu deleted file mode 100644 index 4e541c66def89..0000000000000 --- a/clang/test/Driver/cuda-unused-arg-warning.cu +++ /dev/null @@ -1,28 +0,0 @@ -// Tests that we trigger unused-arg warnings on CUDA flags appropriately. - -// REQUIRES: x86-registered-target -// REQUIRES: nvptx-registered-target - -// --cuda-host-only and --cuda-compile-host-device should never trigger an -// unused arg warning. -// RUN: %clang -### -target x86_64-linux-gnu --cuda-host-only -c %s 2>&1 | \ -// RUN: FileCheck %s -// RUN: %clang -### -target x86_64-linux-gnu --cuda-host-only -x c -c %s 2>&1 | \ -// RUN: FileCheck %s -// RUN: %clang -### -target x86_64-linux-gnu --cuda-compile-host-device -c %s 2>&1 | \ -// RUN: FileCheck %s -// RUN: %clang -### -target x86_64-linux-gnu --cuda-compile-host-device -x c -c %s 2>&1 | \ -// RUN: FileCheck %s - -// --cuda-device-only should warn during non-CUDA compilation. -// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only -x c -c %s 2>&1 | \ -// RUN: FileCheck -check-prefix UNUSED-WARNING %s - -// --cuda-device-only should not produce warning compiling CUDA files -// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only -c %s 2>&1 | \ -// RUN: FileCheck -check-prefix NO-UNUSED-WARNING %s - -// CHECK-NOT: warning: argument unused during compilation: '--cuda-host-only' -// CHECK-NOT: warning: argument unused during compilation: '--cuda-compile-host-device' -// UNUSED-WARNING: warning: argument unused during compilation: '--cuda-device-only' -// NO-UNUSED-WARNING-NOT: warning: argument unused during compilation: '--cuda-device-only' diff --git a/clang/test/Driver/darwin-header-search-libcxx.cpp b/clang/test/Driver/darwin-header-search-libcxx.cpp index 4824525f1cf41..f1b6f39d84838 100644 --- a/clang/test/Driver/darwin-header-search-libcxx.cpp +++ b/clang/test/Driver/darwin-header-search-libcxx.cpp @@ -6,49 +6,49 @@ // Check without a sysroot and without headers alongside the installation // (no include path should be added, and no warning or error). // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: | FileCheck --check-prefix=CHECK-LIBCXX-NONE %s -// CHECK-LIBCXX-NONE: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-LIBCXX-NONE: "-cc1" // Check with only headers alongside the installation (those should be used). // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain/usr/bin \ // RUN: --sysroot="" \ // RUN: | FileCheck -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \ // RUN: --check-prefix=CHECK-LIBCXX-TOOLCHAIN-1 %s -// CHECK-LIBCXX-TOOLCHAIN-1: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-LIBCXX-TOOLCHAIN-1: "-cc1" // CHECK-LIBCXX-TOOLCHAIN-1: "-internal-isystem" "[[TOOLCHAIN]]/usr/bin/../include/c++/v1" // CHECK-LIBCXX-TOOLCHAIN-1-NOT: "-internal-isystem" "/usr/include/c++/v1" // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain/usr/bin \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_no_libcxx \ // RUN: | FileCheck -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \ // RUN: -DSYSROOT=%S/Inputs/basic_darwin_sdk_no_libcxx \ // RUN: --check-prefix=CHECK-LIBCXX-TOOLCHAIN-2 %s -// CHECK-LIBCXX-TOOLCHAIN-2: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-LIBCXX-TOOLCHAIN-2: "-cc1" // CHECK-LIBCXX-TOOLCHAIN-2: "-internal-isystem" "[[TOOLCHAIN]]/usr/bin/../include/c++/v1" // CHECK-LIBCXX-TOOLCHAIN-2-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1" // Check with only headers in the sysroot (those should be used). // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_cxx_v1 \ // RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_cxx_v1 \ // RUN: -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain_no_libcxx \ // RUN: --check-prefix=CHECK-LIBCXX-SYSROOT-1 %s -// CHECK-LIBCXX-SYSROOT-1: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-LIBCXX-SYSROOT-1: "-cc1" // CHECK-LIBCXX-SYSROOT-1: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1" // CHECK-LIBCXX-SYSROOT-1-NOT: "-internal-isystem" "[[TOOLCHAIN]]/usr/bin/../include/c++/v1" @@ -57,8 +57,8 @@ // Ensure that both -isysroot and --sysroot work, and that isysroot has precedence // over --sysroot. // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ @@ -67,8 +67,8 @@ // RUN: -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \ // RUN: --check-prefix=CHECK-LIBCXX-SYSROOT_AND_TOOLCHAIN-1 %s // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ @@ -77,8 +77,8 @@ // RUN: -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \ // RUN: --check-prefix=CHECK-LIBCXX-SYSROOT_AND_TOOLCHAIN-1 %s // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ @@ -88,15 +88,15 @@ // RUN: -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \ // RUN: --check-prefix=CHECK-LIBCXX-SYSROOT_AND_TOOLCHAIN-1 %s // -// CHECK-LIBCXX-SYSROOT_AND_TOOLCHAIN-1: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-LIBCXX-SYSROOT_AND_TOOLCHAIN-1: "-cc1" // CHECK-LIBCXX-SYSROOT_AND_TOOLCHAIN-1: "-internal-isystem" "[[TOOLCHAIN]]/usr/bin/../include/c++/v1" // CHECK-LIBCXX-SYSROOT_AND_TOOLCHAIN-1-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1" // Make sure that using -nostdinc does not drop any C++ library include path. // This behavior is strange, but it is compatible with the legacy CC1 behavior. // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin16 \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin16 \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_cxx_v1 \ @@ -105,12 +105,12 @@ // RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_cxx_v1 \ // RUN: -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \ // RUN: --check-prefix=CHECK-LIBCXX-NOSTDINC-1 %s -// CHECK-LIBCXX-NOSTDINC-1: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-LIBCXX-NOSTDINC-1: "-cc1" // CHECK-LIBCXX-NOSTDINC-1-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1" // CHECK-LIBCXX-NOSTDINC-1: "-internal-isystem" "[[TOOLCHAIN]]/usr/bin/../include/c++/v1" // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin16 \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin16 \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_no_libcxx \ @@ -119,15 +119,15 @@ // RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_no_libcxx \ // RUN: -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \ // RUN: --check-prefix=CHECK-LIBCXX-NOSTDINC-2 %s -// CHECK-LIBCXX-NOSTDINC-2: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-LIBCXX-NOSTDINC-2: "-cc1" // CHECK-LIBCXX-NOSTDINC-2: "-internal-isystem" "[[TOOLCHAIN]]/usr/bin/../include/c++/v1" // CHECK-LIBCXX-NOSTDINC-2-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1" // Make sure that using -nostdinc++ or -nostdlib will drop both the toolchain // C++ include path and the sysroot one. // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin16 \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin16 \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_cxx_v1 \ @@ -136,12 +136,12 @@ // RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr \ // RUN: -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \ // RUN: --check-prefix=CHECK-LIBCXX-NOSTDINCXX %s -// CHECK-LIBCXX-NOSTDINCXX: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-LIBCXX-NOSTDINCXX: "-cc1" // CHECK-LIBCXX-NOSTDINCXX-NOT: "-internal-isystem" "[[TOOLCHAIN]]/usr/bin/../include/c++/v1" // CHECK-LIBCXX-NOSTDINCXX-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1" // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin16 \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin16 \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr \ @@ -150,15 +150,15 @@ // RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr \ // RUN: -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \ // RUN: --check-prefix=CHECK-LIBCXX-NOSTDLIBINC %s -// CHECK-LIBCXX-NOSTDLIBINC: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-LIBCXX-NOSTDLIBINC: "-cc1" // CHECK-LIBCXX-NOSTDLIBINC-NOT: "-internal-isystem" "[[TOOLCHAIN]]/usr/bin/../include/c++/v1" // CHECK-LIBCXX-NOSTDLIBINC-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1" // Make sure we explain that we considered a path but didn't add it when it // doesn't exist. // -// RUN: %clang -no-canonical-prefixes %s -fsyntax-only -v 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang %s -fsyntax-only -v 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk \ // RUN: -stdlib=libc++ \ @@ -166,8 +166,8 @@ // RUN: --check-prefix=CHECK-LIBCXX-MISSING-TOOLCHAIN %s // CHECK-LIBCXX-MISSING-TOOLCHAIN: ignoring nonexistent directory "[[TOOLCHAIN]]/usr/bin/../include/c++/v1" // -// RUN: %clang -no-canonical-prefixes %s -fsyntax-only -v 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang %s -fsyntax-only -v 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_no_libcxx \ // RUN: -stdlib=libc++ \ diff --git a/clang/test/Driver/darwin-header-search-system.cpp b/clang/test/Driver/darwin-header-search-system.cpp index 272d778c2a246..590535fae354d 100644 --- a/clang/test/Driver/darwin-header-search-system.cpp +++ b/clang/test/Driver/darwin-header-search-system.cpp @@ -6,8 +6,8 @@ // Check system headers (everything below and ). Ensure // that both sysroot and isysroot are checked, and that isysroot has precedence. // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_and_usr_local \ @@ -15,8 +15,8 @@ // RUN: -DRESOURCE=%S/Inputs/resource_dir \ // RUN: --check-prefix=CHECK-SYSTEM %s // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot %S/Inputs/basic_darwin_sdk_usr_and_usr_local \ @@ -24,8 +24,8 @@ // RUN: -DRESOURCE=%S/Inputs/resource_dir \ // RUN: --check-prefix=CHECK-SYSTEM %s // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_and_usr_local \ @@ -34,15 +34,15 @@ // RUN: -DRESOURCE=%S/Inputs/resource_dir \ // RUN: --check-prefix=CHECK-SYSTEM %s // -// CHECK-SYSTEM: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-SYSTEM: "-cc1" // CHECK-SYSTEM: "-internal-isystem" "[[SYSROOT]]/usr/local/include" // CHECK-SYSTEM: "-internal-isystem" "[[RESOURCE]]/include" // CHECK-SYSTEM: "-internal-externc-isystem" "[[SYSROOT]]/usr/include" // Make sure that using -nobuiltininc will drop resource headers // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_and_usr_local \ @@ -50,7 +50,7 @@ // RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_and_usr_local \ // RUN: -DRESOURCE=%S/Inputs/resource_dir \ // RUN: --check-prefix=CHECK-NOBUILTININC %s -// CHECK-NOBUILTININC: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-NOBUILTININC: "-cc1" // CHECK-NOBUILTININC: "-internal-isystem" "[[SYSROOT]]/usr/local/include" // CHECK-NOBUILTININC-NOT: "-internal-isystem" "[[RESOURCE]]/include" // CHECK-NOBUILTININC: "-internal-externc-isystem" "[[SYSROOT]]/usr/include" @@ -58,8 +58,8 @@ // Make sure that using -nostdlibinc will drop /usr/local/include and // /usr/include. // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_and_usr_local \ @@ -67,7 +67,7 @@ // RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_and_usr_local \ // RUN: -DRESOURCE=%S/Inputs/resource_dir \ // RUN: --check-prefix=CHECK-NOSTDLIBINC %s -// CHECK-NOSTDLIBINC: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-NOSTDLIBINC: "-cc1" // CHECK-NOSTDLIBINC-NOT: "-internal-isystem" "[[SYSROOT]]/usr/local/include" // CHECK-NOSTDLIBINC: "-internal-isystem" "[[RESOURCE]]/include" // CHECK-NOSTDLIBINC-NOT: "-internal-externc-isystem" "[[SYSROOT]]/usr/include" @@ -75,8 +75,8 @@ // Make sure that -nostdinc drops all the system include paths, including // /include. // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_and_usr_local \ @@ -84,27 +84,27 @@ // RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_and_usr_local \ // RUN: -DRESOURCE=%S/Inputs/resource_dir \ // RUN: --check-prefix=CHECK-NOSTDINC %s -// CHECK-NOSTDINC: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-NOSTDINC: "-cc1" // CHECK-NOSTDINC-NOT: "-internal-isystem" "[[SYSROOT]]/usr/local/include" // CHECK-NOSTDINC-NOT: "-internal-isystem" "[[RESOURCE]]/include" // CHECK-NOSTDINC-NOT: "-internal-externc-isystem" "[[SYSROOT]]/usr/include" // Check search paths without -isysroot // -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot="" \ // RUN: | FileCheck -DRESOURCE=%S/Inputs/resource_dir \ // RUN: --check-prefix=CHECK-NOSYSROOT %s -// CHECK-NOSYSROOT: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-NOSYSROOT: "-cc1" // CHECK-NOSYSROOT: "-internal-isystem" "/usr/local/include" // CHECK-NOSYSROOT: "-internal-isystem" "[[RESOURCE]]/include" // CHECK-NOSYSROOT: "-internal-externc-isystem" "/usr/include" -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_and_usr_local \ @@ -112,8 +112,8 @@ // RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_and_usr_local \ // RUN: -DRESOURCE=%S/Inputs/resource_dir \ // RUN: --check-prefix=CHECK-NOSTDINC-BUILTINC %s -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_and_usr_local \ @@ -121,8 +121,8 @@ // RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_and_usr_local \ // RUN: -DRESOURCE=%S/Inputs/resource_dir \ // RUN: --check-prefix=CHECK-NOSTDINC-BUILTINC %s -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_and_usr_local \ @@ -130,13 +130,13 @@ // RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_and_usr_local \ // RUN: -DRESOURCE=%S/Inputs/resource_dir \ // RUN: --check-prefix=CHECK-NOSTDINC-BUILTINC %s -// CHECK-NOSTDINC-BUILTINC: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-NOSTDINC-BUILTINC: "-cc1" // CHECK-NOSTDINC-BUILTINC-NOT: "-internal-isystem" "[[SYSROOT]]/usr/local/include" // CHECK-NOSTDINC-BUILTINC: "-internal-isystem" "[[RESOURCE]]/include" // CHECK-NOSTDINC-BUILTINC-NOT: "-internal-externc-isystem" "[[SYSROOT]]/usr/include" -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_and_usr_local \ @@ -144,13 +144,13 @@ // RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_and_usr_local \ // RUN: -DRESOURCE=%S/Inputs/resource_dir \ // RUN: --check-prefix=CHECK-NOBUILTININC-BUILTINC %s -// CHECK-NOBUILTININC-BUILTINC: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-NOBUILTININC-BUILTINC: "-cc1" // CHECK-NOBUILTININC-BUILTINC: "-internal-isystem" "[[SYSROOT]]/usr/local/include" // CHECK-NOBUILTININC-BUILTINC: "-internal-isystem" "[[RESOURCE]]/include" // CHECK-NOBUILTININC-BUILTINC: "-internal-externc-isystem" "[[SYSROOT]]/usr/include" -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_and_usr_local \ @@ -158,13 +158,13 @@ // RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_and_usr_local \ // RUN: -DRESOURCE=%S/Inputs/resource_dir \ // RUN: --check-prefix=CHECK-NOSTDINC-NO-BUILTINC %s -// CHECK-NOSTDINC-NO-BUILTINC: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-NOSTDINC-NO-BUILTINC: "-cc1" // CHECK-NOSTDINC-NO-BUILTINC-NOT: "-internal-isystem" "[[SYSROOT]]/usr/local/include" // CHECK-NOSTDINC-NO-BUILTINC-NOT: "-internal-isystem" "[[RESOURCE]]/include" // CHECK-NOSTDINC-NO-BUILTINC-NOT: "-internal-externc-isystem" "[[SYSROOT]]/usr/include" -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ -// RUN: -target x86_64-apple-darwin \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ // RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_and_usr_local \ @@ -172,7 +172,7 @@ // RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_and_usr_local \ // RUN: -DRESOURCE=%S/Inputs/resource_dir \ // RUN: --check-prefix=CHECK-BUILTINC-NOBUILTININC %s -// CHECK-BUILTINC-NOBUILTININC: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-BUILTINC-NOBUILTININC: "-cc1" // CHECK-BUILTINC-NOBUILTININC: "-internal-isystem" "[[SYSROOT]]/usr/local/include" // CHECK-BUILTINC-NOBUILTININC-NOT: "-internal-isystem" "[[RESOURCE]]/include" // CHECK-BUILTINC-NOBUILTININC: "-internal-externc-isystem" "[[SYSROOT]]/usr/include" diff --git a/clang/test/Driver/driver-only.c b/clang/test/Driver/driver-only.c new file mode 100644 index 0000000000000..067f174a3cf45 --- /dev/null +++ b/clang/test/Driver/driver-only.c @@ -0,0 +1,19 @@ +// RUN: rm -rf %t +// RUN: mkdir %t + +// Check that -fdriver-only doesn't actually run the generated -cc1 job. +// +// RUN: %clang -c %s -o %t/a.o -fdriver-only +// RUN: not cat %t/a.o + +// Check that -fdriver-only respects errors. +// +// RUN: not %clang -c %s -fdriver-only -target i386-apple-darwin9 -m32 -Xarch_i386 -o + +// Check that -fdriver-only respects -v. +// +// RUN: %clang -c %s -fdriver-only -v 2>&1 | FileCheck %s --check-prefix=CHECK-V +// CHECK-V: {{.*}} "-cc1" +// +// RUN: %clang -c %s -fdriver-only 2>&1 | FileCheck %s --check-prefix=CHECK-NO-V --allow-empty +// CHECK-NO-V-NOT: {{.*}} "-cc1" diff --git a/clang/test/Driver/dxc_D.hlsl b/clang/test/Driver/dxc_D.hlsl new file mode 100644 index 0000000000000..d32d885f11b00 --- /dev/null +++ b/clang/test/Driver/dxc_D.hlsl @@ -0,0 +1,13 @@ +// RUN: %clang_dxc -DTEST=2 -### %s 2>&1 | FileCheck %s +// RUN: %clang_dxc -DTEST=2 -Tlib_6_7 %s -fcgl -Fo - | FileCheck %s --check-prefix=ERROR + +// Make sure -D send to cc1. +// CHECK:"-D" "TEST=2" + +#ifndef TEST +#error "TEST not defined" +#elif TEST != 2 +#error "TEST defined to wrong value" +#endif + +// ERROR-NOT: error: diff --git a/clang/test/Driver/dxc_fcgl.hlsl b/clang/test/Driver/dxc_fcgl.hlsl index d3eb2523199ca..782dfaa1e0e55 100644 --- a/clang/test/Driver/dxc_fcgl.hlsl +++ b/clang/test/Driver/dxc_fcgl.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_dxc -fcgl foo.hlsl -### %s 2>&1 | FileCheck %s +// RUN: %clang_dxc -fcgl -T lib_6_7 foo.hlsl -### %s 2>&1 | FileCheck %s // Make sure fcgl option flag which translated into "-S" "-emit-llvm" "-disable-llvm-passes". // CHECK:"-S" "-emit-llvm" "-disable-llvm-passes" diff --git a/clang/test/Driver/emit-reproducer.c b/clang/test/Driver/emit-reproducer.c new file mode 100644 index 0000000000000..b8d6841077c4d --- /dev/null +++ b/clang/test/Driver/emit-reproducer.c @@ -0,0 +1,41 @@ +// RUN: rm -rf %t && mkdir %t + +// RUN: echo "%s -fcrash-diagnostics-dir=%t -fsyntax-only" | sed -e 's/\\/\\\\/g' > %t.rsp + +// RUN: not %clang -DFATAL @%t.rsp -gen-reproducer=off 2>&1 | FileCheck %s --check-prefix=NOT +// RUN: not %clang -DFATAL @%t.rsp -fno-crash-diagnostics 2>&1 | FileCheck %s --check-prefix=NOT +// RUN: not %clang -DFATAL @%t.rsp 2>&1 | FileCheck %s +// RUN: not %clang -DFATAL @%t.rsp -gen-reproducer=crash 2>&1 | FileCheck %s +// RUN: not %clang -DFATAL @%t.rsp -gen-reproducer=error 2>&1 | FileCheck %s +// RUN: not %clang -DFATAL @%t.rsp -gen-reproducer=always 2>&1 | FileCheck %s +// RUN: not %clang -DFATAL @%t.rsp -gen-reproducer 2>&1 | FileCheck %s + +// RUN: not %clang -DERROR @%t.rsp -gen-reproducer=off 2>&1 | FileCheck %s --check-prefix=NOT +// RUN: not %clang -DERROR @%t.rsp -fno-crash-diagnostics 2>&1 | FileCheck %s --check-prefix=NOT +// RUN: not %clang -DERROR @%t.rsp 2>&1 | FileCheck %s --check-prefix=NOT +// RUN: not %clang -DERROR @%t.rsp -gen-reproducer=crash 2>&1 | FileCheck %s --check-prefix=NOT +// RUN: not %clang -DERROR @%t.rsp -gen-reproducer=error 2>&1 | FileCheck %s +// RUN: not %clang -DERROR @%t.rsp -gen-reproducer=always 2>&1 | FileCheck %s +// RUN: not %clang -DERROR @%t.rsp -gen-reproducer 2>&1 | FileCheck %s + +// RUN: %clang @%t.rsp -gen-reproducer=off 2>&1 | FileCheck %s --check-prefix=NOT --allow-empty +// RUN: %clang @%t.rsp -fno-crash-diagnostics 2>&1 | FileCheck %s --check-prefix=NOT --allow-empty +// RUN: %clang @%t.rsp 2>&1 | FileCheck %s --check-prefix=NOT --allow-empty +// RUN: %clang @%t.rsp -gen-reproducer=crash 2>&1 | FileCheck %s --check-prefix=NOT --allow-empty +// RUN: %clang @%t.rsp -gen-reproducer=error 2>&1 | FileCheck %s --check-prefix=NOT --allow-empty +// RUN: not %clang @%t.rsp -gen-reproducer=always 2>&1 | FileCheck %s +// RUN: not %clang @%t.rsp -gen-reproducer 2>&1 | FileCheck %s + +// RUN: not %clang -gen-reproducer=badvalue 2>&1 | FileCheck %s --check-prefix=BAD-VALUE +// BAD-VALUE: Unknown value for -gen-reproducer=: 'badvalue' + +// CHECK: note: diagnostic msg: {{.*}}emit-reproducer-{{.*}}.c +// NOT-NOT: note: diagnostic msg: {{.*}}emit-reproducer-{{.*}}.c + +#ifdef FATAL +#pragma clang __debug crash +#elif ERROR +int main +#else +int main() {} +#endif diff --git a/clang/test/Driver/femit-dwarf-unwind.c b/clang/test/Driver/femit-dwarf-unwind.c new file mode 100644 index 0000000000000..6057c5e0e5348 --- /dev/null +++ b/clang/test/Driver/femit-dwarf-unwind.c @@ -0,0 +1,14 @@ +// REQUIRES: x86-registered-target + +// RUN: rm -rf %t; mkdir %t +// RUN: %clang -target x86_64-apple-macos11.0 -c %s -o %t/x86_64.o +// RUN: %clang -target x86_64-apple-macos11.0 -femit-dwarf-unwind=no-compact-unwind -c %s -o %t/x86_64-no-dwarf.o +// RUN: llvm-objdump --macho --dwarf=frames %t/x86_64.o | FileCheck %s --check-prefix=WITH-FDE +// RUN: llvm-objdump --macho --dwarf=frames %t/x86_64-no-dwarf.o | FileCheck %s --check-prefix=NO-FDE + +// WITH-FDE: FDE +// NO-FDE-NOT: FDE + +int foo() { + return 1; +} diff --git a/clang/test/Driver/femit-dwarf-unwind.s b/clang/test/Driver/femit-dwarf-unwind.s new file mode 100644 index 0000000000000..f2aa821b0cd5a --- /dev/null +++ b/clang/test/Driver/femit-dwarf-unwind.s @@ -0,0 +1,17 @@ +// REQUIRES: x86-registered-target + +// RUN: rm -rf %t; mkdir %t +// RUN: %clang -target x86_64-apple-macos11.0 -c %s -o %t/x86_64.o +// RUN: %clang -target x86_64-apple-macos11.0 -femit-dwarf-unwind=no-compact-unwind -c %s -o %t/x86_64-no-dwarf.o +// RUN: llvm-objdump --macho --dwarf=frames %t/x86_64.o | FileCheck %s --check-prefix=WITH-FDE +// RUN: llvm-objdump --macho --dwarf=frames %t/x86_64-no-dwarf.o | FileCheck %s --check-prefix=NO-FDE + +// WITH-FDE: FDE +// NO-FDE-NOT: FDE + +.text +_foo: + .cfi_startproc + .cfi_def_cfa_offset 8 + ret + .cfi_endproc diff --git a/clang/test/Driver/fsanitize-ignorelist.c b/clang/test/Driver/fsanitize-ignorelist.c index 17c4f5abcedc0..22e8e724be756 100644 --- a/clang/test/Driver/fsanitize-ignorelist.c +++ b/clang/test/Driver/fsanitize-ignorelist.c @@ -64,7 +64,7 @@ // If cfi_ignorelist.txt cannot be found in the resource dir, driver should fail. // RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -flto -fvisibility=default -resource-dir=/dev/null %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MISSING-CFI-IGNORELIST -// CHECK-MISSING-CFI-IGNORELIST: error: no such file or directory: '{{.*}}cfi_ignorelist.txt' +// CHECK-MISSING-CFI-IGNORELIST: error: missing sanitizer ignorelist: '{{.*}}cfi_ignorelist.txt' // -fno-sanitize-ignorelist disables checking for cfi_ignorelist.txt in the resource dir. // RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -flto -fvisibility=default -fno-sanitize-ignorelist -resource-dir=/dev/null %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MISSING-CFI-NO-IGNORELIST diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 75587f8ddc5f0..1d97e99058b9e 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -193,9 +193,9 @@ // RUN: %clang -target x86_64-linux-android -fsanitize=memtag -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANMT-BAD-ARCH // CHECK-SANMT-BAD-ARCH: unsupported option '-fsanitize=memtag' for target -// RUN: %clang -target aarch64-linux -fsanitize=memtag -march=armv8-a+memtag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANMT-MT +// RUN: %clang -target aarch64-linux-android31 -fsanitize=memtag -march=armv8-a+memtag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANMT-MT // CHECK-SANMT-MT: "-target-feature" "+mte" -// CHECK-SANMT-MT-SAME: "-fsanitize=memtag-stack,memtag-heap" +// CHECK-SANMT-MT-SAME: "-fsanitize=memtag-stack,memtag-heap,memtag-globals" // RUN: %clang -target aarch64-linux -fsanitize=memtag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANMT-NOMT-0 // CHECK-SANMT-NOMT-0: '-fsanitize=memtag-stack' requires hardware support (+memtag) @@ -827,7 +827,7 @@ // CHECK-INTSAN-MINIMAL: "-fsanitize-minimal-runtime" // RUN: %clang -target aarch64-linux-android -march=armv8-a+memtag -fsanitize=memtag -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MEMTAG-MINIMAL -// CHECK-MEMTAG-MINIMAL: "-fsanitize=memtag-stack,memtag-heap" +// CHECK-MEMTAG-MINIMAL: "-fsanitize=memtag-stack,memtag-heap,memtag-globals" // CHECK-MEMTAG-MINIMAL: "-fsanitize-minimal-runtime" // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize=function -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-FUNCTION-MINIMAL diff --git a/clang/test/Driver/fuchsia.c b/clang/test/Driver/fuchsia.c index 024c029e0e0cb..996f5862bbd47 100644 --- a/clang/test/Driver/fuchsia.c +++ b/clang/test/Driver/fuchsia.c @@ -1,28 +1,28 @@ -// RUN: %clang %s -### -no-canonical-prefixes --target=x86_64-unknown-fuchsia \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-X86_64 %s -// RUN: %clang %s -### -no-canonical-prefixes --target=aarch64-unknown-fuchsia \ +// RUN: %clang -### %s --target=aarch64-unknown-fuchsia \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-AARCH64 %s -// RUN: %clang %s -### -no-canonical-prefixes --target=riscv64-unknown-fuchsia \ +// RUN: %clang -### %s --target=riscv64-unknown-fuchsia \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-RISCV64 %s -// RUN: %clang %s -### -no-canonical-prefixes --target=x86_64-fuchsia \ +// RUN: %clang -### %s --target=x86_64-fuchsia \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-X86_64 %s -// RUN: %clang %s -### -no-canonical-prefixes --target=aarch64-fuchsia \ +// RUN: %clang -### %s --target=aarch64-fuchsia \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-AARCH64 %s -// RUN: %clang %s -### -no-canonical-prefixes --target=riscv64-fuchsia \ +// RUN: %clang -### %s --target=riscv64-fuchsia \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-RISCV64 %s -// CHECK: {{.*}}clang{{.*}}" "-cc1" +// CHECK: "-cc1" // CHECK-X86_64: "-triple" "x86_64-unknown-fuchsia" // CHECK-AARCH64: "-triple" "aarch64-unknown-fuchsia" // CHECK-RISCV64: "-triple" "riscv64-unknown-fuchsia" @@ -54,22 +54,22 @@ // CHECK-NOT: crtend.o // CHECK-NOT: crtn.o -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -rtlib=libgcc -fuse-ld=lld 2>&1 \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia -rtlib=libgcc -fuse-ld=lld 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-RTLIB // CHECK-RTLIB: error: invalid runtime library name in argument '-rtlib=libgcc' -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -static -fuse-ld=lld 2>&1 \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia -static -fuse-ld=lld 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-STATIC // CHECK-STATIC: "-Bstatic" // CHECK-STATIC: "-Bdynamic" // CHECK-STATIC: "-lc" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -shared -fuse-ld=lld 2>&1 \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia -shared -fuse-ld=lld 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-SHARED // CHECK-SHARED-NOT: "-pie" // CHECK-SHARED: "-shared" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -r -fuse-ld=lld 2>&1 \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia -r -fuse-ld=lld 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-RELOCATABLE // CHECK-RELOCATABLE-NOT: "-pie" // CHECK-RELOCATABLE-NOT: "--build-id" @@ -77,28 +77,28 @@ // CHECK-RELOCATABLE-NOT: "-l // CHECK-RELOCATABLE-NOT: crt{{[^./]+}}.o -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -nodefaultlibs -fuse-ld=lld 2>&1 \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia -nodefaultlibs -fuse-ld=lld 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck %s -check-prefix=CHECK-NODEFAULTLIBS // CHECK-NODEFAULTLIBS: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-NODEFAULTLIBS-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.builtins.a" // CHECK-NODEFAULTLIBS-NOT: "-lc" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -nostdlib -fuse-ld=lld 2>&1 \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia -nostdlib -fuse-ld=lld 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck %s -check-prefix=CHECK-NOSTDLIB // CHECK-NOSTDLIB: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-NOSTDLIB-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.builtins.a" // CHECK-NOSTDLIB-NOT: "-lc" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -nolibc -fuse-ld=lld 2>&1 \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia -nolibc -fuse-ld=lld 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck %s -check-prefix=CHECK-NOLIBC // CHECK-NOLIBC: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-NOLIBC: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.builtins.a" // CHECK-NOLIBC-NOT: "-lc" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia \ // RUN: -fsanitize=safe-stack 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld \ @@ -108,7 +108,7 @@ // CHECK-SAFESTACK-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.safestack.a" // CHECK-SAFESTACK-NOT: "__safestack_init" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia \ // RUN: -fsanitize=address 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld \ @@ -120,7 +120,7 @@ // CHECK-ASAN-X86: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.asan.so" // CHECK-ASAN-X86: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.asan-preinit.a" -// RUN: %clang %s -### --target=aarch64-unknown-fuchsia \ +// RUN: %clang -### %s --target=aarch64-unknown-fuchsia \ // RUN: -fsanitize=address 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld \ @@ -132,7 +132,7 @@ // CHECK-ASAN-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}aarch64-unknown-fuchsia{{/|\\\\}}libclang_rt.asan.so" // CHECK-ASAN-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}aarch64-unknown-fuchsia{{/|\\\\}}libclang_rt.asan-preinit.a" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia \ // RUN: -fsanitize=address -fPIC -shared 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld \ @@ -143,7 +143,7 @@ // CHECK-ASAN-SHARED: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.asan.so" // CHECK-ASAN-SHARED-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.asan-preinit.a" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia \ // RUN: -fsanitize=fuzzer 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld \ @@ -152,7 +152,7 @@ // CHECK-FUZZER-X86: "-fsanitize=fuzzer,fuzzer-no-link,safe-stack" // CHECK-FUZZER-X86: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.fuzzer.a" -// RUN: %clang %s -### --target=aarch64-unknown-fuchsia \ +// RUN: %clang -### %s --target=aarch64-unknown-fuchsia \ // RUN: -fsanitize=fuzzer 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld \ @@ -161,7 +161,7 @@ // CHECK-FUZZER-AARCH64: "-fsanitize=fuzzer,fuzzer-no-link,shadow-call-stack" // CHECK-FUZZER-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}aarch64-unknown-fuchsia{{/|\\\\}}libclang_rt.fuzzer.a" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia \ // RUN: -fsanitize=scudo 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld \ @@ -171,7 +171,7 @@ // CHECK-SCUDO-X86: "-pie" // CHECK-SCUDO-X86: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.scudo.so" -// RUN: %clang %s -### --target=aarch64-unknown-fuchsia \ +// RUN: %clang -### %s --target=aarch64-unknown-fuchsia \ // RUN: -fsanitize=scudo 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld \ @@ -181,7 +181,7 @@ // CHECK-SCUDO-AARCH64: "-pie" // CHECK-SCUDO-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}aarch64-unknown-fuchsia{{/|\\\\}}libclang_rt.scudo.so" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia \ // RUN: -fsanitize=scudo -fPIC -shared 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld \ @@ -190,7 +190,7 @@ // CHECK-SCUDO-SHARED: "-fsanitize=safe-stack,scudo" // CHECK-SCUDO-SHARED: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.scudo.so" -// RUN: %clang %s -### --target=aarch64-unknown-fuchsia \ +// RUN: %clang -### %s --target=aarch64-unknown-fuchsia \ // RUN: -fsanitize=leak 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld \ @@ -200,7 +200,7 @@ // CHECK-LSAN-AARCH64: "-pie" // CHECK-LSAN-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}aarch64-unknown-fuchsia{{/|\\\\}}libclang_rt.lsan.a" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia \ // RUN: -fsanitize=leak 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld \ @@ -210,7 +210,7 @@ // CHECK-LSAN-X86: "-pie" // CHECK-LSAN-X86: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.lsan.a" -// RUN: %clang %s -### --target=aarch64-unknown-fuchsia \ +// RUN: %clang -### %s --target=aarch64-unknown-fuchsia \ // RUN: -fsanitize=leak -fPIC -shared 2>&1 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld \ @@ -219,7 +219,7 @@ // CHECK-LSAN-SHARED: "-fsanitize=leak,shadow-call-stack" // CHECK-LSAN-SHARED-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}aarch64-unknown-fuchsia{{/|\\\\}}libclang_rt.lsan.a" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia \ // RUN: -fxray-instrument -fxray-modes=xray-basic \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1 \ @@ -229,7 +229,7 @@ // CHECK-XRAY-X86: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.xray.a" // CHECK-XRAY-X86: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.xray-basic.a" -// RUN: %clang %s -### --target=aarch64-unknown-fuchsia \ +// RUN: %clang -### %s --target=aarch64-unknown-fuchsia \ // RUN: -fxray-instrument -fxray-modes=xray-basic \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1 \ @@ -239,14 +239,14 @@ // CHECK-XRAY-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}aarch64-unknown-fuchsia{{/|\\\\}}libclang_rt.xray.a" // CHECK-XRAY-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}aarch64-unknown-fuchsia{{/|\\\\}}libclang_rt.xray-basic.a" -// RUN: %clang %s -### --target=aarch64-unknown-fuchsia \ +// RUN: %clang -### %s --target=aarch64-unknown-fuchsia \ // RUN: -O3 -flto -mcpu=cortex-a53 2>&1 \ // RUN: -fuse-ld=lld \ // RUN: | FileCheck %s -check-prefix=CHECK-LTO // CHECK-LTO: "-plugin-opt=mcpu=cortex-a53" // CHECK-LTO: "-plugin-opt=O3" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia \ // RUN: -flto=thin -flto-jobs=8 2>&1 \ // RUN: -fuse-ld=lld \ // RUN: | FileCheck %s -check-prefix=CHECK-THINLTO @@ -254,12 +254,12 @@ // CHECK-THINLTO: "-plugin-opt=thinlto" // CHECK-THINLTO: "-plugin-opt=jobs=8" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia \ // RUN: -gsplit-dwarf -g -c %s 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-SPLIT-DWARF // CHECK-SPLIT-DWARF: "-split-dwarf-output" "fuchsia.dwo" -// RUN: %clang %s -### --target=aarch64-unknown-fuchsia \ +// RUN: %clang -### %s --target=aarch64-unknown-fuchsia \ // RUN: -fprofile-instr-generate -fcoverage-mapping \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1 \ @@ -267,7 +267,7 @@ // CHECK-PROFRT-AARCH64: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-PROFRT-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}aarch64-unknown-fuchsia{{/|\\\\}}libclang_rt.profile.a" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia \ // RUN: -fprofile-instr-generate -fcoverage-mapping \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1 \ diff --git a/clang/test/Driver/fuchsia.cpp b/clang/test/Driver/fuchsia.cpp index 7d2e342f72e6d..e5640f5826271 100644 --- a/clang/test/Driver/fuchsia.cpp +++ b/clang/test/Driver/fuchsia.cpp @@ -1,34 +1,34 @@ -// RUN: %clangxx %s -### -no-canonical-prefixes --target=x86_64-unknown-fuchsia \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-X86_64 %s -// RUN: %clangxx %s -### -no-canonical-prefixes --target=aarch64-unknown-fuchsia \ +// RUN: %clangxx -### %s --target=aarch64-unknown-fuchsia \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-AARCH64 %s -// RUN: %clangxx %s -### -no-canonical-prefixes --target=riscv64-unknown-fuchsia \ +// RUN: %clangxx -### %s --target=riscv64-unknown-fuchsia \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-RISCV64 %s -// RUN: %clangxx %s -### -no-canonical-prefixes --target=x86_64-fuchsia \ +// RUN: %clangxx -### %s --target=x86_64-fuchsia \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-X86_64 %s -// RUN: %clangxx %s -### -no-canonical-prefixes --target=aarch64-fuchsia \ +// RUN: %clangxx -### %s --target=aarch64-fuchsia \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-AARCH64 %s -// RUN: %clangxx %s -### -no-canonical-prefixes --target=riscv64-fuchsia \ +// RUN: %clangxx -### %s --target=riscv64-fuchsia \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-RISCV64 %s -// CHECK: {{.*}}clang{{.*}}" "-cc1" +// CHECK: "-cc1" // CHECK-X86_64: "-triple" "x86_64-unknown-fuchsia" // CHECK-AARCH64: "-triple" "aarch64-unknown-fuchsia" // CHECK-RISCV64: "-triple" "riscv64-unknown-fuchsia" @@ -61,12 +61,12 @@ // CHECK-NOT: crtend.o // CHECK-NOT: crtn.o -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -stdlib=libstdc++ \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -stdlib=libstdc++ \ // RUN: -fuse-ld=lld 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-STDLIB // CHECK-STDLIB: error: invalid library name in argument '-stdlib=libstdc++' -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -static-libstdc++ \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -static-libstdc++ \ // RUN: -fuse-ld=lld 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-STATIC // CHECK-STATIC: "--push-state" @@ -78,100 +78,100 @@ // CHECK-STATIC: "--pop-state" // CHECK-STATIC: "-lc" -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -nostdlib++ -fuse-ld=lld 2>&1 \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -nostdlib++ -fuse-ld=lld 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-NOSTDLIBXX // CHECK-NOSTDLIBXX-NOT: "-lc++" // CHECK-NOSTDLIBXX-NOT: "-lm" // CHECK-NOSTDLIBXX: "-lc" -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fsanitize=address \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fsanitize=address \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-ASAN-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fno-exceptions \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fno-exceptions \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-NOEXCEPT-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fsanitize=address -fno-exceptions \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fsanitize=address -fno-exceptions \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-ASAN-NOEXCEPT-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fexperimental-relative-c++-abi-vtables \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fexperimental-relative-c++-abi-vtables \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-RELATIVE-VTABLES-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fexperimental-relative-c++-abi-vtables -fno-exceptions \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fexperimental-relative-c++-abi-vtables -fno-exceptions \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-RELATIVE-VTABLES-NOEXCEPT-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fexperimental-relative-c++-abi-vtables -fsanitize=address \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fexperimental-relative-c++-abi-vtables -fsanitize=address \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-RELATIVE-VTABLES-ASAN-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fexperimental-relative-c++-abi-vtables -fno-exceptions -fsanitize=address \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fexperimental-relative-c++-abi-vtables -fno-exceptions -fsanitize=address \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-RELATIVE-VTABLES-ASAN-NOEXCEPT-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fno-experimental-relative-c++-abi-vtables \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fno-experimental-relative-c++-abi-vtables \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fno-experimental-relative-c++-abi-vtables \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fno-experimental-relative-c++-abi-vtables \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fno-experimental-relative-c++-abi-vtables -fexperimental-relative-c++-abi-vtables \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fno-experimental-relative-c++-abi-vtables -fexperimental-relative-c++-abi-vtables \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fsanitize=hwaddress \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fsanitize=hwaddress \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-HWASAN-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fsanitize=hwaddress -fno-exceptions \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fsanitize=hwaddress -fno-exceptions \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-HWASAN-NOEXCEPT-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fexperimental-relative-c++-abi-vtables -fsanitize=hwaddress \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fexperimental-relative-c++-abi-vtables -fsanitize=hwaddress \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-RELATIVE-VTABLES-HWASAN-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fexperimental-relative-c++-abi-vtables -fno-exceptions -fsanitize=hwaddress \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fexperimental-relative-c++-abi-vtables -fno-exceptions -fsanitize=hwaddress \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-RELATIVE-VTABLES-HWASAN-NOEXCEPT-X86 // Test compat multilibs. -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fc++-abi=itanium \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fc++-abi=itanium \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-COMPAT-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fc++-abi=itanium -fc++-abi=fuchsia \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fc++-abi=itanium -fc++-abi=fuchsia \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ // RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86 -// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -fc++-abi=fuchsia -fc++-abi=itanium \ +// RUN: %clangxx -### %s --target=x86_64-unknown-fuchsia -fc++-abi=fuchsia -fc++-abi=itanium \ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ diff --git a/clang/test/Driver/hip-cuid-hash.hip b/clang/test/Driver/hip-cuid-hash.hip index 25a746bcc1e75..0c7c2a7fbd3e5 100644 --- a/clang/test/Driver/hip-cuid-hash.hip +++ b/clang/test/Driver/hip-cuid-hash.hip @@ -27,8 +27,8 @@ // RUN: FileCheck %s -check-prefixes=DIFF -input-file %t.out -// SAME: "{{.*}}clang{{.*}}" {{.*}} "-target-cpu" "gfx906" {{.*}}"-cuid=[[CUID:[0-9a-f]+]]" -// SAME: "{{.*}}clang{{.*}}" {{.*}} "-target-cpu" "gfx906" {{.*}}"-cuid=[[CUID]]" +// SAME: "-cc1"{{.*}} "-target-cpu" "gfx906" {{.*}}"-cuid=[[CUID:[0-9a-f]+]]" +// SAME: "-cc1"{{.*}} "-target-cpu" "gfx906" {{.*}}"-cuid=[[CUID]]" -// DIFF: "{{.*}}clang{{.*}}" {{.*}} "-target-cpu" "gfx906" {{.*}}"-cuid=[[CUID:[0-9a-f]+]]" -// DIFF-NOT: "{{.*}}clang{{.*}}" {{.*}} "-target-cpu" "gfx906" {{.*}}"-cuid=[[CUID]]" +// DIFF: "-cc1"{{.*}} "-target-cpu" "gfx906" {{.*}}"-cuid=[[CUID:[0-9a-f]+]]" +// DIFF-NOT: "-target-cpu" "gfx906" {{.*}}"-cuid=[[CUID]]" diff --git a/clang/test/Driver/hip-cuid.hip b/clang/test/Driver/hip-cuid.hip index e1f2d16291592..347dcac0670e3 100644 --- a/clang/test/Driver/hip-cuid.hip +++ b/clang/test/Driver/hip-cuid.hip @@ -58,35 +58,35 @@ // INVALID: invalid value 'invalid' in '-fuse-cuid=invalid' -// COMMON: "{{.*}}clang{{.*}}" "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa" +// COMMON: "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa" // COMMON-SAME: "-target-cpu" "gfx900" // HEX-SAME: "-cuid=[[CUID:[0-9a-f]+]]" // FIXED-SAME: "-cuid=[[CUID:xyz_123]]" // COMMON-SAME: "{{.*}}a.cu" -// COMMON: "{{.*}}clang{{.*}}" "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa" +// COMMON: "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa" // COMMON-SAME: "-target-cpu" "gfx906" // COMMON-SAME: "-cuid=[[CUID]]" // COMMON-SAME: "{{.*}}a.cu" -// COMMON: "{{.*}}clang{{.*}}" "-cc1"{{.*}} "-triple" "x86_64-unknown-linux-gnu" +// COMMON: "-cc1"{{.*}} "-triple" "x86_64-unknown-linux-gnu" // COMMON-SAME: "-cuid=[[CUID]]" // COMMON-SAME: "{{.*}}a.cu" -// COMMON: "{{.*}}clang{{.*}}" "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa" +// COMMON: "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa" // COMMON-SAME: "-target-cpu" "gfx900" // HEX-NOT: "-cuid=[[CUID]]" // HEX-SAME: "-cuid=[[CUID2:[0-9a-f]+]]" // FIXED-SAME: "-cuid=[[CUID2:xyz_123]]" // COMMON-SAME: "{{.*}}b.hip" -// COMMON: "{{.*}}clang{{.*}}" "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa" +// COMMON: "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa" // COMMON-SAME: "-target-cpu" "gfx906" // HEX-NOT: "-cuid=[[CUID]]" // COMMON-SAME: "-cuid=[[CUID2]]" // COMMON-SAME: "{{.*}}b.hip" -// COMMON: "{{.*}}clang{{.*}}" "-cc1"{{.*}} "-triple" "x86_64-unknown-linux-gnu" +// COMMON: "-cc1"{{.*}} "-triple" "x86_64-unknown-linux-gnu" // HEX-NOT: "-cuid=[[CUID]]" // COMMON-SAME: "-cuid=[[CUID2]]" // COMMON-SAME: "{{.*}}b.hip" diff --git a/clang/test/Driver/hip-link-bundle-archive.hip b/clang/test/Driver/hip-link-bundle-archive.hip index 641bf59b63461..7ffe135405da6 100644 --- a/clang/test/Driver/hip-link-bundle-archive.hip +++ b/clang/test/Driver/hip-link-bundle-archive.hip @@ -1,14 +1,28 @@ // REQUIRES: x86-registered-target, amdgpu-registered-target -// RUN: touch %T/libhipBundled.a // Check clang unbundle the archive and link them by lld. +// RUN: touch %T/libhipBundled.a // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \ +// RUN: -target x86_64-unknown-linux-gnu \ // RUN: -nogpulib %s -fgpu-rdc -L%T -lhipBundled \ -// RUN: 2>&1 | FileCheck -check-prefix=CHECK %s +// RUN: 2>&1 | FileCheck -check-prefix=GNU %s + +// RUN: touch %T/hipBundled2.lib +// RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \ +// RUN: -target x86_64-pc-windows-msvc \ +// RUN: -nogpulib %s -fgpu-rdc -L%T -lhipBundled2 \ +// RUN: 2>&1 | FileCheck -check-prefix=MSVC %s + +// GNU: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}libhipBundled.a" "-targets=hip-amdgcn-amd-amdhsa-gfx1030" "-output=[[A1030:.*\.a]]" "-allow-missing-bundles" +// GNU: "{{.*}}lld{{.*}}" {{.*}}"-plugin-opt=mcpu=gfx1030" {{.*}} "[[A1030]]" +// GNU: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}libhipBundled.a" "-targets=hip-amdgcn-amd-amdhsa-gfx906" "-output=[[A906:.*\.a]]" "-allow-missing-bundles" +// GNU: "{{.*}}lld{{.*}}" {{.*}}"-plugin-opt=mcpu=gfx906" {{.*}} "[[A906]]" +// GNU: "{{.*}}ld{{.*}}" {{.*}}"-o" "a.out" {{.*}}"-lhipBundled" -// CHECK: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}libhipBundled.a" "-targets=hip-amdgcn-amd-amdhsa-gfx1030" "-output=[[A1030:.*\.a]]" "-allow-missing-bundles" -// CHECK: "{{.*}}lld{{.*}}" {{.*}}"-plugin-opt=mcpu=gfx1030" {{.*}} "[[A1030]]" -// CHECK: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}libhipBundled.a" "-targets=hip-amdgcn-amd-amdhsa-gfx906" "-output=[[A906:.*\.a]]" "-allow-missing-bundles" -// CHECK: "{{.*}}lld{{.*}}" {{.*}}"-plugin-opt=mcpu=gfx906" {{.*}} "[[A906]]" +// MSVC: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}hipBundled2.lib" "-targets=hip-amdgcn-amd-amdhsa-gfx1030" "-output=[[A1030:.*\.a]]" "-allow-missing-bundles" +// MSVC: "{{.*}}lld{{.*}}" {{.*}}"-plugin-opt=mcpu=gfx1030" {{.*}} "[[A1030]]" +// MSVC: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}hipBundled2.lib" "-targets=hip-amdgcn-amd-amdhsa-gfx906" "-output=[[A906:.*\.a]]" "-allow-missing-bundles" +// MSVC: "{{.*}}lld{{.*}}" {{.*}}"-plugin-opt=mcpu=gfx906" {{.*}} "[[A906]]" +// MSVC: "{{.*}}link{{.*}}" {{.*}}"-out:a.exe" {{.*}}"hipBundled2.lib" diff --git a/clang/test/Driver/hip-options.hip b/clang/test/Driver/hip-options.hip index c995fa68daccd..c4f436669b0b7 100644 --- a/clang/test/Driver/hip-options.hip +++ b/clang/test/Driver/hip-options.hip @@ -106,3 +106,13 @@ // RUN: --offload-arch=gfx906 -fopenmp -fopenmp-targets=amdgcn %s 2>&1 \ // RUN: | FileCheck -check-prefix=OMPTGT %s // OMPTGT: unsupported option '-fopenmp-targets=' for language mode 'HIP' + +// Check -Xoffload-linker option is passed to lld. + +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpuinc -nogpulib \ +// RUN: --cuda-gpu-arch=gfx906 -fgpu-rdc -Xoffload-linker --build-id=md5 %s 2>&1 \ +// RUN: | FileCheck -check-prefix=OFL-LINK %s +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpuinc -nogpulib \ +// RUN: --cuda-gpu-arch=gfx906 -Xoffload-linker --build-id=md5 %s 2>&1 \ +// RUN: | FileCheck -check-prefix=OFL-LINK %s +// OFL-LINK: lld{{.*}}"--build-id=md5" diff --git a/clang/test/Driver/hip-std.hip b/clang/test/Driver/hip-std.hip index 1d52b911df86f..2e47cbc47df08 100644 --- a/clang/test/Driver/hip-std.hip +++ b/clang/test/Driver/hip-std.hip @@ -3,20 +3,20 @@ // RUN: %clang -### -target x86_64-unknown-linux-gnu -offload-arch=gfx906 %s \ // RUN: 2>&1 | FileCheck -check-prefixes=DEFAULT %s -// DEFAULT: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-fcuda-is-device"{{.*}}"-std=c++11" -// DEFAULT: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-std=c++11" +// DEFAULT: "-cc1"{{.*}}"-fcuda-is-device"{{.*}}"-std=c++11" +// DEFAULT: "-cc1"{{.*}}"-std=c++11" // RUN: %clang -### -target x86_64-unknown-linux-gnu -offload-arch=gfx906 %s \ // RUN: -std=c++17 %s 2>&1 | FileCheck -check-prefixes=SPECIFIED %s -// SPECIFIED: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-fcuda-is-device"{{.*}}"-std=c++17" -// SPECIFIED: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-std=c++17" +// SPECIFIED: "-cc1"{{.*}}"-fcuda-is-device"{{.*}}"-std=c++17" +// SPECIFIED: "-cc1"{{.*}}"-std=c++17" // RUN: %clang -### -target x86_64-pc-windows-msvc -offload-arch=gfx906 %s \ // RUN: 2>&1 | FileCheck -check-prefixes=MSVC-DEF %s -// MSVC-DEF: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-fcuda-is-device"{{.*}}"-std=c++14" -// MSVC-DEF: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-std=c++14" +// MSVC-DEF: "-cc1"{{.*}}"-fcuda-is-device"{{.*}}"-std=c++14" +// MSVC-DEF: "-cc1"{{.*}}"-std=c++14" // RUN: %clang -### -target x86_64-pc-windows-msvc -offload-arch=gfx906 %s \ // RUN: -std=c++17 %s 2>&1 | FileCheck -check-prefixes=MSVC-SPEC %s -// MSVC-SPEC: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-fcuda-is-device"{{.*}}"-std=c++17" -// MSVC-SPEC: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-std=c++17" +// MSVC-SPEC: "-cc1"{{.*}}"-fcuda-is-device"{{.*}}"-std=c++17" +// MSVC-SPEC: "-cc1"{{.*}}"-std=c++17" diff --git a/clang/test/Driver/hip-toolchain-opt.hip b/clang/test/Driver/hip-toolchain-opt.hip index bf4f4620c9c69..40cae56353b45 100644 --- a/clang/test/Driver/hip-toolchain-opt.hip +++ b/clang/test/Driver/hip-toolchain-opt.hip @@ -57,7 +57,7 @@ // RUN: %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck --check-prefixes=ALL,Og %s -// ALL: "{{.*}}clang{{.*}}" "-cc1" "-triple" "amdgcn-amd-amdhsa" +// ALL: "-cc1" "-triple" "amdgcn-amd-amdhsa" // DEFAULT-NOT: "-O{{.}}" // O0-SAME: "-O0" // O1-SAME: "-O1" @@ -81,7 +81,7 @@ // Oz-SAME: "-plugin-opt=O2" // Og-SAME: "-plugin-opt=O1" -// ALL: "{{.*}}clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-linux-gnu" +// ALL: "-cc1" "-triple" "x86_64-unknown-linux-gnu" // DEFAULT-NOT: "-O{{.}}" // O0-SAME: "-O0" // O1-SAME: "-O1" diff --git a/clang/test/Driver/hlsl_no_stdinc.hlsl b/clang/test/Driver/hlsl_no_stdinc.hlsl new file mode 100644 index 0000000000000..ec6d0612a9ed7 --- /dev/null +++ b/clang/test/Driver/hlsl_no_stdinc.hlsl @@ -0,0 +1,12 @@ +// RUN: %clang_dxc -Tlib_6_7 -fcgl -Fo - %s -### 2>&1 | FileCheck %s --check-prefix=STDINC +// RUN: %clang_dxc -Tlib_6_7 -hlsl-no-stdinc -fcgl -Fo - %s -### 2>&1 | FileCheck %s --check-prefix=NOSTDINC + +// RUN: %clang -cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -ast-dump -o - %s -verify + +// Make sure hlsl-no-stdinc is translated into finclude-default-header. +// STDINC:"-finclude-default-header" +// NOSTDINC-NOT:"-finclude-default-header" + +// Make sure uint not work when finclude-default-header is off. +// expected-error@+1 {{unknown type name 'uint'}} +uint a; diff --git a/clang/test/Driver/linker-wrapper-image.c b/clang/test/Driver/linker-wrapper-image.c index 98141f4658bd1..524fc2551daa2 100644 --- a/clang/test/Driver/linker-wrapper-image.c +++ b/clang/test/Driver/linker-wrapper-image.c @@ -12,20 +12,20 @@ // OPENMP-NEXT: @__stop_omp_offloading_entries = external hidden constant %__tgt_offload_entry // OPENMP-NEXT: @__dummy.omp_offloading.entry = hidden constant [0 x %__tgt_offload_entry] zeroinitializer, section "omp_offloading_entries" // OPENMP-NEXT: @.omp_offloading.device_image = internal unnamed_addr constant [0 x i8] zeroinitializer -// OPENMP-NEXT: @.omp_offloading.device_images = internal unnamed_addr constant [1 x %__tgt_device_image] [%__tgt_device_image { i8* getelementptr inbounds ([0 x i8], [0 x i8]* @.omp_offloading.device_image, i64 0, i64 0), i8* getelementptr inbounds ([0 x i8], [0 x i8]* @.omp_offloading.device_image, i64 0, i64 0), %__tgt_offload_entry* @__start_omp_offloading_entries, %__tgt_offload_entry* @__stop_omp_offloading_entries }] -// OPENMP-NEXT: @.omp_offloading.descriptor = internal constant %__tgt_bin_desc { i32 1, %__tgt_device_image* getelementptr inbounds ([1 x %__tgt_device_image], [1 x %__tgt_device_image]* @.omp_offloading.device_images, i64 0, i64 0), %__tgt_offload_entry* @__start_omp_offloading_entries, %__tgt_offload_entry* @__stop_omp_offloading_entries } -// OPENMP-NEXT: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @.omp_offloading.descriptor_reg, i8* null }] -// OPENMP-NEXT: @llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @.omp_offloading.descriptor_unreg, i8* null }] +// OPENMP-NEXT: @.omp_offloading.device_images = internal unnamed_addr constant [1 x %__tgt_device_image] [%__tgt_device_image { ptr @.omp_offloading.device_image, ptr @.omp_offloading.device_image, ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries }] +// OPENMP-NEXT: @.omp_offloading.descriptor = internal constant %__tgt_bin_desc { i32 1, ptr @.omp_offloading.device_images, ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries } +// OPENMP-NEXT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.omp_offloading.descriptor_reg, ptr null }] +// OPENMP-NEXT: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.omp_offloading.descriptor_unreg, ptr null }] // OPENMP: define internal void @.omp_offloading.descriptor_reg() section ".text.startup" { // OPENMP-NEXT: entry: -// OPENMP-NEXT: call void @__tgt_register_lib(%__tgt_bin_desc* @.omp_offloading.descriptor) +// OPENMP-NEXT: call void @__tgt_register_lib(ptr @.omp_offloading.descriptor) // OPENMP-NEXT: ret void // OPENMP-NEXT: } // OPENMP: define internal void @.omp_offloading.descriptor_unreg() section ".text.startup" { // OPENMP-NEXT: entry: -// OPENMP-NEXT: call void @__tgt_unregister_lib(%__tgt_bin_desc* @.omp_offloading.descriptor) +// OPENMP-NEXT: call void @__tgt_unregister_lib(ptr @.omp_offloading.descriptor) // OPENMP-NEXT: ret void // OPENMP-NEXT: } @@ -36,56 +36,56 @@ // RUN: -linker-path /usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CUDA // CUDA: @.fatbin_image = internal constant [0 x i8] zeroinitializer, section ".nv_fatbin" -// CUDA-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1180844977, i32 1, i8* getelementptr inbounds ([0 x i8], [0 x i8]* @.fatbin_image, i32 0, i32 0), i8* null }, section ".nvFatBinSegment", align 8 +// CUDA-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1180844977, i32 1, ptr @.fatbin_image, ptr null }, section ".nvFatBinSegment", align 8 // CUDA-NEXT: @__dummy.cuda_offloading.entry = hidden constant [0 x %__tgt_offload_entry] zeroinitializer, section "cuda_offloading_entries" -// CUDA-NEXT: @.cuda.binary_handle = internal global i8** null +// CUDA-NEXT: @.cuda.binary_handle = internal global ptr null // CUDA-NEXT: @__start_cuda_offloading_entries = external hidden constant [0 x %__tgt_offload_entry] // CUDA-NEXT: @__stop_cuda_offloading_entries = external hidden constant [0 x %__tgt_offload_entry] -// CUDA-NEXT: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @.cuda.fatbin_reg, i8* null }] +// CUDA-NEXT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.cuda.fatbin_reg, ptr null }] // CUDA: define internal void @.cuda.fatbin_reg() section ".text.startup" { // CUDA-NEXT: entry: -// CUDA-NEXT: %0 = call i8** @__cudaRegisterFatBinary(i8* bitcast (%fatbin_wrapper* @.fatbin_wrapper to i8*)) -// CUDA-NEXT: store i8** %0, i8*** @.cuda.binary_handle, align 8 -// CUDA-NEXT: call void @.cuda.globals_reg(i8** %0) -// CUDA-NEXT: call void @__cudaRegisterFatBinaryEnd(i8** %0) -// CUDA-NEXT: %1 = call i32 @atexit(void ()* @.cuda.fatbin_unreg) +// CUDA-NEXT: %0 = call ptr @__cudaRegisterFatBinary(ptr @.fatbin_wrapper) +// CUDA-NEXT: store ptr %0, ptr @.cuda.binary_handle, align 8 +// CUDA-NEXT: call void @.cuda.globals_reg(ptr %0) +// CUDA-NEXT: call void @__cudaRegisterFatBinaryEnd(ptr %0) +// CUDA-NEXT: %1 = call i32 @atexit(ptr @.cuda.fatbin_unreg) // CUDA-NEXT: ret void // CUDA-NEXT: } // CUDA: define internal void @.cuda.fatbin_unreg() section ".text.startup" { // CUDA-NEXT: entry: -// CUDA-NEXT: %0 = load i8**, i8*** @.cuda.binary_handle, align 8 -// CUDA-NEXT: call void @__cudaUnregisterFatBinary(i8** %0) +// CUDA-NEXT: %0 = load ptr, ptr @.cuda.binary_handle, align 8 +// CUDA-NEXT: call void @__cudaUnregisterFatBinary(ptr %0) // CUDA-NEXT: ret void // CUDA-NEXT: } -// CUDA: define internal void @.cuda.globals_reg(i8** %0) section ".text.startup" { +// CUDA: define internal void @.cuda.globals_reg(ptr %0) section ".text.startup" { // CUDA-NEXT: entry: -// CUDA-NEXT: br i1 icmp ne ([0 x %__tgt_offload_entry]* @__start_cuda_offloading_entries, [0 x %__tgt_offload_entry]* @__stop_cuda_offloading_entries), label %while.entry, label %while.end +// CUDA-NEXT: br i1 icmp ne (ptr @__start_cuda_offloading_entries, ptr @__stop_cuda_offloading_entries), label %while.entry, label %while.end // CUDA: while.entry: -// CUDA-NEXT: %entry1 = phi %__tgt_offload_entry* [ getelementptr inbounds ([0 x %__tgt_offload_entry], [0 x %__tgt_offload_entry]* @__start_cuda_offloading_entries, i64 0, i64 0), %entry ], [ %7, %if.end ] -// CUDA-NEXT: %1 = getelementptr inbounds %__tgt_offload_entry, %__tgt_offload_entry* %entry1, i64 0, i32 0 -// CUDA-NEXT: %addr = load i8*, i8** %1, align 8 -// CUDA-NEXT: %2 = getelementptr inbounds %__tgt_offload_entry, %__tgt_offload_entry* %entry1, i64 0, i32 1 -// CUDA-NEXT: %name = load i8*, i8** %2, align 8 -// CUDA-NEXT: %3 = getelementptr inbounds %__tgt_offload_entry, %__tgt_offload_entry* %entry1, i64 0, i32 2 -// CUDA-NEXT: %size = load i64, i64* %3, align 4 +// CUDA-NEXT: %entry1 = phi ptr [ @__start_cuda_offloading_entries, %entry ], [ %7, %if.end ] +// CUDA-NEXT: %1 = getelementptr inbounds %__tgt_offload_entry, ptr %entry1, i64 0, i32 0 +// CUDA-NEXT: %addr = load ptr, ptr %1, align 8 +// CUDA-NEXT: %2 = getelementptr inbounds %__tgt_offload_entry, ptr %entry1, i64 0, i32 1 +// CUDA-NEXT: %name = load ptr, ptr %2, align 8 +// CUDA-NEXT: %3 = getelementptr inbounds %__tgt_offload_entry, ptr %entry1, i64 0, i32 2 +// CUDA-NEXT: %size = load i64, ptr %3, align 4 // CUDA-NEXT: %4 = icmp eq i64 %size, 0 // CUDA-NEXT: br i1 %4, label %if.then, label %if.else // CUDA: if.then: -// CUDA-NEXT: %5 = call i32 @__cudaRegisterFunction(i8** %0, i8* %addr, i8* %name, i8* %name, i32 -1, i8* null, i8* null, i8* null, i8* null, i32* null) +// CUDA-NEXT: %5 = call i32 @__cudaRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null) // CUDA-NEXT: br label %if.end // CUDA: if.else: -// CUDA-NEXT: %6 = call i32 @__cudaRegisterVar(i8** %0, i8* %addr, i8* %name, i8* %name, i32 0, i64 %size, i32 0, i32 0) +// CUDA-NEXT: %6 = call i32 @__cudaRegisterVar(ptr %0, ptr %addr, ptr %name, ptr %name, i32 0, i64 %size, i32 0, i32 0) // CUDA-NEXT: br label %if.end // CUDA: if.end: -// CUDA-NEXT: %7 = getelementptr inbounds %__tgt_offload_entry, %__tgt_offload_entry* %entry1, i64 1 -// CUDA-NEXT: %8 = icmp eq %__tgt_offload_entry* %7, getelementptr inbounds ([0 x %__tgt_offload_entry], [0 x %__tgt_offload_entry]* @__stop_cuda_offloading_entries, i64 0, i64 0) +// CUDA-NEXT: %7 = getelementptr inbounds %__tgt_offload_entry, ptr %entry1, i64 1 +// CUDA-NEXT: %8 = icmp eq ptr %7, @__stop_cuda_offloading_entries // CUDA-NEXT: br i1 %8, label %while.end, label %while.entry // CUDA: while.end: diff --git a/clang/test/Driver/lto-no-opaque-pointers.c b/clang/test/Driver/lto-no-opaque-pointers.c new file mode 100644 index 0000000000000..9146ae5da5824 --- /dev/null +++ b/clang/test/Driver/lto-no-opaque-pointers.c @@ -0,0 +1,5 @@ +// UNSUPPORTED: enable-opaque-pointers +// RUN: %clang --target=x86_64-unknown-linux -### %s -flto 2> %t +// RUN: FileCheck %s < %t + +// CHECK: -plugin-opt=no-opaque-pointers diff --git a/clang/test/Driver/lto-opaque-pointers.c b/clang/test/Driver/lto-opaque-pointers.c new file mode 100644 index 0000000000000..acdf13c21fd41 --- /dev/null +++ b/clang/test/Driver/lto-opaque-pointers.c @@ -0,0 +1,5 @@ +// REQUIRES: enable-opaque-pointers +// RUN: %clang --target=x86_64-unknown-linux -### %s -flto 2> %t +// RUN: FileCheck %s < %t + +// CHECK-NOT: -plugin-opt=no-opaque-pointers diff --git a/clang/test/Driver/memtag_lto.c b/clang/test/Driver/memtag_lto.c index d73670f99cb60..2ad22141608c7 100644 --- a/clang/test/Driver/memtag_lto.c +++ b/clang/test/Driver/memtag_lto.c @@ -8,9 +8,9 @@ // RUN: %clang -O1 -target aarch64-unknown-linux -mllvm -stack-safety-print %s -S -o - 2>&1 | FileCheck %s // Full LTO -// RUN: %clang -O1 -target aarch64-unknown-linux -c %s -flto=full -o %t.ltonewpm1.bc -// RUN: %clang -O1 -target aarch64-unknown-linux -c -DBUILD2 %s -flto=full -o %t.ltonewpm2.bc -// RUN: llvm-lto2 run -o %t.ltonewpm %t.ltonewpm1.bc %t.ltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \ +// RUN: %clang -O1 -target aarch64-unknown-linux -c %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm1.bc +// RUN: %clang -O1 -target aarch64-unknown-linux -c -DBUILD2 %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm2.bc +// RUN: llvm-lto2 run -lto-opaque-pointers -o %t.ltonewpm %t.ltonewpm1.bc %t.ltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \ // RUN: -r %t.ltonewpm1.bc,fn,plx \ // RUN: -r %t.ltonewpm1.bc,use,lx \ // RUN: -r %t.ltonewpm1.bc,use_local,plx \ @@ -19,9 +19,9 @@ // RUN: -r %t.ltonewpm2.bc,z, 2>&1 | FileCheck %s --allow-empty // Thin LTO, new PM -// RUN: %clang -O1 -target aarch64-unknown-linux -c %s -flto=thin -o %t.thinltonewpm1.bc -// RUN: %clang -O1 -target aarch64-unknown-linux -c -DBUILD2 %s -flto=thin -o %t.thinltonewpm2.bc -// RUN: llvm-lto2 run -o %t.thinltonewpm %t.thinltonewpm1.bc %t.thinltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \ +// RUN: %clang -O1 -target aarch64-unknown-linux -c %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm1.bc +// RUN: %clang -O1 -target aarch64-unknown-linux -c -DBUILD2 %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm2.bc +// RUN: llvm-lto2 run -lto-opaque-pointers -o %t.thinltonewpm %t.thinltonewpm1.bc %t.thinltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \ // RUN: -r %t.thinltonewpm1.bc,fn,plx \ // RUN: -r %t.thinltonewpm1.bc,use,lx \ // RUN: -r %t.thinltonewpm1.bc,use_local,plx \ @@ -39,9 +39,9 @@ // RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -mllvm -stack-safety-print %s -S -o /dev/null 2>&1 | FileCheck %s -check-prefixes=SSI,XUNSAFE,YSAFE // Full LTO: both are safe. -// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -flto=full -o %t.ltonewpm1.bc -// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c -DBUILD2 %s -flto=full -o %t.ltonewpm2.bc -// RUN: llvm-lto2 run -o %t.ltonewpm %t.ltonewpm1.bc %t.ltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \ +// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm1.bc +// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c -DBUILD2 %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm2.bc +// RUN: llvm-lto2 run -lto-opaque-pointers -o %t.ltonewpm %t.ltonewpm1.bc %t.ltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \ // RUN: -r %t.ltonewpm1.bc,fn,plx \ // RUN: -r %t.ltonewpm1.bc,use,lx \ // RUN: -r %t.ltonewpm1.bc,use_local,plx \ @@ -50,9 +50,9 @@ // RUN: -r %t.ltonewpm2.bc,z, 2>&1 | FileCheck %s -check-prefixes=SSI,XSAFE,YSAFE // Thin LTO: both are safe. -// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -flto=thin -o %t.thinltonewpm1.bc -// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c -DBUILD2 %s -flto=thin -o %t.thinltonewpm2.bc -// RUN: llvm-lto2 run -o %t.thinltonewpm %t.thinltonewpm1.bc %t.thinltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \ +// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm1.bc +// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c -DBUILD2 %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm2.bc +// RUN: llvm-lto2 run -lto-opaque-pointers -o %t.thinltonewpm %t.thinltonewpm1.bc %t.thinltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \ // RUN: -r %t.thinltonewpm1.bc,fn,plx \ // RUN: -r %t.thinltonewpm1.bc,use,lx \ // RUN: -r %t.thinltonewpm1.bc,use_local,plx \ diff --git a/clang/test/Driver/miamcu-opt.c b/clang/test/Driver/miamcu-opt.c index 6fcee57a64643..e668b6ad828fe 100644 --- a/clang/test/Driver/miamcu-opt.c +++ b/clang/test/Driver/miamcu-opt.c @@ -1,13 +1,13 @@ // REQUIRES: x86-registered-target // -// RUN: %clang -miamcu -rtlib=platform -no-canonical-prefixes %s -### -o %t.o 2>&1 | FileCheck %s -// RUN: %clang -miamcu -rtlib=platform -no-canonical-prefixes -m32 %s -### -o %t.o 2>&1 | FileCheck %s -// RUN: %clang -miamcu -rtlib=platform -no-canonical-prefixes -target x86_64-unknown-linux-gnu %s -### -o %t.o 2>&1 | FileCheck %s -// RUN: %clang -mno-iamcu -miamcu -rtlib=platform -no-canonical-prefixes %s -### -o %t.o 2>&1 | FileCheck %s -// RUN: %clang -miamcu -rtlib=platform -no-canonical-prefixes -m64 %s -### -o %t.o 2>&1 | FileCheck %s -check-prefix=M64 -// RUN: %clang -miamcu -rtlib=platform -no-canonical-prefixes -dynamic %s -### -o %t.o 2>&1 | FileCheck %s -check-prefix=DYNAMIC -// RUN: %clang -miamcu -rtlib=platform -no-canonical-prefixes -target armv8-eabi %s -### -o %t.o 2>&1 | FileCheck %s -check-prefix=NOT-X86 -// RUN: %clang -miamcu -mno-iamcu -no-canonical-prefixes -target x86_64-unknown-linux-gnu %s -### -o %t.o 2>&1 | FileCheck %s -check-prefix=MNOIAMCU +// RUN: %clang -miamcu -rtlib=platform -### %s 2>&1 | FileCheck %s +// RUN: %clang -miamcu -rtlib=platform -m32 -### %s 2>&1 | FileCheck %s +// RUN: %clang -miamcu -rtlib=platform --target=x86_64-unknown-linux-gnu -### %s 2>&1 | FileCheck %s +// RUN: %clang -mno-iamcu -miamcu -rtlib=platform -### %s 2>&1 | FileCheck %s +// RUN: %clang -miamcu -rtlib=platform -m64 -### %s 2>&1 | FileCheck %s -check-prefix=M64 +// RUN: %clang -miamcu -rtlib=platform -dynamic -### %s 2>&1 | FileCheck %s -check-prefix=DYNAMIC +// RUN: %clang -miamcu -rtlib=platform --target=armv8-eabi -### %s 2>&1 | FileCheck %s -check-prefix=NOT-X86 +// RUN: %clang -miamcu -mno-iamcu --target=x86_64-unknown-linux-gnu -### %s 2>&1 | FileCheck %s -check-prefix=MNOIAMCU // M64: error: invalid argument '-miamcu' not allowed with '-m64' @@ -17,7 +17,7 @@ // MNOIAMCU-NOT: "-triple" "i586-intel-elfiamcu" -// CHECK: "{{.*}}clang{{.*}}" "-cc1" +// CHECK: "-cc1" // CHECK: "-triple" "i586-intel-elfiamcu" // CHECK: "-static-define" // CHECK: "-mfloat-abi" "soft" diff --git a/clang/test/Driver/mips-eleb.c b/clang/test/Driver/mips-eleb.c index aaa80e0c0908a..37236984ab10a 100644 --- a/clang/test/Driver/mips-eleb.c +++ b/clang/test/Driver/mips-eleb.c @@ -1,33 +1,33 @@ // Check that -EL/-EB options adjust the toolchain flags. // -// RUN: %clang -no-canonical-prefixes -target mips-unknown-linux-gnu -### \ +// RUN: %clang --target=mips-unknown-linux-gnu -### \ // RUN: -EL -no-integrated-as %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS32-EL %s -// MIPS32-EL: "{{.*}}clang{{.*}}" "-cc1" "-triple" "mipsel-unknown-linux-gnu" +// MIPS32-EL: "-cc1" "-triple" "mipsel-unknown-linux-gnu" // MIPS32-EL: "{{.*}}as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" // MIPS32-EL: "-EL" // MIPS32-EL: "{{.*}}ld{{(.exe)?}}" {{.*}} "-m" "elf32ltsmip" // -// RUN: %clang -no-canonical-prefixes -target mips64-unknown-linux-gnu -### \ +// RUN: %clang --target=mips64-unknown-linux-gnu -### \ // RUN: -EL -no-integrated-as %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS64-EL %s -// MIPS64-EL: "{{.*}}clang{{.*}}" "-cc1" "-triple" "mips64el-unknown-linux-gnu" +// MIPS64-EL: "-cc1" "-triple" "mips64el-unknown-linux-gnu" // MIPS64-EL: "{{.*}}as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "64" // MIPS64-EL: "-EL" // MIPS64-EL: "{{.*}}ld{{(.exe)?}}" {{.*}} "-m" "elf64ltsmip" // -// RUN: %clang -no-canonical-prefixes -target mipsel-unknown-linux-gnu -### \ +// RUN: %clang --target=mipsel-unknown-linux-gnu -### \ // RUN: -EB -no-integrated-as %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS32-EB %s -// MIPS32-EB: "{{.*}}clang{{.*}}" "-cc1" "-triple" "mips-unknown-linux-gnu" +// MIPS32-EB: "-cc1" "-triple" "mips-unknown-linux-gnu" // MIPS32-EB: "{{.*}}as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" // MIPS32-EB: "-EB" // MIPS32-EB: "{{.*}}ld{{(.exe)?}}" {{.*}} "-m" "elf32btsmip" // -// RUN: %clang -no-canonical-prefixes -target mips64el-unknown-linux-gnu -### \ +// RUN: %clang --target=mips64el-unknown-linux-gnu -### \ // RUN: -EB -no-integrated-as %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS64-EB %s -// MIPS64-EB: "{{.*}}clang{{.*}}" "-cc1" "-triple" "mips64-unknown-linux-gnu" +// MIPS64-EB: "-cc1" "-triple" "mips64-unknown-linux-gnu" // MIPS64-EB: "{{.*}}as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "64" // MIPS64-EB: "-EB" // MIPS64-EB: "{{.*}}ld{{(.exe)?}}" {{.*}} "-m" "elf64btsmip" diff --git a/clang/test/Driver/modules-cache-path.m b/clang/test/Driver/modules-cache-path.m index 51df6739a5055..1da27d2143631 100644 --- a/clang/test/Driver/modules-cache-path.m +++ b/clang/test/Driver/modules-cache-path.m @@ -1,2 +1,10 @@ // RUN: %clang -fmodules -### %s 2>&1 | FileCheck %s -check-prefix=CHECK-DEFAULT // CHECK-DEFAULT: -fmodules-cache-path={{.*}}clang{{[/\\]+}}ModuleCache + +// RUN: env CLANG_MODULE_CACHE_PATH=/dev/null \ +// RUN: %clang -fmodules -### %s 2>&1 | FileCheck %s -check-prefix=OVERRIDE +// OVERRIDE: -fmodules-cache-path=/dev/null + +// RUN: env CLANG_MODULE_CACHE_PATH= \ +// RUN: %clang -fmodules -### %s 2>&1 | FileCheck %s -check-prefix=DISABLE +// DISABLE-NOT: -fmodules-cache-path= diff --git a/clang/test/Driver/modules.cpp b/clang/test/Driver/modules.cpp index f532b5b3c775f..87b6cc640cb0d 100644 --- a/clang/test/Driver/modules.cpp +++ b/clang/test/Driver/modules.cpp @@ -73,11 +73,3 @@ import "foo.h"; // CHECK-HEADER-UNIT-USE: BAR; FOO; #endif - -// Check the independent use of -fcxx-modules -// -// RUN: %clang -fcxx-modules -std=c++17 -### -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-CXX-MODULES -// RUN: %clang -fcxx-modules -std=c++14 -### -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-CXX-MODULES -// RUN: %clang -fcxx-modules -std=c++11 -### -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-CXX-MODULES -// RUN: %clang -fcxx-modules -std=c++03 -### -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-CXX-MODULES -// CHECK-CXX-MODULES: "-fcxx-modules" diff --git a/clang/test/Driver/msp430-toolchain.c b/clang/test/Driver/msp430-toolchain.c index 1aee2f75a9d9d..13a4a1afdad89 100644 --- a/clang/test/Driver/msp430-toolchain.c +++ b/clang/test/Driver/msp430-toolchain.c @@ -3,24 +3,24 @@ // Test for include paths and other cc1 flags -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -E \ +// RUN: %clang -### %s --target=msp430 -E \ // RUN: --sysroot="%S/Inputs/basic_msp430_tree" 2>&1 \ // RUN: | FileCheck -check-prefix=INCLUDE-DIRS %s -// INCLUDE-DIRS: "{{.*}}clang{{.*}}" "-cc1" "-triple" "msp430" +// INCLUDE-DIRS: "-cc1" "-triple" "msp430" // INCLUDE-DIRS: "-internal-isystem" "{{.*}}/Inputs/basic_msp430_tree{{/|\\\\}}msp430-elf{{/|\\\\}}include" // Tests for passing flags to msp430-elf-ld (not file-related) -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 --sysroot="" > %t 2>&1 +// RUN: %clang -### %s --target=msp430 --sysroot="" > %t 2>&1 // RUN: FileCheck -check-prefix=DEFAULT-POS %s < %t // RUN: FileCheck -check-prefix=DEFAULT-NEG %s < %t // DEFAULT-POS: "{{.*}}msp430-elf-ld" // DEFAULT-POS: "--gc-sections" // DEFAULT-NEG-NOT: "--relax" -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 --sysroot="" \ +// RUN: %clang -### %s --target=msp430 --sysroot="" \ // RUN: -r 2>&1 | FileCheck --check-prefixes=NO-GC-SECTIONS,RELOCATABLE-OBJECT %s -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 --sysroot="" \ +// RUN: %clang -### %s --target=msp430 --sysroot="" \ // RUN: -g 2>&1 | FileCheck -check-prefix=NO-GC-SECTIONS %s // NO-GC-SECTIONS: "{{.*}}msp430-elf-ld" // NO-GC-SECTIONS-NOT: "--gc-sections" @@ -29,7 +29,7 @@ // RELOCATABLE-OBJECT-NOT: crtend // RELOCATABLE-OBJECT-NOT: "-l{{.*}}" -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 --sysroot="" \ +// RUN: %clang -### %s --target=msp430 --sysroot="" \ // RUN: -Wl,--some-linker-arg 2>&1 | FileCheck -check-prefix=WL-ARG %s // WL-ARG: "{{.*}}msp430-elf-ld" // WL-ARG: "--some-linker-arg" @@ -37,7 +37,7 @@ // Trivially mapped options: arbitrarily split into two disjoint groups // to check both "on"/present and "off"/absent state (when appropriate). -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 --sysroot="" \ +// RUN: %clang -### %s --target=msp430 --sysroot="" \ // RUN: -o /tmp/test.elf -r -t -z muldefs -mrelax > %t 2>&1 // RUN: FileCheck -check-prefix=MISC-FLAGS-1-POS %s < %t // RUN: FileCheck -check-prefix=MISC-FLAGS-1-NEG %s < %t @@ -52,7 +52,7 @@ // MISC-FLAGS-1-NEG-NOT: "-s" // MISC-FLAGS-1-NEG-NOT: "-u" -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 --sysroot="" \ +// RUN: %clang -### %s --target=msp430 --sysroot="" \ // RUN: -e EntryPoint -s -u __undef > %t 2>&1 // RUN: FileCheck -check-prefix=MISC-FLAGS-2-POS %s < %t // RUN: FileCheck -check-prefix=MISC-FLAGS-2-NEG %s < %t @@ -66,11 +66,11 @@ // Tests for -nostdlib, -nostartfiles, -nodefaultfiles and -f(no-)exceptions -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -rtlib=libgcc \ +// RUN: %clang -### %s --target=msp430 -rtlib=libgcc \ // RUN: --sysroot="%S/Inputs/basic_msp430_tree" > %t 2>&1 // RUN: FileCheck -check-prefix=LIBS-DEFAULT-POS %s < %t // RUN: FileCheck -check-prefix=LIBS-DEFAULT-NEG %s < %t -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -rtlib=libgcc \ +// RUN: %clang -### %s --target=msp430 -rtlib=libgcc \ // RUN: --gcc-toolchain="%S/Inputs/basic_msp430_tree" --sysroot="" 2>&1 \ // RUN: | FileCheck -check-prefix=LIBS-DEFAULT-GCC-TOOLCHAIN %s // LIBS-DEFAULT-POS: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/8.3.1/../../..{{/|\\\\}}..{{/|\\\\}}bin{{/|\\\\}}msp430-elf-ld" @@ -94,7 +94,7 @@ // LIBS-DEFAULT-NEG-NOT: crtend.o // LIBS-DEFAULT-NEG-NOT: /exceptions -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -rtlib=compiler-rt \ +// RUN: %clang -### %s --target=msp430 -rtlib=compiler-rt \ // RUN: --sysroot="%S/Inputs/basic_msp430_tree" > %t 2>&1 // RUN: FileCheck -check-prefix=LIBS-COMPILER-RT-POS %s < %t // RUN: FileCheck -check-prefix=LIBS-COMPILER-RT-NEG %s < %t @@ -112,7 +112,7 @@ // LIBS-COMPILER-RT-NEG-NOT: crtend.o // LIBS-COMPILER-RT-NEG-NOT: /exceptions -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -rtlib=libgcc -fexceptions \ +// RUN: %clang -### %s --target=msp430 -rtlib=libgcc -fexceptions \ // RUN: --sysroot="%S/Inputs/basic_msp430_tree" > %t 2>&1 // RUN: FileCheck -check-prefix=LIBS-EXC-POS %s < %t // RUN: FileCheck -check-prefix=LIBS-EXC-NEG %s < %t @@ -126,7 +126,7 @@ // LIBS-EXC-NEG-NOT: "{{.*}}/430" // LIBS-EXC-NEG-NOT: "{{.*}}430/crt{{.*}}" -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -rtlib=libgcc \ +// RUN: %clang -### %s --target=msp430 -rtlib=libgcc \ // RUN: -fstack-protector --sysroot="%S/Inputs/basic_msp430_tree" 2>&1 \ // RUN: | FileCheck -check-prefix=LIBS-SSP %s // LIBS-SSP: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/8.3.1/../../..{{/|\\\\}}..{{/|\\\\}}bin{{/|\\\\}}msp430-elf-ld" @@ -138,7 +138,7 @@ // LIBS-SSP: "-lgcc" "--start-group" "-lmul_none" "-lc" "-lgcc" "-lcrt" "-lnosys" "--end-group" // LIBS-SSP: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/8.3.1/430{{/|\\\\}}crtend_no_eh.o" "-lgcc" -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -rtlib=libgcc -nodefaultlibs \ +// RUN: %clang -### %s --target=msp430 -rtlib=libgcc -nodefaultlibs \ // RUN: --sysroot="%S/Inputs/basic_msp430_tree" > %t 2>&1 // RUN: FileCheck -check-prefix=LIBS-NO-DFT-POS %s < %t // RUN: FileCheck -check-prefix=LIBS-NO-DFT-NEG %s < %t @@ -155,7 +155,7 @@ // LIBS-NO-DFT-NEG-NOT: "--start-group" // LIBS-NO-DFT-NEG-NOT: "--end-group" -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -rtlib=libgcc -nolibc \ +// RUN: %clang -### %s --target=msp430 -rtlib=libgcc -nolibc \ // RUN: -fstack-protector --sysroot="%S/Inputs/basic_msp430_tree" > %t 2>&1 // RUN: FileCheck -check-prefix=LIBS-NO-LIBC-POS %s < %t // RUN: FileCheck -check-prefix=LIBS-NO-LIBC-NEG %s < %t @@ -173,7 +173,7 @@ // LIBS-NO-LIBC-NEG-NOT: "--start-group" // LIBS-NO-LIBC-NEG-NOT: "--end-group" -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -rtlib=libgcc -nostartfiles \ +// RUN: %clang -### %s --target=msp430 -rtlib=libgcc -nostartfiles \ // RUN: --sysroot="%S/Inputs/basic_msp430_tree" > %t 2>&1 // RUN: FileCheck -check-prefix=LIBS-NO-START-POS %s < %t // RUN: FileCheck -check-prefix=LIBS-NO-START-NEG %s < %t @@ -185,7 +185,7 @@ // LIBS-NO-START-NEG-NOT: crtbegin // LIBS-NO-START-NEG-NOT: crtend -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -nostdlib \ +// RUN: %clang -### %s --target=msp430 -nostdlib \ // RUN: --sysroot="%S/Inputs/basic_msp430_tree" > %t 2>&1 // RUN: FileCheck -check-prefix=LIBS-NO-STD-POS %s < %t // RUN: FileCheck -check-prefix=LIBS-NO-STD-NEG %s < %t @@ -203,14 +203,14 @@ // Test for linker script autodiscovery -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=msp430g2553 \ +// RUN: %clang -### %s --target=msp430 -mmcu=msp430g2553 \ // RUN: --sysroot=%S/Inputs/basic_msp430_tree 2>&1 \ // RUN: | FileCheck -check-prefix=LD-SCRIPT %s // LD-SCRIPT: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/8.3.1/../../..{{/|\\\\}}..{{/|\\\\}}bin{{/|\\\\}}msp430-elf-ld" // LD-SCRIPT: "-L{{.*}}/Inputs/basic_msp430_tree{{/|\\\\}}include" // LD-SCRIPT: "-Tmsp430g2553.ld" -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=msp430g2553 \ +// RUN: %clang -### %s --target=msp430 -mmcu=msp430g2553 \ // RUN: --sysroot=%S/Inputs/basic_msp430_tree \ // RUN: -T custom_script.ld 2>&1 \ // RUN: | FileCheck -check-prefix=CUSTOM-LD-SCRIPT %s @@ -221,7 +221,7 @@ // Test for compiling for simulator -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=msp430g2553 \ +// RUN: %clang -### %s --target=msp430 -mmcu=msp430g2553 \ // RUN: -msim -rtlib=libgcc --sysroot=%S/Inputs/basic_msp430_tree > %t 2>&1 // RUN: FileCheck -check-prefix=SIMULATOR-POS %s < %t // RUN: FileCheck -check-prefix=SIMULATOR-NEG %s < %t @@ -237,28 +237,28 @@ // Tests for HWMult -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=msp430f147 --sysroot="" 2>&1 \ +// RUN: %clang -### %s --target=msp430 -mmcu=msp430f147 --sysroot="" 2>&1 \ // RUN: | FileCheck -check-prefix=HWMult-16BIT %s -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=msp430f147 -mhwmult=auto --sysroot="" 2>&1 \ +// RUN: %clang -### %s --target=msp430 -mmcu=msp430f147 -mhwmult=auto --sysroot="" 2>&1 \ // RUN: | FileCheck -check-prefix=HWMult-16BIT %s -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mhwmult=16bit --sysroot="" 2>&1 \ +// RUN: %clang -### %s --target=msp430 -mhwmult=16bit --sysroot="" 2>&1 \ // RUN: | FileCheck -check-prefix=HWMult-16BIT %s // HWMult-16BIT: "--start-group" "-lmul_16" -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=msp430f4783 --sysroot="" 2>&1 \ +// RUN: %clang -### %s --target=msp430 -mmcu=msp430f4783 --sysroot="" 2>&1 \ // RUN: | FileCheck -check-prefix=HWMult-32BIT %s -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=msp430f4783 -mhwmult=auto --sysroot="" 2>&1 \ +// RUN: %clang -### %s --target=msp430 -mmcu=msp430f4783 -mhwmult=auto --sysroot="" 2>&1 \ // RUN: | FileCheck -check-prefix=HWMult-32BIT %s -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mhwmult=32bit --sysroot="" 2>&1 \ +// RUN: %clang -### %s --target=msp430 -mhwmult=32bit --sysroot="" 2>&1 \ // RUN: | FileCheck -check-prefix=HWMult-32BIT %s // HWMult-32BIT: "--start-group" "-lmul_32" -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mhwmult=f5series --sysroot="" 2>&1 \ +// RUN: %clang -### %s --target=msp430 -mhwmult=f5series --sysroot="" 2>&1 \ // RUN: | FileCheck -check-prefix=HWMult-F5 %s // HWMult-F5: "--start-group" "-lmul_f5" -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mhwmult=none --sysroot="" 2>&1 \ +// RUN: %clang -### %s --target=msp430 -mhwmult=none --sysroot="" 2>&1 \ // RUN: | FileCheck -check-prefix=HWMult-NONE %s -// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mhwmult=none -mmcu=msp430f4783 --sysroot="" 2>&1 \ +// RUN: %clang -### %s --target=msp430 -mhwmult=none -mmcu=msp430f4783 --sysroot="" 2>&1 \ // RUN: | FileCheck -check-prefix=HWMult-NONE %s // HWMult-NONE: "--start-group" "-lmul_none" diff --git a/clang/test/Driver/nacl-direct.c b/clang/test/Driver/nacl-direct.c index 7cfa6cb6309d2..b1a80b3e9f837 100644 --- a/clang/test/Driver/nacl-direct.c +++ b/clang/test/Driver/nacl-direct.c @@ -1,10 +1,10 @@ // Test clang changes for NaCl Support including: // include paths, library paths, emulation, default static // -// RUN: %clang -no-canonical-prefixes -### -o %t.o %s \ -// RUN: -target i686-unknown-nacl -resource-dir foo 2>&1 \ +// RUN: %clang -### %s \ +// RUN: --target=i686-unknown-nacl -resource-dir foo 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-I686 %s -// CHECK-I686: {{.*}}clang{{.*}}" "-cc1" +// CHECK-I686: "-cc1" // CHECK-I686-NOT: "-fno-use-init-array" // CHECK-I686: "-target-cpu" "pentium4" // CHECK-I686: "-resource-dir" "foo" @@ -21,10 +21,10 @@ // CHECK-I686: "-Lfoo{{/|\\\\}}lib{{/|\\\\}}i686-nacl" // CHECK-I686-NOT: -lpthread // -// RUN: %clang -no-canonical-prefixes -### -o %t.o %s \ -// RUN: -target x86_64-unknown-nacl -resource-dir foo 2>&1 \ +// RUN: %clang -### %s \ +// RUN: --target=x86_64-unknown-nacl -resource-dir foo 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-x86_64 %s -// CHECK-x86_64: {{.*}}clang{{.*}}" "-cc1" +// CHECK-x86_64: "-cc1" // CHECK-x86_64-NOT: "-fno-use-init-array" // CHECK-x86_64: "-target-cpu" "x86-64" // CHECK-x86_64: "-resource-dir" "foo" @@ -41,10 +41,10 @@ // CHECK-x86_64: "-Lfoo{{/|\\\\}}lib{{/|\\\\}}x86_64-nacl" // CHECK-X86_64-NOT: -lpthread // -// RUN: %clang -no-canonical-prefixes -### -o %t.o %s \ -// RUN: -target armv7a-unknown-nacl-gnueabihf -resource-dir foo 2>&1 \ +// RUN: %clang -### %s \ +// RUN: --target=armv7a-unknown-nacl-gnueabihf -resource-dir foo 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-ARM %s -// CHECK-ARM: {{.*}}clang{{.*}}" "-cc1" +// CHECK-ARM: "-cc1" // CHECK-ARM-NOT: "-fno-use-init-array" // CHECK-ARM: "-target-cpu" "generic" // CHECK-ARM: "-target-abi" "aapcs-linux" @@ -64,10 +64,10 @@ // CHECK-ARM: "-Lfoo{{/|\\\\}}lib{{/|\\\\}}arm-nacl" // CHECK-ARM-NOT: -lpthread // -// RUN: %clang -no-canonical-prefixes -### -o %t.o %s \ -// RUN: -target mipsel-unknown-nacl -resource-dir foo 2>&1 \ +// RUN: %clang -### %s \ +// RUN: --target=mipsel-unknown-nacl -resource-dir foo 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-MIPS %s -// CHECK-MIPS: {{.*}}clang{{.*}}" "-cc1" +// CHECK-MIPS: "-cc1" // CHECK-MIPS-NOT: "-fno-use-init-array" // CHECK-MIPS: "-target-cpu" "mips32r2" // CHECK-MIPS: "-target-abi" "o32" @@ -89,8 +89,8 @@ // Check that even when the target arch is just "arm" (as will be the case when // it is inferred from the binary name) that we get the right ABI flags -// RUN: %clang -no-canonical-prefixes -### -o %t.o %s 2>&1 \ -// RUN: -target arm-nacl \ +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=arm-nacl \ // RUN: | FileCheck --check-prefix=CHECK-ARM-NOV7 %s // CHECK-ARM-NOV7: "-triple" "armv7-unknown-nacl-gnueabihf" // CHECK-ARM-NOV7: "-target-abi" "aapcs-linux" @@ -100,10 +100,10 @@ // Test clang c++ include dirs and link line when using clang++ -// RUN: %clangxx -no-canonical-prefixes -### -o %t.o %s \ -// RUN: -target armv7a-unknown-nacl-gnueabihf -resource-dir foo 2>&1 \ +// RUN: %clangxx -### %s \ +// RUN: --target=armv7a-unknown-nacl-gnueabihf -resource-dir foo 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-ARM-CXX %s -// CHECK-ARM-CXX: {{.*}}clang{{.*}}" "-cc1" +// CHECK-ARM-CXX: "-cc1" // CHECK-ARM-CXX: "-resource-dir" "foo" // CHECK-ARM-CXX: "-internal-isystem" "{{.*}}{{/|\\\\}}..{{/|\\\\}}arm-nacl{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}v1" // CHECK-ARM-CXX: "-internal-isystem" "foo{{/|\\\\}}include" @@ -111,10 +111,10 @@ // CHECK-ARM-CXX: "-internal-isystem" "{{.*}}{{/|\\\\}}..{{/|\\\\}}arm-nacl{{/|\\\\}}include" // CHECK-ARM-CXX: "-lpthread" -// RUN: %clangxx -no-canonical-prefixes -### -o %t.o %s \ -// RUN: -target i686-unknown-nacl -resource-dir foo 2>&1 \ +// RUN: %clangxx -### %s \ +// RUN: --target=i686-unknown-nacl -resource-dir foo 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-I686-CXX %s -// CHECK-I686-CXX: {{.*}}clang{{.*}}" "-cc1" +// CHECK-I686-CXX: "-cc1" // CHECK-I686-CXX: "-resource-dir" "foo" // CHECK-I686-CXX: "-internal-isystem" "{{.*}}{{/|\\\\}}..{{/|\\\\}}x86_64-nacl{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}v1" // CHECK-I686-CXX: "-internal-isystem" "foo{{/|\\\\}}include" @@ -122,10 +122,10 @@ // CHECK-I686-CXX: "-internal-isystem" "{{.*}}{{/|\\\\}}..{{/|\\\\}}x86_64-nacl{{/|\\\\}}include" // CHECK-I686-CXX: "-lpthread" -// RUN: %clangxx -no-canonical-prefixes -### -o %t.o %s \ -// RUN: -target x86_64-unknown-nacl -resource-dir foo 2>&1 \ +// RUN: %clangxx -### %s \ +// RUN: --target=x86_64-unknown-nacl -resource-dir foo 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-x86_64-CXX %s -// CHECK-x86_64-CXX: {{.*}}clang{{.*}}" "-cc1" +// CHECK-x86_64-CXX: "-cc1" // CHECK-x86_64-CXX: "-resource-dir" "foo" // CHECK-x86_64-CXX: "-internal-isystem" "{{.*}}{{/|\\\\}}..{{/|\\\\}}x86_64-nacl{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}v1" // CHECK-x86_64-CXX: "-internal-isystem" "foo{{/|\\\\}}include" @@ -133,10 +133,10 @@ // CHECK-x86_64-CXX: "-internal-isystem" "{{.*}}{{/|\\\\}}..{{/|\\\\}}x86_64-nacl{{/|\\\\}}include" // CHECK-x86_64-CXX: "-lpthread" -// RUN: %clangxx -no-canonical-prefixes -### -o %t.o %s \ -// RUN: -target mipsel-unknown-nacl -resource-dir foo 2>&1 \ +// RUN: %clangxx -### %s \ +// RUN: --target=mipsel-unknown-nacl -resource-dir foo 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-MIPS-CXX %s -// CHECK-MIPS-CXX: {{.*}}clang{{.*}}" "-cc1" +// CHECK-MIPS-CXX: "-cc1" // CHECK-MIPS-CXX: "-resource-dir" "foo" // CHECK-MIPS-CXX: "-internal-isystem" "{{.*}}{{/|\\\\}}..{{/|\\\\}}mipsel-nacl{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}v1" // CHECK-MIPS-CXX: "-internal-isystem" "foo{{/|\\\\}}include" diff --git a/clang/test/Driver/netbsd.c b/clang/test/Driver/netbsd.c index e429729b71c7c..69806a5ecdf72 100644 --- a/clang/test/Driver/netbsd.c +++ b/clang/test/Driver/netbsd.c @@ -1,135 +1,135 @@ -// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=x86_64-unknown-netbsd \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=STATIC %s -// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd \ -// RUN: -pie --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=x86_64-unknown-netbsd \ +// RUN: -pie --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=PIE %s -// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd \ -// RUN: -static -pie --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=x86_64-unknown-netbsd \ +// RUN: -static -pie --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=STATIC-PIE %s -// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd \ -// RUN: -shared --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=x86_64-unknown-netbsd \ +// RUN: -shared --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=SHARED %s -// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=x86_64-unknown-netbsd \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=X86_64 %s -// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd7.0.0 \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=x86_64-unknown-netbsd7.0.0 \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=X86_64-7 %s -// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd6.0.0 \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=x86_64-unknown-netbsd6.0.0 \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=X86_64-6 %s -// RUN: %clang -no-canonical-prefixes -target aarch64-unknown-netbsd \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=aarch64-unknown-netbsd \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=AARCH64 %s -// RUN: %clang -no-canonical-prefixes -target aarch64-unknown-netbsd7.0.0 \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=aarch64-unknown-netbsd7.0.0 \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=AARCH64-7 %s -// RUN: %clang -no-canonical-prefixes -target aarch64_be-unknown-netbsd \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=aarch64_be-unknown-netbsd \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=AARCH64_BE %s -// RUN: %clang -no-canonical-prefixes -target aarch64_be-unknown-netbsd7.0.0 \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=aarch64_be-unknown-netbsd7.0.0 \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=AARCH64_BE-7 %s -// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd-eabi \ -// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=arm-unknown-netbsd-eabi \ +// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=ARM %s -// RUN: %clang -no-canonical-prefixes -target armeb-unknown-netbsd-eabi \ -// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=armeb-unknown-netbsd-eabi \ +// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=ARMEB %s -// RUN: %clang -no-canonical-prefixes -target armeb-unknown-netbsd-eabi -march=armv7 \ -// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=armeb-unknown-netbsd-eabi -march=armv7 \ +// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=ARMV7EB %s -// RUN: %clang -no-canonical-prefixes -target armv7eb-unknown-netbsd-eabi \ -// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=armv7eb-unknown-netbsd-eabi \ +// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=ARMV7EB %s -// RUN: %clang -r -no-canonical-prefixes -target armeb-unknown-netbsd-eabi \ -// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang -r --target=armeb-unknown-netbsd-eabi \ +// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=ARMEB-R %s -// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd \ -// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=arm-unknown-netbsd \ +// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=ARM-APCS %s -// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd-eabihf \ -// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=arm-unknown-netbsd-eabihf \ +// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=ARM-HF %s -// RUN: %clang -no-canonical-prefixes -target thumb-unknown-netbsd-eabi \ -// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=thumb-unknown-netbsd-eabi \ +// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=THUMB %s -// RUN: %clang -no-canonical-prefixes -target thumbeb-unknown-netbsd-eabi \ -// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=thumbeb-unknown-netbsd-eabi \ +// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=THUMBEB %s -// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd7.0.0-eabi \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=arm-unknown-netbsd7.0.0-eabi \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=ARM-7 %s -// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd6.0.0-eabi \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=arm-unknown-netbsd6.0.0-eabi \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=ARM-6 %s -// RUN: %clang -no-canonical-prefixes -target sparc-unknown-netbsd \ -// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=sparc-unknown-netbsd \ +// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=SPARC %s -// RUN: %clang -no-canonical-prefixes -target sparc64-unknown-netbsd \ -// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=sparc64-unknown-netbsd \ +// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=SPARC64 %s -// RUN: %clang -no-canonical-prefixes -target powerpc-unknown-netbsd \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=powerpc-unknown-netbsd \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=POWERPC %s -// RUN: %clang -no-canonical-prefixes -target powerpc64-unknown-netbsd \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=powerpc64-unknown-netbsd \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=POWERPC64 %s -// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=x86_64-unknown-netbsd -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-X86_64 %s -// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd7.0.0 -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=x86_64-unknown-netbsd7.0.0 -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-X86_64-7 %s -// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd6.0.0 -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=x86_64-unknown-netbsd6.0.0 -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-X86_64-6 %s -// RUN: %clang -no-canonical-prefixes -target aarch64-unknown-netbsd -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=aarch64-unknown-netbsd -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-AARCH64 %s -// RUN: %clang -no-canonical-prefixes -target aarch64-unknown-netbsd7.0.0 -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=aarch64-unknown-netbsd7.0.0 -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-AARCH64-7 %s -// RUN: %clang -no-canonical-prefixes -target aarch64_be-unknown-netbsd -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=aarch64_be-unknown-netbsd -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-AARCH64_BE %s -// RUN: %clang -no-canonical-prefixes -target aarch64_be-unknown-netbsd7.0.0 -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=aarch64_be-unknown-netbsd7.0.0 -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-AARCH64_BE-7 %s -// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd-eabi -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=arm-unknown-netbsd-eabi -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-ARM %s -// RUN: %clang -no-canonical-prefixes -target armeb-unknown-netbsd-eabi -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=armeb-unknown-netbsd-eabi -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-ARMEB %s -// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd7.0.0-eabi -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=arm-unknown-netbsd7.0.0-eabi -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-ARM-7 %s -// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd6.0.0-eabi -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=arm-unknown-netbsd6.0.0-eabi -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-ARM-6 %s -// RUN: %clang -no-canonical-prefixes -target sparc-unknown-netbsd7.0.0 -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=sparc-unknown-netbsd7.0.0 -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-SPARC-7 %s -// RUN: %clang -no-canonical-prefixes -target sparc-unknown-netbsd6.0.0 -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=sparc-unknown-netbsd6.0.0 -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-SPARC-6 %s -// RUN: %clang -no-canonical-prefixes -target sparc64-unknown-netbsd7.0.0 -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=sparc64-unknown-netbsd7.0.0 -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-SPARC64-7 %s -// RUN: %clang -no-canonical-prefixes -target sparc64-unknown-netbsd6.0.0 -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=sparc64-unknown-netbsd6.0.0 -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-SPARC64-6 %s -// RUN: %clang -no-canonical-prefixes -target powerpc-unknown-netbsd -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=powerpc-unknown-netbsd -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-POWERPC %s -// RUN: %clang -no-canonical-prefixes -target powerpc64-unknown-netbsd -static \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=powerpc64-unknown-netbsd -static \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-POWERPC64 %s -// RUN: %clang -target x86_64-unknown-netbsd -pthread -dM -E %s \ +// RUN: %clang --target=x86_64-unknown-netbsd -pthread -dM -E %s \ // RUN: | FileCheck -check-prefix=PTHREAD %s // STATIC: ld{{.*}}" "--eh-frame-hdr" @@ -168,55 +168,55 @@ // PIE: "{{.*}}/usr/lib{{/|\\\\}}crtendS.o" // PIE: "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// X86_64: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd" +// X86_64: "-cc1" "-triple" "x86_64-unknown-netbsd" // X86_64-NOT: "-fno-use-init-array" // X86_64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // X86_64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // X86_64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // X86_64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// X86_64-7: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd7.0.0" +// X86_64-7: "-cc1" "-triple" "x86_64-unknown-netbsd7.0.0" // X86_64-7: "-fno-use-init-array" // X86_64-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // X86_64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // X86_64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // X86_64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// X86_64-6: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd6.0.0" +// X86_64-6: "-cc1" "-triple" "x86_64-unknown-netbsd6.0.0" // X86_64-6: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // X86_64-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// AARCH64: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd" +// AARCH64: "-cc1" "-triple" "aarch64-unknown-netbsd" // AARCH64-NOT: "-fno-use-init-array" // AARCH64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // AARCH64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// AARCH64-7: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd7.0.0" +// AARCH64-7: "-cc1" "-triple" "aarch64-unknown-netbsd7.0.0" // AARCH64-7-NOT: "-fno-use-init-array" // AARCH64-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // AARCH64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// AARCH64_BE: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd" +// AARCH64_BE: "-cc1" "-triple" "aarch64_be-unknown-netbsd" // AARCH64_BE-NOT: "-fno-use-init-array" // AARCH64_BE: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // AARCH64_BE: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// AARCH64_BE-7: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd7.0.0" +// AARCH64_BE-7: "-cc1" "-triple" "aarch64_be-unknown-netbsd7.0.0" // AARCH64_BE-7-NOT: "-fno-use-init-array" // AARCH64_BE-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // AARCH64_BE-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// ARM: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd-eabi" +// ARM: "-cc1" "-triple" "armv5e-unknown-netbsd-eabi" // ARM-NOT: "-fno-use-init-array" // ARM: as{{.*}}" "-mcpu=arm926ej-s" "-o" // ARM: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" @@ -226,7 +226,7 @@ // ARM: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // ARM: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// ARMEB: clang{{.*}}" "-cc1" "-triple" "armebv5e-unknown-netbsd-eabi" +// ARMEB: "-cc1" "-triple" "armebv5e-unknown-netbsd-eabi" // ARMEB-NOT: "-fno-use-init-array" // ARMEB: as{{.*}}" "-mcpu=arm926ej-s" "-o" // ARMEB: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" @@ -243,7 +243,7 @@ // ARMEB-R: ld{{.*}}" // ARMEB-R-NOT: "--be8" -// ARM-APCS: clang{{.*}}" "-cc1" "-triple" "armv4-unknown-netbsd" +// ARM-APCS: "-cc1" "-triple" "armv4-unknown-netbsd" // ARM-APCS: as{{.*}}" "-mcpu=strongarm" "-o" // ARM-APCS: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // ARM-APCS: "-m" "armelf_nbsd" @@ -252,7 +252,7 @@ // ARM-APCS: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // ARM-APCS: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// ARM-HF: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd-eabihf" +// ARM-HF: "-cc1" "-triple" "armv5e-unknown-netbsd-eabihf" // ARM-HF: as{{.*}}" "-mcpu=arm926ej-s" "-o" // ARM-HF: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // ARM-HF: "-m" "armelf_nbsd_eabihf" @@ -261,7 +261,7 @@ // ARM-HF: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // ARM-HF: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// THUMB: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd-eabi" +// THUMB: "-cc1" "-triple" "armv5e-unknown-netbsd-eabi" // THUMB: as{{.*}}" "-mcpu=arm926ej-s" "-o" // THUMB: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // THUMB: "-m" "armelf_nbsd_eabi" @@ -270,7 +270,7 @@ // THUMB: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // THUMB: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// THUMBEB: clang{{.*}}" "-cc1" "-triple" "armebv5e-unknown-netbsd-eabi" +// THUMBEB: "-cc1" "-triple" "armebv5e-unknown-netbsd-eabi" // THUMBEB: as{{.*}}" "-mcpu=arm926ej-s" "-o" // THUMBEB: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // THUMBEB: "-m" "armelfb_nbsd_eabi" @@ -279,7 +279,7 @@ // THUMBEB: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // THUMBEB: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// ARM-7: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd7.0.0-eabi" +// ARM-7: "-cc1" "-triple" "armv5e-unknown-netbsd7.0.0-eabi" // ARM-7-NOT: "-fno-use-init-array" // ARM-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // ARM-7: "-m" "armelf_nbsd_eabi" @@ -288,7 +288,7 @@ // ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// ARM-6: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd6.0.0-eabi" +// ARM-6: "-cc1" "-triple" "armv5e-unknown-netbsd6.0.0-eabi" // ARM-6: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // ARM-6: "-m" "armelf_nbsd_eabi" // ARM-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" @@ -296,7 +296,7 @@ // ARM-6: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // ARM-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// SPARC: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd" +// SPARC: "-cc1" "-triple" "sparc-unknown-netbsd" // SPARC-NOT: "-fno-use-init-array" // SPARC: as{{.*}}" "-32" "-Av8" "-o" // SPARC: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" @@ -306,7 +306,7 @@ // SPARC: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // SPARC: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// SPARC64: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd" +// SPARC64: "-cc1" "-triple" "sparc64-unknown-netbsd" // SPARC64-NOT: "-fno-use-init-array" // SPARC64: as{{.*}}" "-64" "-Av9" "-o" // SPARC64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" @@ -315,7 +315,7 @@ // SPARC64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // SPARC64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// POWERPC: clang{{.*}}" "-cc1" "-triple" "powerpc-unknown-netbsd" +// POWERPC: "-cc1" "-triple" "powerpc-unknown-netbsd" // POWERPC-NOT: "-fno-use-init-array" // POWERPC: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // POWERPC: "-m" "elf32ppc_nbsd" @@ -324,7 +324,7 @@ // POWERPC: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // POWERPC: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// POWERPC64: clang{{.*}}" "-cc1" "-triple" "powerpc64-unknown-netbsd" +// POWERPC64: "-cc1" "-triple" "powerpc64-unknown-netbsd" // POWERPC64-NOT: "-fno-use-init-array" // POWERPC64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // POWERPC64: "-m" "elf64ppc" @@ -333,50 +333,50 @@ // POWERPC64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // POWERPC64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-X86_64: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd" +// S-X86_64: "-cc1" "-triple" "x86_64-unknown-netbsd" // S-X86_64: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-X86_64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-X86_64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // S-X86_64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-X86_64-7: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd7.0.0" +// S-X86_64-7: "-cc1" "-triple" "x86_64-unknown-netbsd7.0.0" // S-X86_64-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-X86_64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-X86_64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // S-X86_64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-X86_64-6: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd6.0.0" +// S-X86_64-6: "-cc1" "-triple" "x86_64-unknown-netbsd6.0.0" // S-X86_64-6: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-X86_64-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // S-X86_64-6: "-lgcc_eh" "-lc" "-lgcc" // S-X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-AARCH64: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd" +// S-AARCH64: "-cc1" "-triple" "aarch64-unknown-netbsd" // S-AARCH64: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-AARCH64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // S-AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-AARCH64-7: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd7.0.0" +// S-AARCH64-7: "-cc1" "-triple" "aarch64-unknown-netbsd7.0.0" // S-AARCH64-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-AARCH64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // S-AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-AARCH64_BE: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd" +// S-AARCH64_BE: "-cc1" "-triple" "aarch64_be-unknown-netbsd" // S-AARCH64_BE: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-AARCH64_BE: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // S-AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-AARCH64_BE-7: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd7.0.0" +// S-AARCH64_BE-7: "-cc1" "-triple" "aarch64_be-unknown-netbsd7.0.0" // S-AARCH64_BE-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-AARCH64_BE-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // S-AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-ARM: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd-eabi" +// S-ARM: "-cc1" "-triple" "armv5e-unknown-netbsd-eabi" // S-ARM: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-ARM: "-m" "armelf_nbsd_eabi" // S-ARM: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" @@ -384,7 +384,7 @@ // S-ARM: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // S-ARM: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-ARMEB: clang{{.*}}" "-cc1" "-triple" "armebv5e-unknown-netbsd-eabi" +// S-ARMEB: "-cc1" "-triple" "armebv5e-unknown-netbsd-eabi" // S-ARMEB: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-ARMEB: "-m" "armelfb_nbsd_eabi" // S-ARMEB: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" @@ -392,7 +392,7 @@ // S-ARMEB: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // S-ARMEB: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-ARM-7: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd7.0.0-eabi" +// S-ARM-7: "-cc1" "-triple" "armv5e-unknown-netbsd7.0.0-eabi" // S-ARM-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-ARM-7: "-m" "armelf_nbsd_eabi" // S-ARM-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" @@ -400,7 +400,7 @@ // S-ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // S-ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-ARM-6: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd6.0.0-eabi" +// S-ARM-6: "-cc1" "-triple" "armv5e-unknown-netbsd6.0.0-eabi" // S-ARM-6: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-ARM-6: "-m" "armelf_nbsd_eabi" // S-ARM-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" @@ -409,7 +409,7 @@ // S-ARM-6: "-lgcc_eh" "-lc" "-lgcc" // S-ARM-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-SPARC-6: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd6.0.0" +// S-SPARC-6: "-cc1" "-triple" "sparc-unknown-netbsd6.0.0" // S-SPARC-6: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-SPARC-6: "-m" "elf32_sparc" // S-SPARC-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" @@ -418,7 +418,7 @@ // S-SPARC-6: "-lgcc_eh" "-lc" "-lgcc" // S-SPARC-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-SPARC-7: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd7.0.0" +// S-SPARC-7: "-cc1" "-triple" "sparc-unknown-netbsd7.0.0" // S-SPARC-7: "-fno-use-init-array" // S-SPARC-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-SPARC-7: "-m" "elf32_sparc" @@ -427,7 +427,7 @@ // S-SPARC-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // S-SPARC-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-SPARC64-6: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd6.0.0" +// S-SPARC64-6: "-cc1" "-triple" "sparc64-unknown-netbsd6.0.0" // S-SPARC64-6: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-SPARC64-6: "-m" "elf64_sparc" // S-SPARC64-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" @@ -435,7 +435,7 @@ // S-SPARC64-6: "-lgcc_eh" "-lc" "-lgcc" // S-SPARC64-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-SPARC64-7: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd7.0.0" +// S-SPARC64-7: "-cc1" "-triple" "sparc64-unknown-netbsd7.0.0" // S-SPARC64-7: "-fno-use-init-array" // S-SPARC64-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-SPARC64-7: "-m" "elf64_sparc" @@ -443,7 +443,7 @@ // S-SPARC64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // S-SPARC64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-POWERPC: clang{{.*}}" "-cc1" "-triple" "powerpc-unknown-netbsd" +// S-POWERPC: "-cc1" "-triple" "powerpc-unknown-netbsd" // S-POWERPC: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-POWERPC: "-m" "elf32ppc_nbsd" // S-POWERPC: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" @@ -451,7 +451,7 @@ // S-POWERPC: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc" // S-POWERPC: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-POWERPC64: clang{{.*}}" "-cc1" "-triple" "powerpc64-unknown-netbsd" +// S-POWERPC64: "-cc1" "-triple" "powerpc64-unknown-netbsd" // S-POWERPC64: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-POWERPC64: "-m" "elf64ppc" // S-POWERPC64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" @@ -464,13 +464,13 @@ // PTHREAD-NOT: _POSIX_THREADS // Check PowerPC for Secure PLT -// RUN: %clang -target powerpc-unknown-netbsd -### -c %s 2>&1 \ +// RUN: %clang --target=powerpc-unknown-netbsd -### -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=POWERPC-SECUREPLT %s // POWERPC-SECUREPLT: "-target-feature" "+secure-plt" // -r suppresses default -l and crt*.o like -nostdlib. -// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd -r \ -// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clang --target=x86_64-unknown-netbsd -r \ +// RUN: --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=RELOCATABLE %s // RELOCATABLE: "-r" // RELOCATABLE-NOT: "-l diff --git a/clang/test/Driver/netbsd.cpp b/clang/test/Driver/netbsd.cpp index 4af7d8373d672..e2b3ff651e9a1 100644 --- a/clang/test/Driver/netbsd.cpp +++ b/clang/test/Driver/netbsd.cpp @@ -1,168 +1,168 @@ -// RUN: %clangxx -no-canonical-prefixes -target x86_64-unknown-netbsd \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=x86_64-unknown-netbsd \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=X86_64 %s -// RUN: %clangxx -no-canonical-prefixes -target x86_64-unknown-netbsd7.0.0 \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=x86_64-unknown-netbsd7.0.0 \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=X86_64-7 %s -// RUN: %clangxx -no-canonical-prefixes -target x86_64-unknown-netbsd6.0.0 \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=x86_64-unknown-netbsd6.0.0 \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=X86_64-6 %s -// RUN: %clangxx -no-canonical-prefixes -target arm-unknown-netbsd6.0.0-eabi \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=arm-unknown-netbsd6.0.0-eabi \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=ARM %s -// RUN: %clangxx -no-canonical-prefixes -target arm-unknown-netbsd7.0.0-eabi \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=arm-unknown-netbsd7.0.0-eabi \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=ARM-7 %s -// RUN: %clangxx -no-canonical-prefixes -target aarch64-unknown-netbsd \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=aarch64-unknown-netbsd \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=AARCH64 %s -// RUN: %clangxx -no-canonical-prefixes -target aarch64-unknown-netbsd7.0.0 \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=aarch64-unknown-netbsd7.0.0 \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=AARCH64-7 %s -// RUN: %clangxx -no-canonical-prefixes -target aarch64_be-unknown-netbsd \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=aarch64_be-unknown-netbsd \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=AARCH64_BE %s -// RUN: %clangxx -no-canonical-prefixes -target aarch64_be-unknown-netbsd7.0.0 \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=aarch64_be-unknown-netbsd7.0.0 \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=AARCH64_BE-7 %s -// RUN: %clangxx -no-canonical-prefixes -target sparc-unknown-netbsd \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=sparc-unknown-netbsd \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=SPARC %s -// RUN: %clangxx -no-canonical-prefixes -target sparc-unknown-netbsd6.0.0 \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=sparc-unknown-netbsd6.0.0 \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=SPARC-6 %s -// RUN: %clangxx -no-canonical-prefixes -target sparc-unknown-netbsd7.0.0 \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=sparc-unknown-netbsd7.0.0 \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=SPARC-7 %s -// RUN: %clangxx -no-canonical-prefixes -target sparc64-unknown-netbsd \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=sparc64-unknown-netbsd \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=SPARC64 %s -// RUN: %clangxx -no-canonical-prefixes -target sparc64-unknown-netbsd6.0.0 \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=sparc64-unknown-netbsd6.0.0 \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=SPARC64-6 %s -// RUN: %clangxx -no-canonical-prefixes -target sparc64-unknown-netbsd7.0.0 \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=sparc64-unknown-netbsd7.0.0 \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=SPARC64-7 %s -// RUN: %clangxx -no-canonical-prefixes -target powerpc-unknown-netbsd \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=powerpc-unknown-netbsd \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=POWERPC %s -// RUN: %clangxx -no-canonical-prefixes -target powerpc64-unknown-netbsd \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=powerpc64-unknown-netbsd \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=POWERPC64 %s -// RUN: %clangxx -no-canonical-prefixes -target x86_64-unknown-netbsd -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=x86_64-unknown-netbsd -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-X86_64 %s -// RUN: %clangxx -no-canonical-prefixes -target x86_64-unknown-netbsd7.0.0 -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=x86_64-unknown-netbsd7.0.0 -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-X86_64-7 %s -// RUN: %clangxx -no-canonical-prefixes -target x86_64-unknown-netbsd6.0.0 -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=x86_64-unknown-netbsd6.0.0 -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-X86_64-6 %s -// RUN: %clangxx -no-canonical-prefixes -target arm-unknown-netbsd6.0.0-eabi -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=arm-unknown-netbsd6.0.0-eabi -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-ARM %s -// RUN: %clangxx -no-canonical-prefixes -target arm-unknown-netbsd7.0.0-eabi -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=arm-unknown-netbsd7.0.0-eabi -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-ARM-7 %s -// RUN: %clangxx -no-canonical-prefixes -target aarch64-unknown-netbsd -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=aarch64-unknown-netbsd -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-AARCH64 %s -// RUN: %clangxx -no-canonical-prefixes -target aarch64-unknown-netbsd7.0.0 -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=aarch64-unknown-netbsd7.0.0 -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-AARCH64-7 %s -// RUN: %clangxx -no-canonical-prefixes -target aarch64_be-unknown-netbsd -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=aarch64_be-unknown-netbsd -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-AARCH64_BE %s -// RUN: %clangxx -no-canonical-prefixes -target aarch64_be-unknown-netbsd7.0.0 -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=aarch64_be-unknown-netbsd7.0.0 -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-AARCH64_BE-7 %s -// RUN: %clangxx -no-canonical-prefixes -target sparc-unknown-netbsd -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=sparc-unknown-netbsd -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-SPARC %s -// RUN: %clangxx -no-canonical-prefixes -target sparc-unknown-netbsd6.0.0 -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=sparc-unknown-netbsd6.0.0 -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-SPARC-6 %s -// RUN: %clangxx -no-canonical-prefixes -target sparc-unknown-netbsd7.0.0 -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=sparc-unknown-netbsd7.0.0 -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-SPARC-7 %s -// RUN: %clangxx -no-canonical-prefixes -target sparc64-unknown-netbsd -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=sparc64-unknown-netbsd -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-SPARC64 %s -// RUN: %clangxx -no-canonical-prefixes -target sparc64-unknown-netbsd6.0.0 -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=sparc64-unknown-netbsd6.0.0 -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-SPARC64-6 %s -// RUN: %clangxx -no-canonical-prefixes -target sparc64-unknown-netbsd7.0.0 -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=sparc64-unknown-netbsd7.0.0 -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-SPARC64-7 %s -// RUN: %clangxx -no-canonical-prefixes -target powerpc-unknown-netbsd -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=powerpc-unknown-netbsd -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-POWERPC %s -// RUN: %clangxx -no-canonical-prefixes -target powerpc64-unknown-netbsd -static \ -// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: %clangxx --target=powerpc64-unknown-netbsd -static \ +// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=S-POWERPC64 %s -// X86_64: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd" +// X86_64: "-cc1" "-triple" "x86_64-unknown-netbsd" // X86_64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // X86_64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // X86_64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // X86_64: "-lm" "-lc" "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// X86_64-7: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd7.0.0" +// X86_64-7: "-cc1" "-triple" "x86_64-unknown-netbsd7.0.0" // X86_64-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // X86_64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // X86_64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // X86_64-7: "-lm" "-lc" "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// X86_64-6: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd6.0.0" +// X86_64-6: "-cc1" "-triple" "x86_64-unknown-netbsd6.0.0" // X86_64-6: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // X86_64-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lstdc++" // X86_64-6: "-lm" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" // X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// ARM: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd6.0.0-eabi" +// ARM: "-cc1" "-triple" "armv5e-unknown-netbsd6.0.0-eabi" // ARM: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // ARM: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}eabi{{/|\\\\}}crti.o" // ARM: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lstdc++" // ARM: "-lm" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" // ARM: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// ARM-7: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd7.0.0-eabi" +// ARM-7: "-cc1" "-triple" "armv5e-unknown-netbsd7.0.0-eabi" // ARM-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // ARM-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}eabi{{/|\\\\}}crti.o" // ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" "-lm" "-lc" // ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// AARCH64: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd" +// AARCH64: "-cc1" "-triple" "aarch64-unknown-netbsd" // AARCH64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // AARCH64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // AARCH64: "-lm" "-lc" // AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// AARCH64-7: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd7.0.0" +// AARCH64-7: "-cc1" "-triple" "aarch64-unknown-netbsd7.0.0" // AARCH64-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // AARCH64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // AARCH64-7: "-lm" "-lc" // AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// AARCH64_BE: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd" +// AARCH64_BE: "-cc1" "-triple" "aarch64_be-unknown-netbsd" // AARCH64_BE: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // AARCH64_BE: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // AARCH64_BE: "-lm" "-lc" // AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// AARCH64_BE-7: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd7.0.0" +// AARCH64_BE-7: "-cc1" "-triple" "aarch64_be-unknown-netbsd7.0.0" // AARCH64_BE-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // AARCH64_BE-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // AARCH64_BE-7: "-lm" "-lc" // AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// SPARC: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd" +// SPARC: "-cc1" "-triple" "sparc-unknown-netbsd" // SPARC: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // SPARC: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" // SPARC: "{{.*}}/usr/lib{{/|\\\\}}sparc{{/|\\\\}}crti.o" @@ -170,7 +170,7 @@ // SPARC: "-lm" "-lc" // SPARC: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// SPARC-7: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd7.0.0" +// SPARC-7: "-cc1" "-triple" "sparc-unknown-netbsd7.0.0" // SPARC-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // SPARC-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" // SPARC-7: "{{.*}}/usr/lib{{/|\\\\}}sparc{{/|\\\\}}crti.o" @@ -178,7 +178,7 @@ // SPARC-7: "-lm" "-lc" // SPARC-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// SPARC-6: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd6.0.0" +// SPARC-6: "-cc1" "-triple" "sparc-unknown-netbsd6.0.0" // SPARC-6: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // SPARC-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" // SPARC-6: "{{.*}}/usr/lib{{/|\\\\}}sparc{{/|\\\\}}crti.o" @@ -186,102 +186,102 @@ // SPARC-6: "-lm" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" // SPARC-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// SPARC64: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd" +// SPARC64: "-cc1" "-triple" "sparc64-unknown-netbsd" // SPARC64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // SPARC64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // SPARC64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // SPARC64: "-lm" "-lc" // SPARC64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// SPARC64-7: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd7.0.0" +// SPARC64-7: "-cc1" "-triple" "sparc64-unknown-netbsd7.0.0" // SPARC64-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // SPARC64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // SPARC64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // SPARC64-7: "-lm" "-lc" // SPARC64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// SPARC64-6: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd6.0.0" +// SPARC64-6: "-cc1" "-triple" "sparc64-unknown-netbsd6.0.0" // SPARC64-6: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // SPARC64-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // SPARC64-6: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lstdc++" // SPARC64-6: "-lm" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" // SPARC64-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// POWERPC: clang{{.*}}" "-cc1" "-triple" "powerpc-unknown-netbsd" +// POWERPC: "-cc1" "-triple" "powerpc-unknown-netbsd" // POWERPC: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // POWERPC: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" // POWERPC: "{{.*}}/usr/lib{{/|\\\\}}powerpc{{/|\\\\}}crti.o" // POWERPC: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // POWERPC: "-lm" "-lc" "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// POWERPC64: clang{{.*}}" "-cc1" "-triple" "powerpc64-unknown-netbsd" +// POWERPC64: "-cc1" "-triple" "powerpc64-unknown-netbsd" // POWERPC64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so" // POWERPC64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" // POWERPC64: "{{.*}}/usr/lib{{/|\\\\}}crti.o" // POWERPC64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // POWERPC64: "-lm" "-lc" "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-X86_64: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd" +// S-X86_64: "-cc1" "-triple" "x86_64-unknown-netbsd" // S-X86_64: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-X86_64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-X86_64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // S-X86_64: "-lm" "-lc" "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-X86_64-7: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd7.0.0" +// S-X86_64-7: "-cc1" "-triple" "x86_64-unknown-netbsd7.0.0" // S-X86_64-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-X86_64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-X86_64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // S-X86_64-7: "-lm" "-lc" "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-X86_64-6: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd6.0.0" +// S-X86_64-6: "-cc1" "-triple" "x86_64-unknown-netbsd6.0.0" // S-X86_64-6: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-X86_64-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lstdc++" // S-X86_64-6: "-lm" "-lc" "-lgcc_eh" "-lc" "-lgcc" // S-X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-ARM: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd6.0.0-eabi" +// S-ARM: "-cc1" "-triple" "armv5e-unknown-netbsd6.0.0-eabi" // S-ARM: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-ARM: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}eabi{{/|\\\\}}crti.o" // S-ARM: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lstdc++" // S-ARM: "-lm" "-lc" "-lgcc_eh" "-lc" "-lgcc" // S-ARM: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-ARM-7: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd7.0.0-eabi" +// S-ARM-7: "-cc1" "-triple" "armv5e-unknown-netbsd7.0.0-eabi" // S-ARM-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-ARM-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}eabi{{/|\\\\}}crti.o" // S-ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" "-lm" "-lc" // S-ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-AARCH64: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd" +// S-AARCH64: "-cc1" "-triple" "aarch64-unknown-netbsd" // S-AARCH64: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-AARCH64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // S-AARCH64: "-lm" "-lc" // S-AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-AARCH64-7: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd7.0.0" +// S-AARCH64-7: "-cc1" "-triple" "aarch64-unknown-netbsd7.0.0" // S-AARCH64-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-AARCH64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // S-AARCH64-7: "-lm" "-lc" // S-AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-AARCH64_BE: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd" +// S-AARCH64_BE: "-cc1" "-triple" "aarch64_be-unknown-netbsd" // S-AARCH64_BE: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-AARCH64_BE: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // S-AARCH64_BE: "-lm" "-lc" // S-AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-AARCH64_BE-7: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd7.0.0" +// S-AARCH64_BE-7: "-cc1" "-triple" "aarch64_be-unknown-netbsd7.0.0" // S-AARCH64_BE-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-AARCH64_BE-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // S-AARCH64_BE-7: "-lm" "-lc" // S-AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-SPARC: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd" +// S-SPARC: "-cc1" "-triple" "sparc-unknown-netbsd" // S-SPARC: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-SPARC: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" // S-SPARC: "{{.*}}/usr/lib{{/|\\\\}}sparc{{/|\\\\}}crti.o" @@ -289,7 +289,7 @@ // S-SPARC: "-lm" "-lc" // S-SPARC: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-SPARC-7: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd7.0.0" +// S-SPARC-7: "-cc1" "-triple" "sparc-unknown-netbsd7.0.0" // S-SPARC-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-SPARC-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" // S-SPARC-7: "{{.*}}/usr/lib{{/|\\\\}}sparc{{/|\\\\}}crti.o" @@ -297,7 +297,7 @@ // S-SPARC-7: "-lm" "-lc" // S-SPARC-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-SPARC-6: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd6.0.0" +// S-SPARC-6: "-cc1" "-triple" "sparc-unknown-netbsd6.0.0" // S-SPARC-6: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-SPARC-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" // S-SPARC-6: "{{.*}}/usr/lib{{/|\\\\}}sparc{{/|\\\\}}crti.o" @@ -305,35 +305,35 @@ // S-SPARC-6: "-lm" "-lc" "-lgcc_eh" "-lc" "-lgcc" // S-SPARC-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-SPARC64: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd" +// S-SPARC64: "-cc1" "-triple" "sparc64-unknown-netbsd" // S-SPARC64: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-SPARC64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-SPARC64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // S-SPARC64: "-lm" "-lc" // S-SPARC64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-SPARC64-7: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd7.0.0" +// S-SPARC64-7: "-cc1" "-triple" "sparc64-unknown-netbsd7.0.0" // S-SPARC64-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-SPARC64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-SPARC64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // S-SPARC64-7: "-lm" "-lc" // S-SPARC64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-SPARC64-6: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd6.0.0" +// S-SPARC64-6: "-cc1" "-triple" "sparc64-unknown-netbsd6.0.0" // S-SPARC64-6: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-SPARC64-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o" // S-SPARC64-6: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lstdc++" // S-SPARC64-6: "-lm" "-lc" "-lgcc_eh" "-lc" "-lgcc" // S-SPARC64-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-POWERPC: clang{{.*}}" "-cc1" "-triple" "powerpc-unknown-netbsd" +// S-POWERPC: "-cc1" "-triple" "powerpc-unknown-netbsd" // S-POWERPC: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-POWERPC: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" // S-POWERPC: "{{.*}}/usr/lib{{/|\\\\}}powerpc{{/|\\\\}}crti.o" // S-POWERPC: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" // S-POWERPC: "-lm" "-lc" "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" -// S-POWERPC64: clang{{.*}}" "-cc1" "-triple" "powerpc64-unknown-netbsd" +// S-POWERPC64: "-cc1" "-triple" "powerpc64-unknown-netbsd" // S-POWERPC64: ld{{.*}}" "--eh-frame-hdr" "-Bstatic" // S-POWERPC64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" // S-POWERPC64: "{{.*}}/usr/lib{{/|\\\\}}crti.o" diff --git a/clang/test/Driver/offloading-interoperability.c b/clang/test/Driver/offloading-interoperability.c index ce4cde45d38af..e7c68fad60d02 100644 --- a/clang/test/Driver/offloading-interoperability.c +++ b/clang/test/Driver/offloading-interoperability.c @@ -4,13 +4,13 @@ // // Verify that CUDA device commands do not get OpenMP flags. // -// RUN: %clang -no-canonical-prefixes -### -x cuda -target powerpc64le-linux-gnu -std=c++11 --cuda-gpu-arch=sm_35 -fopenmp=libomp %s 2>&1 \ -// RUN: | FileCheck %s --check-prefix NO-OPENMP-FLAGS-FOR-CUDA-DEVICE +// RUN: %clang -### -x cuda --target=powerpc64le-linux-gnu -std=c++11 --cuda-gpu-arch=sm_35 -fopenmp=libomp %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix NO-OPENMP-FLAGS-FOR-CUDA-DEVICE // -// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-LABEL:clang{{.*}}" "-cc1" "-triple" "nvptx64-nvidia-cuda" +// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE: "-cc1" "-triple" "nvptx64-nvidia-cuda" // NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NOT: -fopenmp // NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NEXT: ptxas" "-m64" // NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NEXT: fatbinary"{{( "--cuda")?}} "-64" -// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-LABEL:clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux-gnu" +// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NEXT: "-cc1" "-triple" "powerpc64le-unknown-linux-gnu" // NO-OPENMP-FLAGS-FOR-CUDA-DEVICE: -fopenmp // NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NEXT: {{ld(.exe)?"}} {{.*}}"-m" "elf64lppc" diff --git a/clang/test/Driver/openmp-offload-gpu-new.c b/clang/test/Driver/openmp-offload-gpu-new.c index d1bd497f65ff4..8eb197af1fd41 100644 --- a/clang/test/Driver/openmp-offload-gpu-new.c +++ b/clang/test/Driver/openmp-offload-gpu-new.c @@ -40,13 +40,16 @@ // CHECK-PHASES: 14: clang-linker-wrapper, {13}, image, (host-openmp) // RUN: %clang -### --target=x86_64-unknown-linux-gnu -ccc-print-bindings -fopenmp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target=nvptx64-nvidia-cuda -march=sm_52 -nogpulib %s 2>&1 | FileCheck %s --check-prefix=CHECK-BINDINGS -// CHECK-BINDINGS: "x86_64-unknown-linux-gnu" - "clang", inputs: ["[[INPUT:.*]]"], output: "[[HOST_BC:.*]]" -// CHECK-BINDINGS: "nvptx64-nvidia-cuda" - "clang", inputs: ["[[INPUT]]", "[[HOST_BC]]"], output: "[[DEVICE_BC:.*]]" -// CHECK-BINDINGS: "nvptx64-nvidia-cuda" - "NVPTX::Assembler", inputs: ["[[DEVICE_BC]]"], output: "[[DEVICE_OBJ:.*]]" -// CHECK-BINDINGS: "x86_64-unknown-linux-gnu" - "Offload::Packager", inputs: ["[[DEVICE_OBJ]]"], output: "[[BINARY:.*]]" -// CHECK-BINDINGS: "x86_64-unknown-linux-gnu" - "clang", inputs: ["[[HOST_BC]]", "[[BINARY]]"], output: "[[HOST_OBJ:.*]]" +// CHECK-BINDINGS: "x86_64-unknown-linux-gnu" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[HOST_BC:.+]]" +// CHECK-BINDINGS: "nvptx64-nvidia-cuda" - "clang", inputs: ["[[INPUT]]", "[[HOST_BC]]"], output: "[[DEVICE_BC:.+]]" +// CHECK-BINDINGS: "nvptx64-nvidia-cuda" - "NVPTX::Assembler", inputs: ["[[DEVICE_BC]]"], output: "[[DEVICE_OBJ:.+]]" +// CHECK-BINDINGS: "x86_64-unknown-linux-gnu" - "Offload::Packager", inputs: ["[[DEVICE_OBJ]]"], output: "[[BINARY:.+.out]]" +// CHECK-BINDINGS: "x86_64-unknown-linux-gnu" - "clang", inputs: ["[[HOST_BC]]", "[[BINARY]]"], output: "[[HOST_OBJ:.+]]" // CHECK-BINDINGS: "x86_64-unknown-linux-gnu" - "Offload::Linker", inputs: ["[[HOST_OBJ]]"], output: "a.out" +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -ccc-print-bindings -fopenmp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target=nvptx64-nvidia-cuda -march=sm_52 -nogpulib -save-temps %s 2>&1 | FileCheck %s --check-prefix=CHECK-TEMP-BINDINGS +// CHECK-TEMP-BINDINGS: "x86_64-unknown-linux-gnu" - "Offload::Packager", inputs: ["[[DEVICE_OBJ:.+]]"], output: "[[BINARY:.+.out]]" + // RUN: %clang -### --target=x86_64-unknown-linux-gnu -ccc-print-bindings -fopenmp -fopenmp-targets=nvptx64-nvidia-cuda --offload-arch=sm_52 --offload-arch=sm_70 -nogpulib %s 2>&1 | FileCheck %s --check-prefix=CHECK-ARCH-BINDINGS // CHECK-ARCH-BINDINGS: "x86_64-unknown-linux-gnu" - "clang", inputs: ["[[INPUT:.*]]"], output: "[[HOST_BC:.*]]" // CHECK-ARCH-BINDINGS: "nvptx64-nvidia-cuda" - "clang", inputs: ["[[INPUT]]", "[[HOST_BC]]"], output: "[[DEVICE_BC_SM_52:.*]]" diff --git a/clang/test/Driver/openmp-offload.c b/clang/test/Driver/openmp-offload.c index 78fa4a2a73da1..89247604d07cd 100644 --- a/clang/test/Driver/openmp-offload.c +++ b/clang/test/Driver/openmp-offload.c @@ -39,7 +39,7 @@ /// ########################################################################### /// Check -Xopenmp-target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 is passed when compiling for the device. -// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 %s 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-EQ-TARGET %s // CHK-FOPENMP-EQ-TARGET: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-device" @@ -47,7 +47,7 @@ /// ########################################################################### /// Check -Xopenmp-target -mcpu=pwr7 is passed when compiling for the device. -// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target -mcpu=pwr7 %s 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target -mcpu=pwr7 %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-TARGET %s // CHK-FOPENMP-TARGET: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-device" @@ -55,7 +55,7 @@ /// ########################################################################## /// Check -mcpu=pwr7 is passed to the same triple. -// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -target powerpc64le-ibm-linux-gnu -mcpu=pwr7 %s 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu --target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-MCPU-TO-SAME-TRIPLE %s // CHK-FOPENMP-MCPU-TO-SAME-TRIPLE: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-device" @@ -63,7 +63,7 @@ /// ########################################################################## /// Check -march=pwr7 is NOT passed to nvptx64-nvidia-cuda. -// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -target powerpc64le-ibm-linux-gnu -march=pwr7 %s 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda --target=powerpc64le-ibm-linux-gnu -march=pwr7 %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-MARCH-TO-GPU %s // CHK-FOPENMP-MARCH-TO-GPU-NOT: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-device" @@ -71,7 +71,7 @@ /// ########################################################################### /// Check -march=pwr7 is NOT passed to x86_64-unknown-linux-gnu. -// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=x86_64-unknown-linux-gnu -target powerpc64le-ibm-linux-gnu -march=pwr7 %s 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=x86_64-unknown-linux-gnu --target=powerpc64le-ibm-linux-gnu -march=pwr7 %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-MARCH-TO-X86 %s // CHK-FOPENMP-MARCH-TO-X86-NOT: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-device" @@ -79,7 +79,7 @@ /// ########################################################################### /// Check -Xopenmp-target triggers error when multiple triples are used. -// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu,powerpc64le-unknown-linux-gnu -Xopenmp-target -mcpu=pwr8 %s 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu,powerpc64le-unknown-linux-gnu -Xopenmp-target -mcpu=pwr8 %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-TARGET-AMBIGUOUS-ERROR %s // CHK-FOPENMP-TARGET-AMBIGUOUS-ERROR: clang{{.*}} error: cannot deduce implicit triple value for -Xopenmp-target, specify triple using -Xopenmp-target= @@ -87,7 +87,7 @@ /// ########################################################################### /// Check -Xopenmp-target triggers error when an option requiring arguments is passed to it. -// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target -Xopenmp-target -mcpu=pwr8 %s 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target -Xopenmp-target -mcpu=pwr8 %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-TARGET-NESTED-ERROR %s // CHK-FOPENMP-TARGET-NESTED-ERROR: clang{{.*}} error: invalid -Xopenmp-target argument: '-Xopenmp-target -Xopenmp-target', options requiring arguments are unsupported @@ -98,7 +98,7 @@ /// We should have an offload action joining the host compile and device /// preprocessor and another one joining the device linking outputs to the host /// action. -// RUN: %clang -ccc-print-phases -fopenmp=libomp -fno-openmp-new-driver -target powerpc64le-ibm-linux-gnu -fopenmp-targets=x86_64-pc-linux-gnu %s 2>&1 \ +// RUN: %clang -ccc-print-phases -fopenmp=libomp -fno-openmp-new-driver --target=powerpc64le-ibm-linux-gnu -fopenmp-targets=x86_64-pc-linux-gnu %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-PHASES %s // CHK-PHASES: 0: input, "[[INPUT:.+\.c]]", c, (host-openmp) // CHK-PHASES: 1: preprocessor, {0}, cpp-output, (host-openmp) @@ -122,7 +122,7 @@ /// Check the phases when using multiple targets. Here we also add a library to /// make sure it is treated as input by the device. -// RUN: %clang -ccc-print-phases -lsomelib -fopenmp=libomp -fno-openmp-new-driver -target powerpc64-ibm-linux-gnu -fopenmp-targets=x86_64-pc-linux-gnu,powerpc64-ibm-linux-gnu %s 2>&1 \ +// RUN: %clang -ccc-print-phases -lsomelib -fopenmp=libomp -fno-openmp-new-driver --target=powerpc64-ibm-linux-gnu -fopenmp-targets=x86_64-pc-linux-gnu,powerpc64-ibm-linux-gnu %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-PHASES-LIB %s // CHK-PHASES-LIB: 0: input, "somelib", object, (host-openmp) // CHK-PHASES-LIB: 1: input, "[[INPUT:.+\.c]]", c, (host-openmp) @@ -157,7 +157,7 @@ /// Check the phases when using multiple targets and multiple source files // RUN: echo " " > %t.c -// RUN: %clang -ccc-print-phases -lsomelib -fopenmp=libomp -fno-openmp-new-driver -target powerpc64-ibm-linux-gnu -fopenmp-targets=x86_64-pc-linux-gnu,powerpc64-ibm-linux-gnu %s %t.c 2>&1 \ +// RUN: %clang -ccc-print-phases -lsomelib -fopenmp=libomp -fno-openmp-new-driver --target=powerpc64-ibm-linux-gnu -fopenmp-targets=x86_64-pc-linux-gnu,powerpc64-ibm-linux-gnu %s %t.c 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-PHASES-FILES %s // CHK-PHASES-FILES: 0: input, "somelib", object, (host-openmp) // CHK-PHASES-FILES: 1: input, "[[INPUT1:.+\.c]]", c, (host-openmp) @@ -209,7 +209,7 @@ /// Check the phases graph when using a single GPU target, and check the OpenMP /// and CUDA phases are articulated correctly. -// RUN: %clang -ccc-print-phases -fopenmp=libomp -fno-openmp-new-driver -target powerpc64le-ibm-linux-gnu -fopenmp-targets=nvptx64-nvidia-cuda -x cuda %s 2>&1 \ +// RUN: %clang -ccc-print-phases -fopenmp=libomp -fno-openmp-new-driver --target=powerpc64le-ibm-linux-gnu -fopenmp-targets=nvptx64-nvidia-cuda -x cuda %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-PHASES-WITH-CUDA %s // CHK-PHASES-WITH-CUDA: 0: input, "[[INPUT:.+\.c]]", cuda, (host-cuda-openmp) // CHK-PHASES-WITH-CUDA: 1: preprocessor, {0}, cuda-cpp-output, (host-cuda-openmp) @@ -250,27 +250,27 @@ /// the target code generation to gather information about which declaration /// really need to be emitted. /// -// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -o %t.out -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -no-canonical-prefixes 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -o %t.out --target=powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-COMMANDS %s -// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -o %t.out -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -save-temps -no-canonical-prefixes 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -o %t.out --target=powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -save-temps 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-COMMANDS-ST %s // // Generate host BC file and host object. // -// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-disable-llvm-passes" +// CHK-COMMANDS: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-disable-llvm-passes" // CHK-COMMANDS-SAME: "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" // CHK-COMMANDS-SAME: "-o" " // CHK-COMMANDS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "c" " // CHK-COMMANDS-SAME: [[INPUT:[^\\/]+\.c]]" -// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[HOSTBC]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS-ST: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[HOSTPP:[^\\/]+\.i]]" "-x" "c" " // CHK-COMMANDS-ST-SAME: [[INPUT:[^\\/]+\.c]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " +// CHK-COMMANDS-ST: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS-ST: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[HOSTASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[HOSTBC]]" // CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "{{.*}}[[HOSTASM]]" @@ -278,36 +278,36 @@ // // Compile for the powerpc device. // -// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" +// CHK-COMMANDS: "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" // CHK-COMMANDS-SAME: "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-COMMANDS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" // CHK-COMMANDS: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-COMMANDS-SAME: [[T1BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T1OBJ]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS-ST: "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T1PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-COMMANDS-ST: "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS-ST: "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " +// CHK-COMMANDS-ST: "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]" // CHK-COMMANDS-ST: ld{{(\.exe)?}}" {{.*}}"-shared" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T1BIN:[^\\/]+\.out-openmp-powerpc64le-ibm-linux-gnu]]" {{.*}}"{{.*}}[[T1OBJ]]" // // Compile for the x86 device. // -// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" +// CHK-COMMANDS: "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" // CHK-COMMANDS-SAME: "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-COMMANDS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" // CHK-COMMANDS: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-COMMANDS-SAME: [[T2BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T2OBJ]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS-ST: "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T2PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-COMMANDS-ST: "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS-ST: "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " +// CHK-COMMANDS-ST: "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]" // CHK-COMMANDS-ST: ld{{(\.exe)?}}" {{.*}}"-shared" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T2BIN:[^\\/]+\.out-openmp-x86_64-pc-linux-gnu]]" {{.*}}"{{.*}}[[T2OBJ]]" @@ -317,13 +317,13 @@ // // CHK-COMMANDS: clang-offload-wrapper{{(\.exe)?}}" "-target" "powerpc64le-unknown-linux" {{.*}}"-o" " // CHK-COMMANDS-SAME: [[WRAPPERBC:[^\\/]+\.bc]]" "{{.*}}[[T1BIN]]" "{{.*}}[[T2BIN]]" -// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-SAME: [[WRAPPEROBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[WRAPPERBC]]" // CHK-COMMANDS-ST: clang-offload-wrapper{{(\.exe)?}}" "-target" "powerpc64le-unknown-linux" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[WRAPPERBC:[^\\/]+\.bc]]" "{{.*}}[[T1BIN]]" "{{.*}}[[T2BIN]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-COMMANDS-ST: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[WRAPPERASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[WRAPPERBC]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" " +// CHK-COMMANDS-ST: "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[WRAPPEROBJ:[^\\/]+\.o]]" "{{.*}}[[WRAPPERASM]]" // @@ -337,7 +337,7 @@ /// ########################################################################### /// Check separate compilation with offloading - bundling actions -// RUN: %clang -### -ccc-print-phases -fopenmp=libomp -fno-openmp-new-driver -c -o %t.o %S/Input/in.so -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -no-canonical-prefixes 2>&1 \ +// RUN: %clang -### -ccc-print-phases -fopenmp=libomp -fno-openmp-new-driver -c %S/Input/in.so -lsomelib --target=powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-BUACTIONS %s // CHK-BUACTIONS: 0: input, "[[INPUT:.+\.c]]", c, (host-openmp) @@ -365,7 +365,7 @@ /// Check separate compilation with offloading - unbundling actions // RUN: touch %t.i -// RUN: %clang -### -ccc-print-phases -fopenmp=libomp -fno-openmp-new-driver -o %t.out -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i -no-canonical-prefixes 2>&1 \ +// RUN: %clang -### -ccc-print-phases -fopenmp=libomp -fno-openmp-new-driver -o %t.out -lsomelib --target=powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-UBACTIONS %s // CHK-UBACTIONS: 0: input, "somelib", object, (host-openmp) @@ -397,7 +397,7 @@ /// Check separate compilation with offloading - unbundling/bundling actions // RUN: touch %t.i -// RUN: %clang -### -ccc-print-phases -fopenmp=libomp -fno-openmp-new-driver -c -o %t.o -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i -no-canonical-prefixes 2>&1 \ +// RUN: %clang -### -ccc-print-phases -fopenmp=libomp -fno-openmp-new-driver -c -lsomelib --target=powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-UBUACTIONS %s // CHK-UBUACTIONS: 0: input, "[[INPUT:.+\.i]]", cpp-output, (host-openmp) @@ -420,54 +420,54 @@ /// ########################################################################### /// Check separate compilation with offloading - bundling jobs construct -// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -c -o %t.o -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -no-canonical-prefixes 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -c -lsomelib --target=powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-BUJOBS %s -// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -c -o %t.o -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -save-temps -no-canonical-prefixes 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -c -lsomelib --target=powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -save-temps 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-BUJOBS-ST %s // Create host BC. -// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " +// CHK-BUJOBS: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " // CHK-BUJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "c" " // CHK-BUJOBS-SAME: [[INPUT:[^\\/]+\.c]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS-ST: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[HOSTPP:[^\\/]+\.i]]" "-x" "c" " // CHK-BUJOBS-ST-SAME: [[INPUT:[^\\/]+\.c]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " +// CHK-BUJOBS-ST: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" // Create target 1 object. -// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-BUJOBS: "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-BUJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS-ST: "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T1PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-BUJOBS-ST: "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS-ST: "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " +// CHK-BUJOBS-ST: "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]" // Create target 2 object. -// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-BUJOBS: "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-BUJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS-ST: "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T2PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-BUJOBS-ST: "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS-ST: "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " +// CHK-BUJOBS-ST: "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]" // Create host object and bundle. -// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[HOSTBC]]" // CHK-BUJOBS: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le-unknown-linux" "-output= // CHK-BUJOBS-SAME: [[RES:[^\\/]+\.o]]" "-input={{.*}}[[T1OBJ]]" "-input={{.*}}[[T2OBJ]]" "-input={{.*}}[[HOSTOBJ]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS-ST: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[HOSTASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[HOSTBC]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" " +// CHK-BUJOBS-ST: "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "{{.*}}[[HOSTASM]]" // CHK-BUJOBS-ST: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le-unknown-linux" "-output= // CHK-BUJOBS-ST-SAME: [[RES:[^\\/]+\.o]]" "-input={{.*}}[[T1OBJ]]" "-input={{.*}}[[T2OBJ]]" "-input={{.*}}[[HOSTOBJ]]" @@ -476,14 +476,14 @@ /// Check separate compilation with offloading - unbundling jobs construct // RUN: touch %t.i -// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -o %t.out -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i -no-canonical-prefixes 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -o %t.out -lsomelib --target=powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-UBJOBS %s -// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -o %t.out -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i -save-temps -no-canonical-prefixes 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -o %t.out -lsomelib --target=powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i -save-temps 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-UBJOBS-ST %s // RUN: touch %t.o -// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -o %t.out -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.o -no-canonical-prefixes 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -o %t.out -lsomelib --target=powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.o 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-UBJOBS2 %s -// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -o %t.out -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.o %S/Inputs/in.so -save-temps -no-canonical-prefixes 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -o %t.out -lsomelib --target=powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.o %S/Inputs/in.so -save-temps 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-UBJOBS2-ST %s // Unbundle and create host BC. @@ -492,46 +492,46 @@ // CHK-UBJOBS-SAME: [[HOSTPP:[^\\/]+\.i]]" "-output= // CHK-UBJOBS-SAME: [[T1PP:[^\\/]+\.i]]" "-output= // CHK-UBJOBS-SAME: [[T2PP:[^\\/]+\.i]]" "-unbundle" "-allow-missing-bundles" -// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " +// CHK-UBJOBS: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" -// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBJOBS: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[HOSTBC]]" // CHK-UBJOBS-ST: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le-unknown-linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-input= // CHK-UBJOBS-ST-SAME: [[INPUT:[^\\/]+.tmp\.i]]" "-output= // CHK-UBJOBS-ST-SAME: [[HOSTPP:[^\\/]+linux\.i]]" "-output= // CHK-UBJOBS-ST-SAME: [[T1PP:[^\\/]+gnu\.i]]" "-output= // CHK-UBJOBS-ST-SAME: [[T2PP:[^\\/]+gnu\.i]]" "-unbundle" "-allow-missing-bundles" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " +// CHK-UBJOBS-ST: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBJOBS-ST: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[HOSTASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[HOSTBC]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" " +// CHK-UBJOBS-ST: "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "{{.*}}[[HOSTASM]]" // Create target 1 object. -// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBJOBS: "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" // CHK-UBJOBS: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[T1BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T1OBJ]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBJOBS-ST: "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBJOBS-ST: "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " +// CHK-UBJOBS-ST: "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]" // CHK-UBJOBS-ST: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T1BIN:[^\\/]+\.out-openmp-powerpc64le-ibm-linux-gnu]]" {{.*}}"{{.*}}[[T1OBJ]]" // Create target 2 object. -// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBJOBS: "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" // CHK-UBJOBS: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[T2BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T2OBJ]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBJOBS-ST: "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBJOBS-ST: "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " +// CHK-UBJOBS-ST: "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]" // CHK-UBJOBS-ST: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T2BIN:[^\\/]+\.out-openmp-x86_64-pc-linux-gnu]]" {{.*}}"{{.*}}[[T2OBJ]]" @@ -539,13 +539,13 @@ // Create wrapper BC file and wrapper object. // CHK-UBJOBS: clang-offload-wrapper{{(\.exe)?}}" "-target" "powerpc64le-unknown-linux" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[WRAPPERBC:[^\\/]+\.bc]]" "{{.*}}[[T1BIN]]" "{{.*}}[[T2BIN]]" -// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBJOBS: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[WRAPPEROBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[WRAPPERBC]]" // CHK-UBJOBS-ST: clang-offload-wrapper{{(\.exe)?}}" "-target" "powerpc64le-unknown-linux" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[WRAPPERBC:[^\\/]+\.bc]]" "{{.*}}[[T1BIN]]" "{{.*}}[[T2BIN]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBJOBS-ST: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[WRAPPERASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[WRAPPERBC]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" " +// CHK-UBJOBS-ST: "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[WRAPPEROBJ:[^\\/]+\.o]]" "{{.*}}[[WRAPPERASM]]" // Create binary. @@ -566,7 +566,7 @@ // CHK-UBJOBS2-SAME: [[T2BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T2OBJ]]" // CHK-UBJOBS2: clang-offload-wrapper{{(\.exe)?}}" "-target" "powerpc64le-unknown-linux" {{.*}}"-o" " // CHK-UBJOBS2-SAME: [[WRAPPERBC:[^\\/]+\.bc]]" "{{.*}}[[T1BIN]]" "{{.*}}[[T2BIN]]" -// CHK-UBJOBS2: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBJOBS2: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS2-SAME: [[WRAPPEROBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[WRAPPERBC]]" // CHK-UBJOBS2: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-UBJOBS2-SAME: [[HOSTBIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[HOSTOBJ]]" "{{.*}}[[WRAPPEROBJ]]" @@ -583,9 +583,9 @@ // CHK-UBJOBS2-ST-SAME: [[T2BIN:[^\\/]+\.out-openmp-x86_64-pc-linux-gnu]]" {{.*}}"{{.*}}[[T2OBJ]]" // CHK-UBJOBS2-ST: clang-offload-wrapper{{(\.exe)?}}" "-target" "powerpc64le-unknown-linux" {{.*}}"-o" " // CHK-UBJOBS2-ST-SAME: [[WRAPPERBC:[^\\/]+\.bc]]" "{{.*}}[[T1BIN]]" "{{.*}}[[T2BIN]]" -// CHK-UBJOBS2-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBJOBS2-ST: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS2-ST-SAME: [[WRAPPERASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[WRAPPERBC]]" -// CHK-UBJOBS2-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" " +// CHK-UBJOBS2-ST: "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" " // CHK-UBJOBS2-ST-SAME: [[WRAPPEROBJ:[^\\/]+\.o]]" "{{.*}}[[WRAPPERASM]]" // CHK-UBJOBS2-ST: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-UBJOBS2-ST-SAME: [[HOSTBIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[HOSTOBJ]]" "{{.*}}[[WRAPPEROBJ]]" @@ -595,9 +595,9 @@ /// Check separate compilation with offloading - unbundling/bundling jobs /// construct // RUN: touch %t.i -// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -c %t.o -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i -no-canonical-prefixes 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -c %t.o -lsomelib --target=powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-UBUJOBS %s -// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -c %t.o -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i -save-temps -no-canonical-prefixes 2>&1 \ +// RUN: %clang -### -fopenmp=libomp -fno-openmp-new-driver -c %t.o -lsomelib --target=powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i -save-temps 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-UBUJOBS-ST %s // Unbundle and create host BC. @@ -606,7 +606,7 @@ // CHK-UBUJOBS-SAME: [[HOSTPP:[^\\/]+\.i]]" "-output= // CHK-UBUJOBS-SAME: [[T1PP:[^\\/]+\.i]]" "-output= // CHK-UBUJOBS-SAME: [[T2PP:[^\\/]+\.i]]" "-unbundle" "-allow-missing-bundles" -// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " +// CHK-UBUJOBS: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " // CHK-UBUJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" // CHK-UBUJOBS-ST: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le-unknown-linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-input= @@ -614,37 +614,37 @@ // CHK-UBUJOBS-ST-SAME: [[HOSTPP:[^\\/]+linux\.i]]" "-output= // CHK-UBUJOBS-ST-SAME: [[T1PP:[^\\/]+gnu\.i]]" "-output= // CHK-UBUJOBS-ST-SAME: [[T2PP:[^\\/]+gnu\.i]]" "-unbundle" "-allow-missing-bundles" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " +// CHK-UBUJOBS-ST: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-disable-llvm-passes" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" // Create target 1 object. -// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBUJOBS: "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-UBUJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBUJOBS-ST: "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBUJOBS-ST: "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " +// CHK-UBUJOBS-ST: "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]" // Create target 2 object. -// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBUJOBS: "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-UBUJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBUJOBS-ST: "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBUJOBS-ST: "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " +// CHK-UBUJOBS-ST: "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]" // Create binary. -// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBUJOBS: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBUJOBS-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[HOSTBC]]" // CHK-UBUJOBS: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le-unknown-linux" "-output= // CHK-UBUJOBS-SAME: [[RES:[^\\/]+\.o]]" "-input={{.*}}[[T1OBJ]]" "-input={{.*}}[[T2OBJ]]" "-input={{.*}}[[HOSTOBJ]]" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-UBUJOBS-ST: "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[HOSTASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[HOSTBC]]" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" " +// CHK-UBUJOBS-ST: "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "{{.*}}[[HOSTASM]]" // CHK-UBUJOBS-ST: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le-unknown-linux" "-output= // CHK-UBUJOBS-ST-SAME: [[RES:[^\\/]+\.o]]" "-input={{.*}}[[T1OBJ]]" "-input={{.*}}[[T2OBJ]]" "-input={{.*}}[[HOSTOBJ]]" @@ -652,13 +652,13 @@ /// ########################################################################### /// Check -fopenmp-is-device is passed when compiling for the device. -// RUN: %clang -### -no-canonical-prefixes -target powerpc64le-linux -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu %s 2>&1 \ +// RUN: %clang -### --target=powerpc64le-linux -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-IS-DEVICE %s -// CHK-FOPENMP-IS-DEVICE: clang{{.*}} "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" {{.*}}.c" +// CHK-FOPENMP-IS-DEVICE: "-cc1"{{.*}} "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" {{.*}}.c" /// Check arguments to the linker wrapper -// RUN: %clang -### -no-canonical-prefixes -target powerpc64le-linux -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -fopenmp-new-driver %s 2>&1 \ +// RUN: %clang -### --target=powerpc64le-linux -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -fopenmp-new-driver %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-NEW-DRIVER %s // CHK-NEW-DRIVER: clang-linker-wrapper{{.*}}"-host-triple" "powerpc64le-unknown-linux"{{.*}}--{{.*}}"-lomp"{{.*}}"-lomptarget" diff --git a/clang/test/Driver/print-diagnostic-options.c b/clang/test/Driver/print-diagnostic-options.c new file mode 100644 index 0000000000000..fc6d1bf2eff53 --- /dev/null +++ b/clang/test/Driver/print-diagnostic-options.c @@ -0,0 +1,13 @@ +// Test that -print-diagnostic-options prints warning groups and disablers + +// RUN: %clang -print-diagnostic-options | FileCheck %s + +// CHECK: -W +// CHECK: -Wno- +// CHECK: -W#pragma-messages +// CHECK: -Wno-#pragma-messages +// CHECK: -W#warnings +// CHECK: -Wabi +// CHECK: -Wno-abi +// CHECK: -Wall +// CHECK: -Wno-all diff --git a/clang/test/Driver/rewrite-legacy-objc.m b/clang/test/Driver/rewrite-legacy-objc.m index 3fd35b1c91d5d..413a7a7a61f05 100644 --- a/clang/test/Driver/rewrite-legacy-objc.m +++ b/clang/test/Driver/rewrite-legacy-objc.m @@ -1,13 +1,13 @@ -// RUN: %clang -no-canonical-prefixes -target x86_64-apple-macosx10.7.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \ +// RUN: %clang --target=x86_64-apple-macosx10.7.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \ // RUN: FileCheck -check-prefix=TEST0 %s -// TEST0: clang{{.*}}" "-cc1" +// TEST0: "-cc1" // TEST0: "-rewrite-objc" // FIXME: CHECK-NOT is broken somehow, it doesn't work here. Check adjacency instead. // TEST0: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fmax-type-align=16" // TEST0: rewrite-legacy-objc.m" -// RUN: %clang -no-canonical-prefixes -target i386-apple-macosx10.9.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \ +// RUN: %clang --target=i386-apple-macosx10.9.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \ // RUN: FileCheck -check-prefix=TEST1 %s -// RUN: %clang -no-canonical-prefixes -target i386-apple-macosx10.6.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \ +// RUN: %clang --target=i386-apple-macosx10.6.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \ // RUN: FileCheck -check-prefix=TEST2 %s // TEST1: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16" // TEST2: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16" diff --git a/clang/test/Driver/rewrite-objc.m b/clang/test/Driver/rewrite-objc.m index 47532311fa0f0..de3577a770df8 100644 --- a/clang/test/Driver/rewrite-objc.m +++ b/clang/test/Driver/rewrite-objc.m @@ -1,6 +1,5 @@ -// RUN: %clang -no-canonical-prefixes -target x86_64-apple-macosx10.7.0 -rewrite-objc %s -o - -### 2>&1 | \ +// RUN: %clang --target=x86_64-apple-macosx10.7.0 -rewrite-objc %s -o - -### 2>&1 | \ // RUN: FileCheck -check-prefix=TEST0 %s -// TEST0: clang{{.*}}" "-cc1" -// TEST0: "-rewrite-objc" +// TEST0: "-cc1" {{.*}} "-rewrite-objc" // FIXME: CHECK-NOT is broken somehow, it doesn't work here. Check adjacency instead. // TEST0: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fmax-type-align=16" diff --git a/clang/test/Driver/riscv64-toolchain.c b/clang/test/Driver/riscv64-toolchain.c index ec3707412e2aa..78ce26c181284 100644 --- a/clang/test/Driver/riscv64-toolchain.c +++ b/clang/test/Driver/riscv64-toolchain.c @@ -15,7 +15,7 @@ // In the below tests, --rtlib=platform is used so that the driver ignores // the configure-time CLANG_DEFAULT_RTLIB option when choosing the runtime lib -// RUN: %clang -### %s -fuse-ld= \ +// RUN: env "PATH=" %clang -### %s -fuse-ld= \ // RUN: --target=riscv64-unknown-elf --rtlib=platform \ // RUN: --gcc-toolchain=%S/Inputs/basic_riscv64_tree \ // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf 2>&1 -no-pie \ @@ -30,7 +30,7 @@ // C-RV64-BAREMETAL-LP64: "--start-group" "-lc" "-lgloss" "--end-group" "-lgcc" // C-RV64-BAREMETAL-LP64: "{{.*}}/Inputs/basic_riscv64_tree/lib/gcc/riscv64-unknown-elf/8.0.1{{/|\\\\}}crtend.o" -// RUN: %clang -### %s -fuse-ld= \ +// RUN: env "PATH=" %clang -### %s -fuse-ld= \ // RUN: --target=riscv64-unknown-elf --rtlib=platform \ // RUN: --sysroot= \ // RUN: --gcc-toolchain=%S/Inputs/basic_riscv64_tree 2>&1 \ @@ -44,7 +44,7 @@ // C-RV64-BAREMETAL-NOSYSROOT-LP64: "--start-group" "-lc" "-lgloss" "--end-group" "-lgcc" // C-RV64-BAREMETAL-NOSYSROOT-LP64: "{{.*}}/Inputs/basic_riscv64_tree/lib/gcc/riscv64-unknown-elf/8.0.1{{/|\\\\}}crtend.o" -// RUN: %clangxx -### %s -fuse-ld= \ +// RUN: env "PATH=" %clangxx -### %s -fuse-ld= \ // RUN: --target=riscv64-unknown-elf -stdlib=libstdc++ --rtlib=platform \ // RUN: --gcc-toolchain=%S/Inputs/basic_riscv64_tree \ // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf 2>&1 \ @@ -60,7 +60,7 @@ // CXX-RV64-BAREMETAL-LP64: "-lstdc++" "--start-group" "-lc" "-lgloss" "--end-group" "-lgcc" // CXX-RV64-BAREMETAL-LP64: "{{.*}}/Inputs/basic_riscv64_tree/lib/gcc/riscv64-unknown-elf/8.0.1{{/|\\\\}}crtend.o" -// RUN: %clangxx -### %s -fuse-ld= \ +// RUN: env "PATH=" %clangxx -### %s -fuse-ld= \ // RUN: --target=riscv64-unknown-elf -stdlib=libstdc++ --rtlib=platform \ // RUN: --sysroot= \ // RUN: --gcc-toolchain=%S/Inputs/basic_riscv64_tree 2>&1 \ @@ -75,7 +75,7 @@ // CXX-RV64-BAREMETAL-NOSYSROOT-LP64: "-lstdc++" "--start-group" "-lc" "-lgloss" "--end-group" "-lgcc" // CXX-RV64-BAREMETAL-NOSYSROOT-LP64: "{{.*}}/Inputs/basic_riscv64_tree/lib/gcc/riscv64-unknown-elf/8.0.1{{/|\\\\}}crtend.o" -// RUN: %clang -### %s -fuse-ld= -no-pie \ +// RUN: env "PATH=" %clang -### %s -fuse-ld= -no-pie \ // RUN: --target=riscv64-unknown-linux-gnu --rtlib=platform -mabi=lp64 \ // RUN: --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \ // RUN: --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \ @@ -90,7 +90,7 @@ // C-RV64-LINUX-MULTI-LP64: "-L{{.*}}/Inputs/multilib_riscv_linux_sdk/sysroot/lib64/lp64" // C-RV64-LINUX-MULTI-LP64: "-L{{.*}}/Inputs/multilib_riscv_linux_sdk/sysroot/usr/lib64/lp64" -// RUN: %clang -### %s -fuse-ld=ld -no-pie \ +// RUN: env "PATH=" %clang -### %s -fuse-ld=ld -no-pie \ // RUN: --target=riscv64-unknown-linux-gnu --rtlib=platform -march=rv64imafd \ // RUN: --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \ // RUN: --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \ diff --git a/clang/test/Driver/sanitizer-ld.c b/clang/test/Driver/sanitizer-ld.c index ea58a8069200b..423ce8beaa84e 100644 --- a/clang/test/Driver/sanitizer-ld.c +++ b/clang/test/Driver/sanitizer-ld.c @@ -15,6 +15,7 @@ // CHECK-ASAN-LINUX: "-lpthread" // CHECK-ASAN-LINUX: "-lrt" // CHECK-ASAN-LINUX: "-ldl" +// CHECK-ASAN-LINUX: "-lresolv" // RUN: %clang -fsanitize=address -fno-sanitize-link-runtime -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -69,6 +70,7 @@ // CHECK-SHARED-ASAN-LINUX-NOT: "-lpthread" // CHECK-SHARED-ASAN-LINUX-NOT: "-lrt" // CHECK-SHARED-ASAN-LINUX-NOT: "-ldl" +// CHECK-SHARED-ASAN-LINUX-NOT: "-lresolv" // CHECK-SHARED-ASAN-LINUX-NOT: "--export-dynamic" // CHECK-SHARED-ASAN-LINUX-NOT: "--dynamic-list" @@ -86,6 +88,7 @@ // CHECK-DSO-SHARED-ASAN-LINUX-NOT: "-lpthread" // CHECK-DSO-SHARED-ASAN-LINUX-NOT: "-lrt" // CHECK-DSO-SHARED-ASAN-LINUX-NOT: "-ldl" +// CHECK-DSO-SHARED-ASAN-LINUX-NOT: "-lresolv" // CHECK-DSO-SHARED-ASAN-LINUX-NOT: "--export-dynamic" // CHECK-DSO-SHARED-ASAN-LINUX-NOT: "--dynamic-list" @@ -130,6 +133,7 @@ // CHECK-ASAN-LINUX-CXX: "-lpthread" // CHECK-ASAN-LINUX-CXX: "-lrt" // CHECK-ASAN-LINUX-CXX: "-ldl" +// CHECK-ASAN-LINUX-CXX: "-lresolv" // RUN: %clang -### %s -o /dev/null -fsanitize=address \ // RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform \ @@ -169,8 +173,10 @@ // CHECK-ASAN-ANDROID: "-pie" // CHECK-ASAN-ANDROID-NOT: "-lc" // CHECK-ASAN-ANDROID-NOT: "-lpthread" +// CHECK-ASAN-ANDROID-NOT: "-lresolv" // CHECK-ASAN-ANDROID: libclang_rt.asan-arm-android.so" // CHECK-ASAN-ANDROID-NOT: "-lpthread" +// CHECK-ASAN-ANDROID-NOT: "-lresolv" // RUN: %clang -### %s 2>&1 \ // RUN: --target=arm-linux-androideabi -fuse-ld=ld -fsanitize=address \ @@ -182,6 +188,7 @@ // CHECK-ASAN-ANDROID-STATICLIBASAN: libclang_rt.asan-arm-android.a" // CHECK-ASAN-ANDROID-STATICLIBASAN-NOT: "-lpthread" // CHECK-ASAN-ANDROID-STATICLIBASAN-NOT: "-lrt" +// CHECK-ASAN-ANDROID-STATICLIBASAN-NOT: "-lresolv" // RUN: %clang -### %s 2>&1 \ // RUN: --target=arm-linux-androideabi -fuse-ld=ld -fsanitize=undefined \ @@ -192,8 +199,10 @@ // CHECK-UBSAN-ANDROID: "-pie" // CHECK-UBSAN-ANDROID-NOT: "-lc" // CHECK-UBSAN-ANDROID-NOT: "-lpthread" +// CHECK-UBSAN-ANDROID-NOT: "-lresolv" // CHECK-UBSAN-ANDROID: libclang_rt.ubsan_standalone-arm-android.so" // CHECK-UBSAN-ANDROID-NOT: "-lpthread" +// CHECK-UBSAN-ANDROID-NOT: "-lresolv" // RUN: %clang -### %s 2>&1 \ // RUN: --target=arm-linux-androideabi -fuse-ld=ld -fsanitize=undefined \ @@ -205,6 +214,7 @@ // CHECK-UBSAN-ANDROID-STATICLIBASAN: libclang_rt.ubsan_standalone-arm-android.a" // CHECK-UBSAN-ANDROID-STATICLIBASAN-NOT: "-lpthread" // CHECK-UBSAN-ANDROID-STATICLIBASAN-NOT: "-lrt" +// CHECK-UBSAN-ANDROID-STATICLIBASAN-NOT: "-lresolv" // // RUN: %clang -### %s 2>&1 \ @@ -216,8 +226,10 @@ // CHECK-ASAN-ANDROID-X86: "-pie" // CHECK-ASAN-ANDROID-X86-NOT: "-lc" // CHECK-ASAN-ANDROID-X86-NOT: "-lpthread" +// CHECK-ASAN-ANDROID-X86-NOT: "-lresolv" // CHECK-ASAN-ANDROID-X86: libclang_rt.asan-i686-android.so" // CHECK-ASAN-ANDROID-X86-NOT: "-lpthread" +// CHECK-ASAN-ANDROID-X86-NOT: "-lresolv" // // RUN: %clang -### %s 2>&1 \ // RUN: --target=arm-linux-androideabi -fsanitize=address \ @@ -237,6 +249,7 @@ // CHECK-ASAN-ANDROID-SHARED-NOT: "-lc" // CHECK-ASAN-ANDROID-SHARED: libclang_rt.asan-arm-android.so" // CHECK-ASAN-ANDROID-SHARED-NOT: "-lpthread" +// CHECK-ASAN-ANDROID-SHARED-NOT: "-lresolv" // RUN: %clang -### %s 2>&1 \ // RUN: --target=sparcel-myriad-rtems-elf -fuse-ld=ld -fsanitize=address \ @@ -265,6 +278,7 @@ // CHECK-TSAN-LINUX-CXX: "-lpthread" // CHECK-TSAN-LINUX-CXX: "-lrt" // CHECK-TSAN-LINUX-CXX: "-ldl" +// CHECK-TSAN-LINUX-CXX: "-lresolv" // RUN: %clang -fsanitize=thread -fno-sanitize-link-runtime -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -292,6 +306,7 @@ // CHECK-MSAN-LINUX-CXX: "-lpthread" // CHECK-MSAN-LINUX-CXX: "-lrt" // CHECK-MSAN-LINUX-CXX: "-ldl" +// CHECK-MSAN-LINUX-CXX: "-lresolv" // RUN: %clang -fsanitize=memory -fno-sanitize-link-runtime -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -328,6 +343,7 @@ // CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_standalone_cxx // CHECK-UBSAN-LINUX-NOT: "-lstdc++" // CHECK-UBSAN-LINUX: "-lpthread" +// CHECK-UBSAN-LINUX: "-lresolv" // RUN: %clang -fsanitize=undefined -fno-sanitize-link-runtime -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -384,6 +400,7 @@ // CHECK-UBSAN-LINUX-CXX: "-lstdc++" // CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan // CHECK-UBSAN-LINUX-CXX: "-lpthread" +// CHECK-UBSAN-LINUX-CXX: "-lresolv" // RUN: %clang -fsanitize=undefined -fsanitize-minimal-runtime -### %s 2>&1 \ // RUN: --target=i386-unknown-linux -fuse-ld=ld \ @@ -393,6 +410,7 @@ // CHECK-UBSAN-MINIMAL-LINUX: "{{.*}}ld{{(.exe)?}}" // CHECK-UBSAN-MINIMAL-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_minimal-i386.a" "--no-whole-archive" // CHECK-UBSAN-MINIMAL-LINUX: "-lpthread" +// CHECK-UBSAN-MINIMAL-LINUX: "-lresolv" // RUN: %clang -fsanitize=undefined -fsanitize-minimal-runtime -### %s 2>&1 \ // RUN: --target=x86_64-apple-darwin -fuse-ld=ld \ @@ -418,6 +436,7 @@ // CHECK-ASAN-UBSAN-LINUX-NOT: libclang_rt.ubsan // CHECK-ASAN-UBSAN-LINUX-NOT: "-lstdc++" // CHECK-ASAN-UBSAN-LINUX: "-lpthread" +// CHECK-ASAN-UBSAN-LINUX: "-lresolv" // RUN: %clangxx -fsanitize=address,undefined -### %s 2>&1 \ // RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform \ @@ -430,6 +449,7 @@ // CHECK-ASAN-UBSAN-LINUX-CXX-NOT: libclang_rt.ubsan // CHECK-ASAN-UBSAN-LINUX-CXX: "-lstdc++" // CHECK-ASAN-UBSAN-LINUX-CXX: "-lpthread" +// CHECK-ASAN-UBSAN-LINUX-CXX: "-lresolv" // RUN: %clangxx -fsanitize=memory,undefined -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -472,6 +492,7 @@ // CHECK-LSAN-LINUX: libclang_rt.lsan-x86_64.a" // CHECK-LSAN-LINUX: "-lpthread" // CHECK-LSAN-LINUX: "-ldl" +// CHECK-LSAN-LINUX: "-lresolv" // RUN: %clang -fsanitize=leak -fno-sanitize-link-runtime -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -494,6 +515,7 @@ // CHECK-LSAN-COV-LINUX-NOT: libclang_rt.ubsan // CHECK-LSAN-COV-LINUX: "-lpthread" // CHECK-LSAN-COV-LINUX: "-ldl" +// CHECK-LSAN-COV-LINUX: "-lresolv" // RUN: %clang -fsanitize=leak,address -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -515,6 +537,7 @@ // CHECK-ASAN-COV-LINUX-NOT: libclang_rt.ubsan // CHECK-ASAN-COV-LINUX-NOT: "-lstdc++" // CHECK-ASAN-COV-LINUX: "-lpthread" +// CHECK-ASAN-COV-LINUX: "-lresolv" // RUN: %clang -fsanitize=memory -fsanitize-coverage=func -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -526,6 +549,7 @@ // CHECK-MSAN-COV-LINUX-NOT: libclang_rt.ubsan // CHECK-MSAN-COV-LINUX-NOT: "-lstdc++" // CHECK-MSAN-COV-LINUX: "-lpthread" +// CHECK-MSAN-COV-LINUX: "-lresolv" // RUN: %clang -fsanitize=dataflow -fsanitize-coverage=func -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -537,6 +561,7 @@ // CHECK-DFSAN-COV-LINUX-NOT: libclang_rt.ubsan // CHECK-DFSAN-COV-LINUX-NOT: "-lstdc++" // CHECK-DFSAN-COV-LINUX: "-lpthread" +// CHECK-DFSAN-COV-LINUX: "-lresolv" // RUN: %clang -fsanitize=undefined -fsanitize-coverage=func -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -547,6 +572,7 @@ // CHECK-UBSAN-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone-x86_64.a" "--no-whole-archive" // CHECK-UBSAN-COV-LINUX-NOT: "-lstdc++" // CHECK-UBSAN-COV-LINUX: "-lpthread" +// CHECK-UBSAN-COV-LINUX: "-lresolv" // RUN: %clang -fsanitize-coverage=func -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -557,6 +583,7 @@ // CHECK-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone-x86_64.a" "--no-whole-archive" // CHECK-COV-LINUX-NOT: "-lstdc++" // CHECK-COV-LINUX: "-lpthread" +// CHECK-COV-LINUX: "-lresolv" // CFI by itself does not link runtime libraries. // RUN: %clang -fsanitize=cfi -### %s 2>&1 \ @@ -651,6 +678,7 @@ // CHECK-SAFESTACK-LINUX: "-u" "__safestack_init" // CHECK-SAFESTACK-LINUX: "-lpthread" // CHECK-SAFESTACK-LINUX: "-ldl" +// CHECK-SAFESTACK-LINUX: "-lresolv" // RUN: %clang -fsanitize=shadow-call-stack -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -828,6 +856,7 @@ // CHECK-SCUDO-LINUX-NOT: "-lstdc++" // CHECK-SCUDO-LINUX: "-lpthread" // CHECK-SCUDO-LINUX: "-ldl" +// CHECK-SCUDO-LINUX: "-lresolv" // RUN: %clang -fsanitize=scudo -fsanitize-minimal-runtime -### %s 2>&1 \ // RUN: --target=i386-unknown-linux -fuse-ld=ld \ @@ -838,6 +867,7 @@ // CHECK-SCUDO-MINIMAL-LINUX: "-pie" // CHECK-SCUDO-MINIMAL-LINUX: "--whole-archive" "{{.*}}libclang_rt.scudo_minimal-i386.a" "--no-whole-archive" // CHECK-SCUDO-MINIMAL-LINUX: "-lpthread" +// CHECK-SCUDO-MINIMAL-LINUX: "-lresolv" // RUN: %clang -### %s -o %t.so -shared 2>&1 \ // RUN: --target=i386-unknown-linux -fuse-ld=ld -fsanitize=scudo -shared-libsan \ @@ -852,6 +882,7 @@ // CHECK-SCUDO-SHARED-LINUX-NOT: "-lpthread" // CHECK-SCUDO-SHARED-LINUX-NOT: "-lrt" // CHECK-SCUDO-SHARED-LINUX-NOT: "-ldl" +// CHECK-SCUDO-SHARED-LINUX-NOT: "-lresolv" // CHECK-SCUDO-SHARED-LINUX-NOT: "--export-dynamic" // CHECK-SCUDO-SHARED-LINUX-NOT: "--dynamic-list" @@ -864,8 +895,10 @@ // CHECK-SCUDO-ANDROID-NOT: "-lc" // CHECK-SCUDO-ANDROID: "-pie" // CHECK-SCUDO-ANDROID-NOT: "-lpthread" +// CHECK-SCUDO-ANDROID-NOT: "-lresolv" // CHECK-SCUDO-ANDROID: libclang_rt.scudo-arm-android.so" // CHECK-SCUDO-ANDROID-NOT: "-lpthread" +// CHECK-SCUDO-ANDROID-NOT: "-lresolv" // RUN: %clang -### %s 2>&1 \ // RUN: --target=arm-linux-androideabi -fuse-ld=ld -fsanitize=scudo \ @@ -878,6 +911,7 @@ // CHECK-SCUDO-ANDROID-STATIC-NOT: "-lstdc++" // CHECK-SCUDO-ANDROID-STATIC-NOT: "-lpthread" // CHECK-SCUDO-ANDROID-STATIC-NOT: "-lrt" +// CHECK-SCUDO-ANDROID-STATIC-NOT: "-lresolv" // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \ @@ -895,6 +929,7 @@ // CHECK-HWASAN-X86-64-LINUX: "-lpthread" // CHECK-HWASAN-X86-64-LINUX: "-lrt" // CHECK-HWASAN-X86-64-LINUX: "-ldl" +// CHECK-HWASAN-X86-64-LINUX: "-lresolv" // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \ @@ -909,6 +944,7 @@ // CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "-lpthread" // CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "-lrt" // CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "-ldl" +// CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "-lresolv" // CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "--export-dynamic" // CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "--dynamic-list" @@ -925,6 +961,7 @@ // CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "-lpthread" // CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "-lrt" // CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "-ldl" +// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "-lresolv" // CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "--export-dynamic" // CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "--dynamic-list" @@ -944,6 +981,7 @@ // CHECK-HWASAN-AARCH64-LINUX: "-lpthread" // CHECK-HWASAN-AARCH64-LINUX: "-lrt" // CHECK-HWASAN-AARCH64-LINUX: "-ldl" +// CHECK-HWASAN-AARCH64-LINUX: "-lresolv" // RUN: %clang -### %s 2>&1 \ // RUN: --target=aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \ @@ -959,6 +997,7 @@ // CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lpthread" // CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lrt" // CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "-ldl" +// CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lresolv" // CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "--export-dynamic" // CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "--dynamic-list" @@ -975,5 +1014,6 @@ // CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lpthread" // CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lrt" // CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-ldl" +// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lresolv" // CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "--export-dynamic" // CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "--dynamic-list" diff --git a/clang/test/Driver/solaris-header-search.cpp b/clang/test/Driver/solaris-header-search.cpp index d5c3c0dd74688..e058941fdc5f8 100644 --- a/clang/test/Driver/solaris-header-search.cpp +++ b/clang/test/Driver/solaris-header-search.cpp @@ -1,41 +1,41 @@ // Test that the C++ headers are found on Solaris with gcc toolchain detection // // Sparc, 32bit -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 --stdlib=platform \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK_SOLARIS_SPARC %s -// CHECK_SOLARIS_SPARC: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK_SOLARIS_SPARC: "-cc1" // CHECK_SOLARIS_SPARC-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK_SOLARIS_SPARC-SAME: "-internal-isystem" "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/../../../../include/c++/4.8.2" // CHECK_SOLARIS_SPARC-SAME: "-internal-isystem" "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/../../../../include/c++/4.8.2/sparc-sun-solaris2.11" // Sparc, 64bit -// RUN: %clang -no-canonical-prefixes -m64 %s -### -fsyntax-only 2>&1 \ +// RUN: %clang -m64 -### %s -fsyntax-only 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 --stdlib=platform \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK_SOLARIS_SPARC64 %s -// CHECK_SOLARIS_SPARC64: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK_SOLARIS_SPARC64: "-cc1" // CHECK_SOLARIS_SPARC64-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK_SOLARIS_SPARC64-SAME: "-internal-isystem" "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/../../../../include/c++/4.8.2" // CHECK_SOLARIS_SPARC64-SAME: "-internal-isystem" "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/../../../../include/c++/4.8.2/sparc-sun-solaris2.11/sparcv9" // Intel, 32bit -// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ +// RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=i386-pc-solaris2.11 --stdlib=platform \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK_SOLARIS_X86 %s -// CHECK_SOLARIS_X86: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK_SOLARIS_X86: "-cc1" // CHECK_SOLARIS_X86-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK_SOLARIS_X86-SAME: "-internal-isystem" "{{.*}}/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/../../../../include/c++/4.9.4" // CHECK_SOLARIS_X86-SAME: "-internal-isystem" "{{.*}}/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/../../../../include/c++/4.9.4/i386-pc-solaris2.11" // Intel, 64bit -// RUN: %clang -no-canonical-prefixes -m64 %s -### -fsyntax-only 2>&1 \ +// RUN: %clang -m64 -### %s -fsyntax-only 2>&1 \ // RUN: --target=i386-pc-solaris2.11 --stdlib=platform \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK_SOLARIS_X64 %s -// CHECK_SOLARIS_X64: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK_SOLARIS_X64: "-cc1" // CHECK_SOLARIS_X64-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK_SOLARIS_X64-SAME: "-internal-isystem" "[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/../../../../include/c++/4.9.4" // CHECK_SOLARIS_X64-SAME: "-internal-isystem" "[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/../../../../include/c++/4.9.4/i386-pc-solaris2.11/amd64" diff --git a/clang/test/Driver/solaris-ld.c b/clang/test/Driver/solaris-ld.c index 57b2b1ba159b0..2193f35ac0545 100644 --- a/clang/test/Driver/solaris-ld.c +++ b/clang/test/Driver/solaris-ld.c @@ -2,13 +2,12 @@ // sysroot to make these tests independent of the host system. // Check sparc-sun-solaris2.11, 32bit -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: --target=sparc-sun-solaris2.11 \ +// RUN: %clang -### %s 2>&1 --target=sparc-sun-solaris2.11 \ // RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32 %s // CHECK-LD-SPARC32-NOT: warning: -// CHECK-LD-SPARC32: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "sparc-sun-solaris2.11" +// CHECK-LD-SPARC32: "-cc1" "-triple" "sparc-sun-solaris2.11" // CHECK-LD-SPARC32-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-LD-SPARC32: "{{.*}}ld{{(.exe)?}}" // CHECK-LD-SPARC32-SAME: "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2{{/|\\\\}}crt1.o" @@ -26,13 +25,12 @@ // CHECK-LD-SPARC32-SAME: "[[SYSROOT]]/usr/lib{{/|\\\\}}crtn.o" // Check sparc-sun-solaris2.11, 64bit -// RUN: %clang -no-canonical-prefixes -m64 %s -### -o %t.o 2>&1 \ -// RUN: --target=sparc-sun-solaris2.11 \ +// RUN: %clang -m64 -### %s 2>&1 --target=sparc-sun-solaris2.11 \ // RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC64 %s // CHECK-LD-SPARC64-NOT: warning: -// CHECK-LD-SPARC64: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "sparcv9-sun-solaris2.11" +// CHECK-LD-SPARC64: "-cc1" "-triple" "sparcv9-sun-solaris2.11" // CHECK-LD-SPARC64-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-LD-SPARC64: "{{.*}}ld{{(.exe)?}}" // CHECK-LD-SPARC64-SAME: "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9{{/|\\\\}}crt1.o" @@ -50,13 +48,12 @@ // CHECK-LD-SPARC64-SAME: "[[SYSROOT]]/usr/lib/sparcv9{{/|\\\\}}crtn.o" // Check i386-pc-solaris2.11, 32bit -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: --target=i386-pc-solaris2.11 \ +// RUN: %clang -### %s 2>&1 --target=i386-pc-solaris2.11 \ // RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X32 %s // CHECK-LD-X32-NOT: warning: -// CHECK-LD-X32: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "i386-pc-solaris2.11" +// CHECK-LD-X32: "-cc1" "-triple" "i386-pc-solaris2.11" // CHECK-LD-X32-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-LD-X32: "{{.*}}ld{{(.exe)?}}" // CHECK-LD-X32-SAME: "[[SYSROOT]]/usr/lib{{/|\\\\}}crt1.o" @@ -74,13 +71,13 @@ // CHECK-LD-X32-SAME: "[[SYSROOT]]/usr/lib{{/|\\\\}}crtn.o" // Check i386-pc-solaris2.11, 64bit -// RUN: %clang -no-canonical-prefixes -m64 %s -### -o %t.o 2>&1 \ +// RUN: %clang -m64 -### %s 2>&1 \ // RUN: --target=i386-pc-solaris2.11 \ // RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X64 %s // CHECK-LD-X64-NOT: warning: -// CHECK-LD-X64: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "x86_64-pc-solaris2.11" +// CHECK-LD-X64: "-cc1" "-triple" "x86_64-pc-solaris2.11" // CHECK-LD-X64-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-LD-X64: "{{.*}}ld{{(.exe)?}}" // CHECK-LD-X64-SAME: "[[SYSROOT]]/usr/lib/amd64{{/|\\\\}}crt1.o" @@ -98,7 +95,7 @@ // CHECK-LD-X64-SAME: "[[SYSROOT]]/usr/lib/amd64{{/|\\\\}}crtn.o" // Check the right -l flags are present with -shared -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o -shared 2>&1 \ +// RUN: %clang -### %s -shared 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ // RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ @@ -110,11 +107,10 @@ // CHECK-SPARC32-SHARED-NOT: "-lm" // -r suppresses default -l and crt*.o, values-*.o like -nostdlib. -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o \ -// RUN: --target=sparc-sun-solaris2.11 -r 2>&1 \ +// RUN: %clang -### %s --target=sparc-sun-solaris2.11 -r 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-RELOCATABLE // CHECK-RELOCATABLE: "-L // CHECK-RELOCATABLE: "-r" // CHECK-RELOCATABLE-NOT: "-l -// CHECK-RELOCATABLE-NOT: {{.*}}crt{{[^.]+}}.o -// CHECK-RELOCATABLE-NOT: {{.*}}values-{{[^.]+}}.o +// CHECK-RELOCATABLE-NOT: /crt{{[^.]+}}.o +// CHECK-RELOCATABLE-NOT: /values-{{[^.]+}}.o diff --git a/clang/test/Driver/wasm-toolchain-lto.c b/clang/test/Driver/wasm-toolchain-lto.c index 216207316f3d7..0de5cbf71e28a 100644 --- a/clang/test/Driver/wasm-toolchain-lto.c +++ b/clang/test/Driver/wasm-toolchain-lto.c @@ -1,6 +1,6 @@ // A basic C link command-line with optimization with known OS and LTO enabled. -// RUN: %clang -### -O2 -flto -no-canonical-prefixes -target wasm32-wasi --sysroot=/foo %s 2>&1 \ +// RUN: %clang -### -O2 -flto --target=wasm32-wasi --sysroot=/foo %s 2>&1 \ // RUN: | FileCheck -check-prefix=LINK_OPT_KNOWN %s -// LINK_OPT_KNOWN: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// LINK_OPT_KNOWN: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" // LINK_OPT_KNOWN: wasm-ld{{.*}}" "-L/foo/lib/wasm32-wasi/llvm-lto/ diff --git a/clang/test/Driver/windows-exceptions.cpp b/clang/test/Driver/windows-exceptions.cpp index 84f8e2708f8ee..ffca80fdfa550 100644 --- a/clang/test/Driver/windows-exceptions.cpp +++ b/clang/test/Driver/windows-exceptions.cpp @@ -1,12 +1,18 @@ -// RUN: %clang -target i686-windows-msvc -c %s -### 2>&1 | FileCheck -check-prefix=MSVC %s -// RUN: %clang -target x86_64-windows-msvc -c %s -### 2>&1 | FileCheck -check-prefix=MSVC %s +// RUN: %clang -target i686-windows-msvc -c %s -### 2>&1 | FileCheck -check-prefix=MSVC -check-prefix=MSVC-NOSEH %s +// RUN: %clang -target x86_64-windows-msvc -c %s -### 2>&1 | FileCheck -check-prefix=MSVC -check-prefix=MSVC-SEH %s +// RUN: %clang -target armv7-windows-msvc -c %s -### 2>&1 | FileCheck -check-prefix=MSVC -check-prefix=MSVC-SEH %s +// RUN: %clang -target aarch64-windows-msvc -c %s -### 2>&1 | FileCheck -check-prefix=MSVC -check-prefix=MSVC-SEH %s // RUN: %clang -target i686-windows-gnu -c %s -### 2>&1 | FileCheck -check-prefix=MINGW-DWARF %s // RUN: %clang -target x86_64-windows-gnu -c %s -### 2>&1 | FileCheck -check-prefix=MINGW-SEH %s +// RUN: %clang -target armv7-windows-gnu -fdwarf-exceptions -c %s -### 2>&1 | FileCheck -check-prefix=MINGW-DWARF %s +// RUN: %clang -target armv7-windows-gnu -c %s -### 2>&1 | FileCheck -check-prefix=MINGW-SEH %s // RUN: %clang -target aarch64-windows-gnu -fdwarf-exceptions -c %s -### 2>&1 | FileCheck -check-prefix=MINGW-DWARF %s // RUN: %clang -target aarch64-windows-gnu -c %s -### 2>&1 | FileCheck -check-prefix=MINGW-SEH %s MSVC-NOT: -exception-model=dwarf MSVC-NOT: -exception-model=seh +MSVC-NOSEH-NOT: -funwind-tables=2 +MSVC-SEH: -funwind-tables=2 MINGW-DWARF: -exception-model=dwarf MINGW-SEH: -funwind-tables=2 MINGW-SEH: -exception-model=seh diff --git a/clang/test/Driver/x86-target-features.c b/clang/test/Driver/x86-target-features.c index 09c17aceaa4d6..453656a1b98fa 100644 --- a/clang/test/Driver/x86-target-features.c +++ b/clang/test/Driver/x86-target-features.c @@ -304,3 +304,14 @@ // RUN: %clang --target=i386 -march=i386 -mno-crc32 %s -### 2>&1 | FileCheck -check-prefix=NO-CRC32 %s // CRC32: "-target-feature" "+crc32" // NO-CRC32: "-target-feature" "-crc32" + +// RUN: %clang --target=i386 -march=i386 -mharden-sls=return %s -### -o %t.o 2>&1 | FileCheck -check-prefixes=SLS-RET,NO-SLS %s +// RUN: %clang --target=i386 -march=i386 -mharden-sls=indirect-jmp %s -### -o %t.o 2>&1 | FileCheck -check-prefixes=SLS-IJMP,NO-SLS %s +// RUN: %clang --target=i386 -march=i386 -mharden-sls=none -mharden-sls=all %s -### -o %t.o 2>&1 | FileCheck -check-prefixes=SLS-IJMP,SLS-RET %s +// RUN: %clang --target=i386 -march=i386 -mharden-sls=all -mharden-sls=none %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-SLS %s +// RUN: %clang --target=i386 -march=i386 -mharden-sls=return,indirect-jmp %s -### -o %t.o 2>&1 | FileCheck -check-prefix=BAD-SLS %s +// NO-SLS-NOT: "+harden-sls- +// SLS-RET-DAG: "-target-feature" "+harden-sls-ret" +// SLS-IJMP-DAG: "-target-feature" "+harden-sls-ijmp" +// NO-SLS-NOT: "+harden-sls- +// BAD-SLS: unsupported argument '{{[^']+}}' to option '-mharden-sls=' diff --git a/clang/test/Driver/zos-dwarfversion.c b/clang/test/Driver/zos-dwarfversion.c new file mode 100644 index 0000000000000..53a727102f081 --- /dev/null +++ b/clang/test/Driver/zos-dwarfversion.c @@ -0,0 +1,3 @@ +// RUN: %clang -target s390x-none-zos -g -S -emit-llvm %s -o - | FileCheck %s + +// CHECK: !"Dwarf Version", i32 4 diff --git a/clang/test/Frontend/noderef.c b/clang/test/Frontend/noderef.c index 6b9a143168172..daf2d6006b2d7 100644 --- a/clang/test/Frontend/noderef.c +++ b/clang/test/Frontend/noderef.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -Wno-unused-value -verify %s +// RUN: %clang_cc1 -Wno-unused-value -fdouble-square-bracket-attributes -verify %s #define NODEREF __attribute__((noderef)) @@ -221,3 +221,24 @@ int test(void) { do {} while (*p); // expected-warning{{dereferencing p; was declared with a 'noderef' type}} return *p; // expected-warning{{dereferencing p; was declared with a 'noderef' type}} } + +// FIXME: Currently, [[]] syntax does not work for the `noderef` atribute. +// For the time being, test that we consistently diagnose the attribute as +// ignored. +// For details see https://github.com/llvm/llvm-project/issues/55790 +void test_standard_syntax() { + [[clang::noderef]] int i; // expected-warning {{'noderef' attribute ignored}} + + [[clang::noderef]] int *p1; // expected-warning {{'noderef' attribute ignored}} + *p1; + + int *p2 [[clang::noderef]]; // expected-warning {{'noderef' attribute ignored}} + *p2; + + int * [[clang::noderef]] p3; // expected-warning {{'noderef' attribute ignored}} + *p3; + + typedef int* IntPtr; + [[clang::noderef]] IntPtr p4; // expected-warning {{'noderef' attribute ignored}} + *p4; +} diff --git a/clang/test/Headers/opencl-c-header.cl b/clang/test/Headers/opencl-c-header.cl index 455842412fd0c..8242798106ac3 100644 --- a/clang/test/Headers/opencl-c-header.cl +++ b/clang/test/Headers/opencl-c-header.cl @@ -100,7 +100,7 @@ global atomic_int z = ATOMIC_VAR_INIT(99); #if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2) // expected-no-diagnostics #else //__OPENCL_C_VERSION__ -// expected-warning@+2{{unknown OpenCL extension 'cl_intel_planar_yuv' - ignoring}} +// expected-warning@+2{{OpenCL extension 'cl_intel_planar_yuv' unknown or does not require pragma - ignoring}} #endif //__OPENCL_C_VERSION__ #pragma OPENCL EXTENSION cl_intel_planar_yuv : enable diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 0713252385885..b9499229c0666 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -185,7 +185,7 @@ // CHECK-NEXT: VecReturn (SubjectMatchRule_record) // CHECK-NEXT: VecTypeHint (SubjectMatchRule_function) // CHECK-NEXT: WarnUnused (SubjectMatchRule_record) -// CHECK-NEXT: WarnUnusedResult (SubjectMatchRule_objc_method, SubjectMatchRule_enum, SubjectMatchRule_record, SubjectMatchRule_hasType_functionType) +// CHECK-NEXT: WarnUnusedResult (SubjectMatchRule_objc_method, SubjectMatchRule_enum, SubjectMatchRule_record, SubjectMatchRule_hasType_functionType, SubjectMatchRule_type_alias) // CHECK-NEXT: Weak (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record) // CHECK-NEXT: WeakRef (SubjectMatchRule_variable, SubjectMatchRule_function) // CHECK-NEXT: WebAssemblyExportName (SubjectMatchRule_function) diff --git a/clang/test/Modules/Inputs/gmodules-deduction-guide.h b/clang/test/Modules/Inputs/gmodules-deduction-guide.h new file mode 100644 index 0000000000000..47b5931083af1 --- /dev/null +++ b/clang/test/Modules/Inputs/gmodules-deduction-guide.h @@ -0,0 +1,11 @@ +struct A { +}; + +template +struct S{ + S(const A &); +}; + +S(const A&) -> S; + +typedef decltype(S(A())) Type0; diff --git a/clang/test/Modules/cxx-modules.cppm b/clang/test/Modules/cxx-modules.cppm deleted file mode 100644 index be17f85f8d17d..0000000000000 --- a/clang/test/Modules/cxx-modules.cppm +++ /dev/null @@ -1,7 +0,0 @@ -// This tests that we could use C++20 modules standalone. -// RUN: %clang -std=c++03 -fcxx-modules -fsyntax-only -Xclang -verify %s -// RUN: %clang -std=c++11 -fcxx-modules -fsyntax-only -Xclang -verify %s -// RUN: %clang -std=c++14 -fcxx-modules -fsyntax-only -Xclang -verify %s -// RUN: %clang -std=c++17 -fcxx-modules -fsyntax-only -Xclang -verify %s -// expected-no-diagnostics -export module M; diff --git a/clang/test/Modules/gmodules-deduction-guide.cpp b/clang/test/Modules/gmodules-deduction-guide.cpp new file mode 100644 index 0000000000000..6b5a4086b3635 --- /dev/null +++ b/clang/test/Modules/gmodules-deduction-guide.cpp @@ -0,0 +1,9 @@ +// REQUIRES: asserts + +// RUN: %clang_cc1 -std=c++2b -x c++-header -emit-pch -fmodule-format=obj -I %S/Inputs \ +// RUN: -o %t.pch %S/Inputs/gmodules-deduction-guide.h \ +// RUN: -mllvm -debug-only=pchcontainer &>%t-pch.ll +// RUN: cat %t-pch.ll | FileCheck %s + +// CHECK: ![[V0:.*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", +// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "Type0",{{.*}}, baseType: ![[V0]]) diff --git a/clang/test/OpenMP/atomic_compare_codegen.cpp b/clang/test/OpenMP/atomic_compare_codegen.cpp index 825832399e3c4..c4032a862cc22 100644 --- a/clang/test/OpenMP/atomic_compare_codegen.cpp +++ b/clang/test/OpenMP/atomic_compare_codegen.cpp @@ -1945,6 +1945,7759 @@ void foo(void) { ullx = ulld; } +void bar() { + char cx, cv, cr, ce, cd; + unsigned char ucx, ucv, ucr, uce, ucd; + short sx, sv, sr, se, sd; + unsigned short usx, usv, usr, use, usd; + int ix, iv, ir, ie, id; + unsigned int uix, uiv, uir, uie, uid; + long lx, lv, lr, le, ld; + unsigned long ulx, ulv, ulr, ule, uld; + long long llx, llv, llr, lle, lld; + unsigned long long ullx, ullv, ullr, ulle, ulld; + +#pragma omp atomic compare capture + { + cv = cx; + if (ce > cx) { + cx = ce; + } + } +#pragma omp atomic compare capture + { + cv = cx; + if (cx > ce) { + cx = ce; + } + } +#pragma omp atomic compare capture + { + cv = cx; + if (ce < cx) { + cx = ce; + } + } +#pragma omp atomic compare capture + { + cv = cx; + if (cx < ce) { + cx = ce; + } + } +#pragma omp atomic compare capture + { + cv = cx; + if (cx == ce) { + cx = cd; + } + } +#pragma omp atomic compare capture + { + cv = cx; + if (ce == cx) { + cx = cd; + } + } +#pragma omp atomic compare capture + { + if (ce > cx) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture + { + if (cx > ce) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture + { + if (ce < cx) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture + { + if (cx < ce) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture + { + if (cx == ce) { + cx = cd; + } + cv = cx; + } +#pragma omp atomic compare capture + { + if (ce == cx) { + cx = cd; + } + cv = cx; + } +#pragma omp atomic compare capture + if (cx == ce) { + cx = cd; + } else { + cv = cx; + } +#pragma omp atomic compare capture + if (ce == cx) { + cx = cd; + } else { + cv = cx; + } +#pragma omp atomic compare capture + { + cr = cx == ce; + if (cr) { + cx = cd; + } + } +#pragma omp atomic compare capture + { + cr = ce == cx; + if (cr) { + cx = cd; + } + } +#pragma omp atomic compare capture + { + cr = cx == ce; + if (cr) { + cx = cd; + } else { + cv = cx; + } + } +#pragma omp atomic compare capture + { + cr = ce == cx; + if (cr) { + cx = cd; + } else { + cv = cx; + } + } + +#pragma omp atomic compare capture acq_rel + { + cv = cx; + if (ce > cx) { + cx = ce; + } + } +#pragma omp atomic compare capture acq_rel + { + cv = cx; + if (cx > ce) { + cx = ce; + } + } +#pragma omp atomic compare capture acq_rel + { + cv = cx; + if (ce < cx) { + cx = ce; + } + } +#pragma omp atomic compare capture acq_rel + { + cv = cx; + if (cx < ce) { + cx = ce; + } + } +#pragma omp atomic compare capture acq_rel + { + cv = cx; + if (cx == ce) { + cx = cd; + } + } +#pragma omp atomic compare capture acq_rel + { + cv = cx; + if (ce == cx) { + cx = cd; + } + } +#pragma omp atomic compare capture acq_rel + { + if (ce > cx) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture acq_rel + { + if (cx > ce) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture acq_rel + { + if (ce < cx) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture acq_rel + { + if (cx < ce) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture acq_rel + { + if (cx == ce) { + cx = cd; + } + cv = cx; + } +#pragma omp atomic compare capture acq_rel + { + if (ce == cx) { + cx = cd; + } + cv = cx; + } +#pragma omp atomic compare capture acq_rel + if (cx == ce) { + cx = cd; + } else { + cv = cx; + } +#pragma omp atomic compare capture acq_rel + if (ce == cx) { + cx = cd; + } else { + cv = cx; + } +#pragma omp atomic compare capture acq_rel + { + cr = cx == ce; + if (cr) { + cx = cd; + } + } +#pragma omp atomic compare capture acq_rel + { + cr = ce == cx; + if (cr) { + cx = cd; + } + } +#pragma omp atomic compare capture acq_rel + { + cr = cx == ce; + if (cr) { + cx = cd; + } else { + cv = cx; + } + } +#pragma omp atomic compare capture acq_rel + { + cr = ce == cx; + if (cr) { + cx = cd; + } else { + cv = cx; + } + } + +#pragma omp atomic compare capture acquire + { + cv = cx; + if (ce > cx) { + cx = ce; + } + } +#pragma omp atomic compare capture acquire + { + cv = cx; + if (cx > ce) { + cx = ce; + } + } +#pragma omp atomic compare capture acquire + { + cv = cx; + if (ce < cx) { + cx = ce; + } + } +#pragma omp atomic compare capture acquire + { + cv = cx; + if (cx < ce) { + cx = ce; + } + } +#pragma omp atomic compare capture acquire + { + cv = cx; + if (cx == ce) { + cx = cd; + } + } +#pragma omp atomic compare capture acquire + { + cv = cx; + if (ce == cx) { + cx = cd; + } + } +#pragma omp atomic compare capture acquire + { + if (ce > cx) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture acquire + { + if (cx > ce) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture acquire + { + if (ce < cx) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture acquire + { + if (cx < ce) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture acquire + { + if (cx == ce) { + cx = cd; + } + cv = cx; + } +#pragma omp atomic compare capture acquire + { + if (ce == cx) { + cx = cd; + } + cv = cx; + } +#pragma omp atomic compare capture acquire + if (cx == ce) { + cx = cd; + } else { + cv = cx; + } +#pragma omp atomic compare capture acquire + if (ce == cx) { + cx = cd; + } else { + cv = cx; + } +#pragma omp atomic compare capture acquire + { + cr = cx == ce; + if (cr) { + cx = cd; + } + } +#pragma omp atomic compare capture acquire + { + cr = ce == cx; + if (cr) { + cx = cd; + } + } +#pragma omp atomic compare capture acquire + { + cr = cx == ce; + if (cr) { + cx = cd; + } else { + cv = cx; + } + } +#pragma omp atomic compare capture acquire + { + cr = ce == cx; + if (cr) { + cx = cd; + } else { + cv = cx; + } + } + +#pragma omp atomic compare capture relaxed + { + cv = cx; + if (ce > cx) { + cx = ce; + } + } +#pragma omp atomic compare capture relaxed + { + cv = cx; + if (cx > ce) { + cx = ce; + } + } +#pragma omp atomic compare capture relaxed + { + cv = cx; + if (ce < cx) { + cx = ce; + } + } +#pragma omp atomic compare capture relaxed + { + cv = cx; + if (cx < ce) { + cx = ce; + } + } +#pragma omp atomic compare capture relaxed + { + cv = cx; + if (cx == ce) { + cx = cd; + } + } +#pragma omp atomic compare capture relaxed + { + cv = cx; + if (ce == cx) { + cx = cd; + } + } +#pragma omp atomic compare capture relaxed + { + if (ce > cx) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture relaxed + { + if (cx > ce) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture relaxed + { + if (ce < cx) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture relaxed + { + if (cx < ce) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture relaxed + { + if (cx == ce) { + cx = cd; + } + cv = cx; + } +#pragma omp atomic compare capture relaxed + { + if (ce == cx) { + cx = cd; + } + cv = cx; + } +#pragma omp atomic compare capture relaxed + if (cx == ce) { + cx = cd; + } else { + cv = cx; + } +#pragma omp atomic compare capture relaxed + if (ce == cx) { + cx = cd; + } else { + cv = cx; + } +#pragma omp atomic compare capture relaxed + { + cr = cx == ce; + if (cr) { + cx = cd; + } + } +#pragma omp atomic compare capture relaxed + { + cr = ce == cx; + if (cr) { + cx = cd; + } + } +#pragma omp atomic compare capture relaxed + { + cr = cx == ce; + if (cr) { + cx = cd; + } else { + cv = cx; + } + } +#pragma omp atomic compare capture relaxed + { + cr = ce == cx; + if (cr) { + cx = cd; + } else { + cv = cx; + } + } + +#pragma omp atomic compare capture release + { + cv = cx; + if (ce > cx) { + cx = ce; + } + } +#pragma omp atomic compare capture release + { + cv = cx; + if (cx > ce) { + cx = ce; + } + } +#pragma omp atomic compare capture release + { + cv = cx; + if (ce < cx) { + cx = ce; + } + } +#pragma omp atomic compare capture release + { + cv = cx; + if (cx < ce) { + cx = ce; + } + } +#pragma omp atomic compare capture release + { + cv = cx; + if (cx == ce) { + cx = cd; + } + } +#pragma omp atomic compare capture release + { + cv = cx; + if (ce == cx) { + cx = cd; + } + } +#pragma omp atomic compare capture release + { + if (ce > cx) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture release + { + if (cx > ce) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture release + { + if (ce < cx) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture release + { + if (cx < ce) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture release + { + if (cx == ce) { + cx = cd; + } + cv = cx; + } +#pragma omp atomic compare capture release + { + if (ce == cx) { + cx = cd; + } + cv = cx; + } +#pragma omp atomic compare capture release + if (cx == ce) { + cx = cd; + } else { + cv = cx; + } +#pragma omp atomic compare capture release + if (ce == cx) { + cx = cd; + } else { + cv = cx; + } +#pragma omp atomic compare capture release + { + cr = cx == ce; + if (cr) { + cx = cd; + } + } +#pragma omp atomic compare capture release + { + cr = ce == cx; + if (cr) { + cx = cd; + } + } +#pragma omp atomic compare capture release + { + cr = cx == ce; + if (cr) { + cx = cd; + } else { + cv = cx; + } + } +#pragma omp atomic compare capture release + { + cr = ce == cx; + if (cr) { + cx = cd; + } else { + cv = cx; + } + } + +#pragma omp atomic compare capture seq_cst + { + cv = cx; + if (ce > cx) { + cx = ce; + } + } +#pragma omp atomic compare capture seq_cst + { + cv = cx; + if (cx > ce) { + cx = ce; + } + } +#pragma omp atomic compare capture seq_cst + { + cv = cx; + if (ce < cx) { + cx = ce; + } + } +#pragma omp atomic compare capture seq_cst + { + cv = cx; + if (cx < ce) { + cx = ce; + } + } +#pragma omp atomic compare capture seq_cst + { + cv = cx; + if (cx == ce) { + cx = cd; + } + } +#pragma omp atomic compare capture seq_cst + { + cv = cx; + if (ce == cx) { + cx = cd; + } + } +#pragma omp atomic compare capture seq_cst + { + if (ce > cx) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture seq_cst + { + if (cx > ce) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture seq_cst + { + if (ce < cx) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture seq_cst + { + if (cx < ce) { + cx = ce; + } + cv = cx; + } +#pragma omp atomic compare capture seq_cst + { + if (cx == ce) { + cx = cd; + } + cv = cx; + } +#pragma omp atomic compare capture seq_cst + { + if (ce == cx) { + cx = cd; + } + cv = cx; + } +#pragma omp atomic compare capture seq_cst + if (cx == ce) { + cx = cd; + } else { + cv = cx; + } +#pragma omp atomic compare capture seq_cst + if (ce == cx) { + cx = cd; + } else { + cv = cx; + } +#pragma omp atomic compare capture seq_cst + { + cr = cx == ce; + if (cr) { + cx = cd; + } + } +#pragma omp atomic compare capture seq_cst + { + cr = ce == cx; + if (cr) { + cx = cd; + } + } +#pragma omp atomic compare capture seq_cst + { + cr = cx == ce; + if (cr) { + cx = cd; + } else { + cv = cx; + } + } +#pragma omp atomic compare capture seq_cst + { + cr = ce == cx; + if (cr) { + cx = cd; + } else { + cv = cx; + } + } + +#pragma omp atomic compare capture + { + ucv = ucx; + if (uce > ucx) { + ucx = uce; + } + } +#pragma omp atomic compare capture + { + ucv = ucx; + if (ucx > uce) { + ucx = uce; + } + } +#pragma omp atomic compare capture + { + ucv = ucx; + if (uce < ucx) { + ucx = uce; + } + } +#pragma omp atomic compare capture + { + ucv = ucx; + if (ucx < uce) { + ucx = uce; + } + } +#pragma omp atomic compare capture + { + ucv = ucx; + if (ucx == uce) { + ucx = ucd; + } + } +#pragma omp atomic compare capture + { + ucv = ucx; + if (uce == ucx) { + ucx = ucd; + } + } +#pragma omp atomic compare capture + { + if (uce > ucx) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture + { + if (ucx > uce) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture + { + if (uce < ucx) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture + { + if (ucx < uce) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture + { + if (ucx == uce) { + ucx = ucd; + } + ucv = ucx; + } +#pragma omp atomic compare capture + { + if (uce == ucx) { + ucx = ucd; + } + ucv = ucx; + } +#pragma omp atomic compare capture + if (ucx == uce) { + ucx = ucd; + } else { + ucv = ucx; + } +#pragma omp atomic compare capture + if (uce == ucx) { + ucx = ucd; + } else { + ucv = ucx; + } +#pragma omp atomic compare capture + { + ucr = ucx == uce; + if (ucr) { + ucx = ucd; + } + } +#pragma omp atomic compare capture + { + ucr = uce == ucx; + if (ucr) { + ucx = ucd; + } + } +#pragma omp atomic compare capture + { + ucr = ucx == uce; + if (ucr) { + ucx = ucd; + } else { + ucv = ucx; + } + } +#pragma omp atomic compare capture + { + ucr = uce == ucx; + if (ucr) { + ucx = ucd; + } else { + ucv = ucx; + } + } + +#pragma omp atomic compare capture acq_rel + { + ucv = ucx; + if (uce > ucx) { + ucx = uce; + } + } +#pragma omp atomic compare capture acq_rel + { + ucv = ucx; + if (ucx > uce) { + ucx = uce; + } + } +#pragma omp atomic compare capture acq_rel + { + ucv = ucx; + if (uce < ucx) { + ucx = uce; + } + } +#pragma omp atomic compare capture acq_rel + { + ucv = ucx; + if (ucx < uce) { + ucx = uce; + } + } +#pragma omp atomic compare capture acq_rel + { + ucv = ucx; + if (ucx == uce) { + ucx = ucd; + } + } +#pragma omp atomic compare capture acq_rel + { + ucv = ucx; + if (uce == ucx) { + ucx = ucd; + } + } +#pragma omp atomic compare capture acq_rel + { + if (uce > ucx) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture acq_rel + { + if (ucx > uce) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture acq_rel + { + if (uce < ucx) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture acq_rel + { + if (ucx < uce) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture acq_rel + { + if (ucx == uce) { + ucx = ucd; + } + ucv = ucx; + } +#pragma omp atomic compare capture acq_rel + { + if (uce == ucx) { + ucx = ucd; + } + ucv = ucx; + } +#pragma omp atomic compare capture acq_rel + if (ucx == uce) { + ucx = ucd; + } else { + ucv = ucx; + } +#pragma omp atomic compare capture acq_rel + if (uce == ucx) { + ucx = ucd; + } else { + ucv = ucx; + } +#pragma omp atomic compare capture acq_rel + { + ucr = ucx == uce; + if (ucr) { + ucx = ucd; + } + } +#pragma omp atomic compare capture acq_rel + { + ucr = uce == ucx; + if (ucr) { + ucx = ucd; + } + } +#pragma omp atomic compare capture acq_rel + { + ucr = ucx == uce; + if (ucr) { + ucx = ucd; + } else { + ucv = ucx; + } + } +#pragma omp atomic compare capture acq_rel + { + ucr = uce == ucx; + if (ucr) { + ucx = ucd; + } else { + ucv = ucx; + } + } + +#pragma omp atomic compare capture acquire + { + ucv = ucx; + if (uce > ucx) { + ucx = uce; + } + } +#pragma omp atomic compare capture acquire + { + ucv = ucx; + if (ucx > uce) { + ucx = uce; + } + } +#pragma omp atomic compare capture acquire + { + ucv = ucx; + if (uce < ucx) { + ucx = uce; + } + } +#pragma omp atomic compare capture acquire + { + ucv = ucx; + if (ucx < uce) { + ucx = uce; + } + } +#pragma omp atomic compare capture acquire + { + ucv = ucx; + if (ucx == uce) { + ucx = ucd; + } + } +#pragma omp atomic compare capture acquire + { + ucv = ucx; + if (uce == ucx) { + ucx = ucd; + } + } +#pragma omp atomic compare capture acquire + { + if (uce > ucx) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture acquire + { + if (ucx > uce) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture acquire + { + if (uce < ucx) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture acquire + { + if (ucx < uce) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture acquire + { + if (ucx == uce) { + ucx = ucd; + } + ucv = ucx; + } +#pragma omp atomic compare capture acquire + { + if (uce == ucx) { + ucx = ucd; + } + ucv = ucx; + } +#pragma omp atomic compare capture acquire + if (ucx == uce) { + ucx = ucd; + } else { + ucv = ucx; + } +#pragma omp atomic compare capture acquire + if (uce == ucx) { + ucx = ucd; + } else { + ucv = ucx; + } +#pragma omp atomic compare capture acquire + { + ucr = ucx == uce; + if (ucr) { + ucx = ucd; + } + } +#pragma omp atomic compare capture acquire + { + ucr = uce == ucx; + if (ucr) { + ucx = ucd; + } + } +#pragma omp atomic compare capture acquire + { + ucr = ucx == uce; + if (ucr) { + ucx = ucd; + } else { + ucv = ucx; + } + } +#pragma omp atomic compare capture acquire + { + ucr = uce == ucx; + if (ucr) { + ucx = ucd; + } else { + ucv = ucx; + } + } + +#pragma omp atomic compare capture relaxed + { + ucv = ucx; + if (uce > ucx) { + ucx = uce; + } + } +#pragma omp atomic compare capture relaxed + { + ucv = ucx; + if (ucx > uce) { + ucx = uce; + } + } +#pragma omp atomic compare capture relaxed + { + ucv = ucx; + if (uce < ucx) { + ucx = uce; + } + } +#pragma omp atomic compare capture relaxed + { + ucv = ucx; + if (ucx < uce) { + ucx = uce; + } + } +#pragma omp atomic compare capture relaxed + { + ucv = ucx; + if (ucx == uce) { + ucx = ucd; + } + } +#pragma omp atomic compare capture relaxed + { + ucv = ucx; + if (uce == ucx) { + ucx = ucd; + } + } +#pragma omp atomic compare capture relaxed + { + if (uce > ucx) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture relaxed + { + if (ucx > uce) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture relaxed + { + if (uce < ucx) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture relaxed + { + if (ucx < uce) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture relaxed + { + if (ucx == uce) { + ucx = ucd; + } + ucv = ucx; + } +#pragma omp atomic compare capture relaxed + { + if (uce == ucx) { + ucx = ucd; + } + ucv = ucx; + } +#pragma omp atomic compare capture relaxed + if (ucx == uce) { + ucx = ucd; + } else { + ucv = ucx; + } +#pragma omp atomic compare capture relaxed + if (uce == ucx) { + ucx = ucd; + } else { + ucv = ucx; + } +#pragma omp atomic compare capture relaxed + { + ucr = ucx == uce; + if (ucr) { + ucx = ucd; + } + } +#pragma omp atomic compare capture relaxed + { + ucr = uce == ucx; + if (ucr) { + ucx = ucd; + } + } +#pragma omp atomic compare capture relaxed + { + ucr = ucx == uce; + if (ucr) { + ucx = ucd; + } else { + ucv = ucx; + } + } +#pragma omp atomic compare capture relaxed + { + ucr = uce == ucx; + if (ucr) { + ucx = ucd; + } else { + ucv = ucx; + } + } + +#pragma omp atomic compare capture release + { + ucv = ucx; + if (uce > ucx) { + ucx = uce; + } + } +#pragma omp atomic compare capture release + { + ucv = ucx; + if (ucx > uce) { + ucx = uce; + } + } +#pragma omp atomic compare capture release + { + ucv = ucx; + if (uce < ucx) { + ucx = uce; + } + } +#pragma omp atomic compare capture release + { + ucv = ucx; + if (ucx < uce) { + ucx = uce; + } + } +#pragma omp atomic compare capture release + { + ucv = ucx; + if (ucx == uce) { + ucx = ucd; + } + } +#pragma omp atomic compare capture release + { + ucv = ucx; + if (uce == ucx) { + ucx = ucd; + } + } +#pragma omp atomic compare capture release + { + if (uce > ucx) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture release + { + if (ucx > uce) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture release + { + if (uce < ucx) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture release + { + if (ucx < uce) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture release + { + if (ucx == uce) { + ucx = ucd; + } + ucv = ucx; + } +#pragma omp atomic compare capture release + { + if (uce == ucx) { + ucx = ucd; + } + ucv = ucx; + } +#pragma omp atomic compare capture release + if (ucx == uce) { + ucx = ucd; + } else { + ucv = ucx; + } +#pragma omp atomic compare capture release + if (uce == ucx) { + ucx = ucd; + } else { + ucv = ucx; + } +#pragma omp atomic compare capture release + { + ucr = ucx == uce; + if (ucr) { + ucx = ucd; + } + } +#pragma omp atomic compare capture release + { + ucr = uce == ucx; + if (ucr) { + ucx = ucd; + } + } +#pragma omp atomic compare capture release + { + ucr = ucx == uce; + if (ucr) { + ucx = ucd; + } else { + ucv = ucx; + } + } +#pragma omp atomic compare capture release + { + ucr = uce == ucx; + if (ucr) { + ucx = ucd; + } else { + ucv = ucx; + } + } + +#pragma omp atomic compare capture seq_cst + { + ucv = ucx; + if (uce > ucx) { + ucx = uce; + } + } +#pragma omp atomic compare capture seq_cst + { + ucv = ucx; + if (ucx > uce) { + ucx = uce; + } + } +#pragma omp atomic compare capture seq_cst + { + ucv = ucx; + if (uce < ucx) { + ucx = uce; + } + } +#pragma omp atomic compare capture seq_cst + { + ucv = ucx; + if (ucx < uce) { + ucx = uce; + } + } +#pragma omp atomic compare capture seq_cst + { + ucv = ucx; + if (ucx == uce) { + ucx = ucd; + } + } +#pragma omp atomic compare capture seq_cst + { + ucv = ucx; + if (uce == ucx) { + ucx = ucd; + } + } +#pragma omp atomic compare capture seq_cst + { + if (uce > ucx) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture seq_cst + { + if (ucx > uce) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture seq_cst + { + if (uce < ucx) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture seq_cst + { + if (ucx < uce) { + ucx = uce; + } + ucv = ucx; + } +#pragma omp atomic compare capture seq_cst + { + if (ucx == uce) { + ucx = ucd; + } + ucv = ucx; + } +#pragma omp atomic compare capture seq_cst + { + if (uce == ucx) { + ucx = ucd; + } + ucv = ucx; + } +#pragma omp atomic compare capture seq_cst + if (ucx == uce) { + ucx = ucd; + } else { + ucv = ucx; + } +#pragma omp atomic compare capture seq_cst + if (uce == ucx) { + ucx = ucd; + } else { + ucv = ucx; + } +#pragma omp atomic compare capture seq_cst + { + ucr = ucx == uce; + if (ucr) { + ucx = ucd; + } + } +#pragma omp atomic compare capture seq_cst + { + ucr = uce == ucx; + if (ucr) { + ucx = ucd; + } + } +#pragma omp atomic compare capture seq_cst + { + ucr = ucx == uce; + if (ucr) { + ucx = ucd; + } else { + ucv = ucx; + } + } +#pragma omp atomic compare capture seq_cst + { + ucr = uce == ucx; + if (ucr) { + ucx = ucd; + } else { + ucv = ucx; + } + } + +#pragma omp atomic compare capture + { + sv = sx; + if (se > sx) { + sx = se; + } + } +#pragma omp atomic compare capture + { + sv = sx; + if (sx > se) { + sx = se; + } + } +#pragma omp atomic compare capture + { + sv = sx; + if (se < sx) { + sx = se; + } + } +#pragma omp atomic compare capture + { + sv = sx; + if (sx < se) { + sx = se; + } + } +#pragma omp atomic compare capture + { + sv = sx; + if (sx == se) { + sx = sd; + } + } +#pragma omp atomic compare capture + { + sv = sx; + if (se == sx) { + sx = sd; + } + } +#pragma omp atomic compare capture + { + if (se > sx) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture + { + if (sx > se) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture + { + if (se < sx) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture + { + if (sx < se) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture + { + if (sx == se) { + sx = sd; + } + sv = sx; + } +#pragma omp atomic compare capture + { + if (se == sx) { + sx = sd; + } + sv = sx; + } +#pragma omp atomic compare capture + if (sx == se) { + sx = sd; + } else { + sv = sx; + } +#pragma omp atomic compare capture + if (se == sx) { + sx = sd; + } else { + sv = sx; + } +#pragma omp atomic compare capture + { + sr = sx == se; + if (sr) { + sx = sd; + } + } +#pragma omp atomic compare capture + { + sr = se == sx; + if (sr) { + sx = sd; + } + } +#pragma omp atomic compare capture + { + sr = sx == se; + if (sr) { + sx = sd; + } else { + sv = sx; + } + } +#pragma omp atomic compare capture + { + sr = se == sx; + if (sr) { + sx = sd; + } else { + sv = sx; + } + } + +#pragma omp atomic compare capture acq_rel + { + sv = sx; + if (se > sx) { + sx = se; + } + } +#pragma omp atomic compare capture acq_rel + { + sv = sx; + if (sx > se) { + sx = se; + } + } +#pragma omp atomic compare capture acq_rel + { + sv = sx; + if (se < sx) { + sx = se; + } + } +#pragma omp atomic compare capture acq_rel + { + sv = sx; + if (sx < se) { + sx = se; + } + } +#pragma omp atomic compare capture acq_rel + { + sv = sx; + if (sx == se) { + sx = sd; + } + } +#pragma omp atomic compare capture acq_rel + { + sv = sx; + if (se == sx) { + sx = sd; + } + } +#pragma omp atomic compare capture acq_rel + { + if (se > sx) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture acq_rel + { + if (sx > se) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture acq_rel + { + if (se < sx) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture acq_rel + { + if (sx < se) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture acq_rel + { + if (sx == se) { + sx = sd; + } + sv = sx; + } +#pragma omp atomic compare capture acq_rel + { + if (se == sx) { + sx = sd; + } + sv = sx; + } +#pragma omp atomic compare capture acq_rel + if (sx == se) { + sx = sd; + } else { + sv = sx; + } +#pragma omp atomic compare capture acq_rel + if (se == sx) { + sx = sd; + } else { + sv = sx; + } +#pragma omp atomic compare capture acq_rel + { + sr = sx == se; + if (sr) { + sx = sd; + } + } +#pragma omp atomic compare capture acq_rel + { + sr = se == sx; + if (sr) { + sx = sd; + } + } +#pragma omp atomic compare capture acq_rel + { + sr = sx == se; + if (sr) { + sx = sd; + } else { + sv = sx; + } + } +#pragma omp atomic compare capture acq_rel + { + sr = se == sx; + if (sr) { + sx = sd; + } else { + sv = sx; + } + } + +#pragma omp atomic compare capture acquire + { + sv = sx; + if (se > sx) { + sx = se; + } + } +#pragma omp atomic compare capture acquire + { + sv = sx; + if (sx > se) { + sx = se; + } + } +#pragma omp atomic compare capture acquire + { + sv = sx; + if (se < sx) { + sx = se; + } + } +#pragma omp atomic compare capture acquire + { + sv = sx; + if (sx < se) { + sx = se; + } + } +#pragma omp atomic compare capture acquire + { + sv = sx; + if (sx == se) { + sx = sd; + } + } +#pragma omp atomic compare capture acquire + { + sv = sx; + if (se == sx) { + sx = sd; + } + } +#pragma omp atomic compare capture acquire + { + if (se > sx) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture acquire + { + if (sx > se) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture acquire + { + if (se < sx) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture acquire + { + if (sx < se) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture acquire + { + if (sx == se) { + sx = sd; + } + sv = sx; + } +#pragma omp atomic compare capture acquire + { + if (se == sx) { + sx = sd; + } + sv = sx; + } +#pragma omp atomic compare capture acquire + if (sx == se) { + sx = sd; + } else { + sv = sx; + } +#pragma omp atomic compare capture acquire + if (se == sx) { + sx = sd; + } else { + sv = sx; + } +#pragma omp atomic compare capture acquire + { + sr = sx == se; + if (sr) { + sx = sd; + } + } +#pragma omp atomic compare capture acquire + { + sr = se == sx; + if (sr) { + sx = sd; + } + } +#pragma omp atomic compare capture acquire + { + sr = sx == se; + if (sr) { + sx = sd; + } else { + sv = sx; + } + } +#pragma omp atomic compare capture acquire + { + sr = se == sx; + if (sr) { + sx = sd; + } else { + sv = sx; + } + } + +#pragma omp atomic compare capture relaxed + { + sv = sx; + if (se > sx) { + sx = se; + } + } +#pragma omp atomic compare capture relaxed + { + sv = sx; + if (sx > se) { + sx = se; + } + } +#pragma omp atomic compare capture relaxed + { + sv = sx; + if (se < sx) { + sx = se; + } + } +#pragma omp atomic compare capture relaxed + { + sv = sx; + if (sx < se) { + sx = se; + } + } +#pragma omp atomic compare capture relaxed + { + sv = sx; + if (sx == se) { + sx = sd; + } + } +#pragma omp atomic compare capture relaxed + { + sv = sx; + if (se == sx) { + sx = sd; + } + } +#pragma omp atomic compare capture relaxed + { + if (se > sx) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture relaxed + { + if (sx > se) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture relaxed + { + if (se < sx) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture relaxed + { + if (sx < se) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture relaxed + { + if (sx == se) { + sx = sd; + } + sv = sx; + } +#pragma omp atomic compare capture relaxed + { + if (se == sx) { + sx = sd; + } + sv = sx; + } +#pragma omp atomic compare capture relaxed + if (sx == se) { + sx = sd; + } else { + sv = sx; + } +#pragma omp atomic compare capture relaxed + if (se == sx) { + sx = sd; + } else { + sv = sx; + } +#pragma omp atomic compare capture relaxed + { + sr = sx == se; + if (sr) { + sx = sd; + } + } +#pragma omp atomic compare capture relaxed + { + sr = se == sx; + if (sr) { + sx = sd; + } + } +#pragma omp atomic compare capture relaxed + { + sr = sx == se; + if (sr) { + sx = sd; + } else { + sv = sx; + } + } +#pragma omp atomic compare capture relaxed + { + sr = se == sx; + if (sr) { + sx = sd; + } else { + sv = sx; + } + } + +#pragma omp atomic compare capture release + { + sv = sx; + if (se > sx) { + sx = se; + } + } +#pragma omp atomic compare capture release + { + sv = sx; + if (sx > se) { + sx = se; + } + } +#pragma omp atomic compare capture release + { + sv = sx; + if (se < sx) { + sx = se; + } + } +#pragma omp atomic compare capture release + { + sv = sx; + if (sx < se) { + sx = se; + } + } +#pragma omp atomic compare capture release + { + sv = sx; + if (sx == se) { + sx = sd; + } + } +#pragma omp atomic compare capture release + { + sv = sx; + if (se == sx) { + sx = sd; + } + } +#pragma omp atomic compare capture release + { + if (se > sx) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture release + { + if (sx > se) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture release + { + if (se < sx) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture release + { + if (sx < se) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture release + { + if (sx == se) { + sx = sd; + } + sv = sx; + } +#pragma omp atomic compare capture release + { + if (se == sx) { + sx = sd; + } + sv = sx; + } +#pragma omp atomic compare capture release + if (sx == se) { + sx = sd; + } else { + sv = sx; + } +#pragma omp atomic compare capture release + if (se == sx) { + sx = sd; + } else { + sv = sx; + } +#pragma omp atomic compare capture release + { + sr = sx == se; + if (sr) { + sx = sd; + } + } +#pragma omp atomic compare capture release + { + sr = se == sx; + if (sr) { + sx = sd; + } + } +#pragma omp atomic compare capture release + { + sr = sx == se; + if (sr) { + sx = sd; + } else { + sv = sx; + } + } +#pragma omp atomic compare capture release + { + sr = se == sx; + if (sr) { + sx = sd; + } else { + sv = sx; + } + } + +#pragma omp atomic compare capture seq_cst + { + sv = sx; + if (se > sx) { + sx = se; + } + } +#pragma omp atomic compare capture seq_cst + { + sv = sx; + if (sx > se) { + sx = se; + } + } +#pragma omp atomic compare capture seq_cst + { + sv = sx; + if (se < sx) { + sx = se; + } + } +#pragma omp atomic compare capture seq_cst + { + sv = sx; + if (sx < se) { + sx = se; + } + } +#pragma omp atomic compare capture seq_cst + { + sv = sx; + if (sx == se) { + sx = sd; + } + } +#pragma omp atomic compare capture seq_cst + { + sv = sx; + if (se == sx) { + sx = sd; + } + } +#pragma omp atomic compare capture seq_cst + { + if (se > sx) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture seq_cst + { + if (sx > se) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture seq_cst + { + if (se < sx) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture seq_cst + { + if (sx < se) { + sx = se; + } + sv = sx; + } +#pragma omp atomic compare capture seq_cst + { + if (sx == se) { + sx = sd; + } + sv = sx; + } +#pragma omp atomic compare capture seq_cst + { + if (se == sx) { + sx = sd; + } + sv = sx; + } +#pragma omp atomic compare capture seq_cst + if (sx == se) { + sx = sd; + } else { + sv = sx; + } +#pragma omp atomic compare capture seq_cst + if (se == sx) { + sx = sd; + } else { + sv = sx; + } +#pragma omp atomic compare capture seq_cst + { + sr = sx == se; + if (sr) { + sx = sd; + } + } +#pragma omp atomic compare capture seq_cst + { + sr = se == sx; + if (sr) { + sx = sd; + } + } +#pragma omp atomic compare capture seq_cst + { + sr = sx == se; + if (sr) { + sx = sd; + } else { + sv = sx; + } + } +#pragma omp atomic compare capture seq_cst + { + sr = se == sx; + if (sr) { + sx = sd; + } else { + sv = sx; + } + } + +#pragma omp atomic compare capture + { + usv = usx; + if (use > usx) { + usx = use; + } + } +#pragma omp atomic compare capture + { + usv = usx; + if (usx > use) { + usx = use; + } + } +#pragma omp atomic compare capture + { + usv = usx; + if (use < usx) { + usx = use; + } + } +#pragma omp atomic compare capture + { + usv = usx; + if (usx < use) { + usx = use; + } + } +#pragma omp atomic compare capture + { + usv = usx; + if (usx == use) { + usx = usd; + } + } +#pragma omp atomic compare capture + { + usv = usx; + if (use == usx) { + usx = usd; + } + } +#pragma omp atomic compare capture + { + if (use > usx) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture + { + if (usx > use) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture + { + if (use < usx) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture + { + if (usx < use) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture + { + if (usx == use) { + usx = usd; + } + usv = usx; + } +#pragma omp atomic compare capture + { + if (use == usx) { + usx = usd; + } + usv = usx; + } +#pragma omp atomic compare capture + if (usx == use) { + usx = usd; + } else { + usv = usx; + } +#pragma omp atomic compare capture + if (use == usx) { + usx = usd; + } else { + usv = usx; + } +#pragma omp atomic compare capture + { + usr = usx == use; + if (usr) { + usx = usd; + } + } +#pragma omp atomic compare capture + { + usr = use == usx; + if (usr) { + usx = usd; + } + } +#pragma omp atomic compare capture + { + usr = usx == use; + if (usr) { + usx = usd; + } else { + usv = usx; + } + } +#pragma omp atomic compare capture + { + usr = use == usx; + if (usr) { + usx = usd; + } else { + usv = usx; + } + } + +#pragma omp atomic compare capture acq_rel + { + usv = usx; + if (use > usx) { + usx = use; + } + } +#pragma omp atomic compare capture acq_rel + { + usv = usx; + if (usx > use) { + usx = use; + } + } +#pragma omp atomic compare capture acq_rel + { + usv = usx; + if (use < usx) { + usx = use; + } + } +#pragma omp atomic compare capture acq_rel + { + usv = usx; + if (usx < use) { + usx = use; + } + } +#pragma omp atomic compare capture acq_rel + { + usv = usx; + if (usx == use) { + usx = usd; + } + } +#pragma omp atomic compare capture acq_rel + { + usv = usx; + if (use == usx) { + usx = usd; + } + } +#pragma omp atomic compare capture acq_rel + { + if (use > usx) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture acq_rel + { + if (usx > use) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture acq_rel + { + if (use < usx) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture acq_rel + { + if (usx < use) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture acq_rel + { + if (usx == use) { + usx = usd; + } + usv = usx; + } +#pragma omp atomic compare capture acq_rel + { + if (use == usx) { + usx = usd; + } + usv = usx; + } +#pragma omp atomic compare capture acq_rel + if (usx == use) { + usx = usd; + } else { + usv = usx; + } +#pragma omp atomic compare capture acq_rel + if (use == usx) { + usx = usd; + } else { + usv = usx; + } +#pragma omp atomic compare capture acq_rel + { + usr = usx == use; + if (usr) { + usx = usd; + } + } +#pragma omp atomic compare capture acq_rel + { + usr = use == usx; + if (usr) { + usx = usd; + } + } +#pragma omp atomic compare capture acq_rel + { + usr = usx == use; + if (usr) { + usx = usd; + } else { + usv = usx; + } + } +#pragma omp atomic compare capture acq_rel + { + usr = use == usx; + if (usr) { + usx = usd; + } else { + usv = usx; + } + } + +#pragma omp atomic compare capture acquire + { + usv = usx; + if (use > usx) { + usx = use; + } + } +#pragma omp atomic compare capture acquire + { + usv = usx; + if (usx > use) { + usx = use; + } + } +#pragma omp atomic compare capture acquire + { + usv = usx; + if (use < usx) { + usx = use; + } + } +#pragma omp atomic compare capture acquire + { + usv = usx; + if (usx < use) { + usx = use; + } + } +#pragma omp atomic compare capture acquire + { + usv = usx; + if (usx == use) { + usx = usd; + } + } +#pragma omp atomic compare capture acquire + { + usv = usx; + if (use == usx) { + usx = usd; + } + } +#pragma omp atomic compare capture acquire + { + if (use > usx) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture acquire + { + if (usx > use) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture acquire + { + if (use < usx) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture acquire + { + if (usx < use) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture acquire + { + if (usx == use) { + usx = usd; + } + usv = usx; + } +#pragma omp atomic compare capture acquire + { + if (use == usx) { + usx = usd; + } + usv = usx; + } +#pragma omp atomic compare capture acquire + if (usx == use) { + usx = usd; + } else { + usv = usx; + } +#pragma omp atomic compare capture acquire + if (use == usx) { + usx = usd; + } else { + usv = usx; + } +#pragma omp atomic compare capture acquire + { + usr = usx == use; + if (usr) { + usx = usd; + } + } +#pragma omp atomic compare capture acquire + { + usr = use == usx; + if (usr) { + usx = usd; + } + } +#pragma omp atomic compare capture acquire + { + usr = usx == use; + if (usr) { + usx = usd; + } else { + usv = usx; + } + } +#pragma omp atomic compare capture acquire + { + usr = use == usx; + if (usr) { + usx = usd; + } else { + usv = usx; + } + } + +#pragma omp atomic compare capture relaxed + { + usv = usx; + if (use > usx) { + usx = use; + } + } +#pragma omp atomic compare capture relaxed + { + usv = usx; + if (usx > use) { + usx = use; + } + } +#pragma omp atomic compare capture relaxed + { + usv = usx; + if (use < usx) { + usx = use; + } + } +#pragma omp atomic compare capture relaxed + { + usv = usx; + if (usx < use) { + usx = use; + } + } +#pragma omp atomic compare capture relaxed + { + usv = usx; + if (usx == use) { + usx = usd; + } + } +#pragma omp atomic compare capture relaxed + { + usv = usx; + if (use == usx) { + usx = usd; + } + } +#pragma omp atomic compare capture relaxed + { + if (use > usx) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture relaxed + { + if (usx > use) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture relaxed + { + if (use < usx) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture relaxed + { + if (usx < use) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture relaxed + { + if (usx == use) { + usx = usd; + } + usv = usx; + } +#pragma omp atomic compare capture relaxed + { + if (use == usx) { + usx = usd; + } + usv = usx; + } +#pragma omp atomic compare capture relaxed + if (usx == use) { + usx = usd; + } else { + usv = usx; + } +#pragma omp atomic compare capture relaxed + if (use == usx) { + usx = usd; + } else { + usv = usx; + } +#pragma omp atomic compare capture relaxed + { + usr = usx == use; + if (usr) { + usx = usd; + } + } +#pragma omp atomic compare capture relaxed + { + usr = use == usx; + if (usr) { + usx = usd; + } + } +#pragma omp atomic compare capture relaxed + { + usr = usx == use; + if (usr) { + usx = usd; + } else { + usv = usx; + } + } +#pragma omp atomic compare capture relaxed + { + usr = use == usx; + if (usr) { + usx = usd; + } else { + usv = usx; + } + } + +#pragma omp atomic compare capture release + { + usv = usx; + if (use > usx) { + usx = use; + } + } +#pragma omp atomic compare capture release + { + usv = usx; + if (usx > use) { + usx = use; + } + } +#pragma omp atomic compare capture release + { + usv = usx; + if (use < usx) { + usx = use; + } + } +#pragma omp atomic compare capture release + { + usv = usx; + if (usx < use) { + usx = use; + } + } +#pragma omp atomic compare capture release + { + usv = usx; + if (usx == use) { + usx = usd; + } + } +#pragma omp atomic compare capture release + { + usv = usx; + if (use == usx) { + usx = usd; + } + } +#pragma omp atomic compare capture release + { + if (use > usx) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture release + { + if (usx > use) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture release + { + if (use < usx) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture release + { + if (usx < use) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture release + { + if (usx == use) { + usx = usd; + } + usv = usx; + } +#pragma omp atomic compare capture release + { + if (use == usx) { + usx = usd; + } + usv = usx; + } +#pragma omp atomic compare capture release + if (usx == use) { + usx = usd; + } else { + usv = usx; + } +#pragma omp atomic compare capture release + if (use == usx) { + usx = usd; + } else { + usv = usx; + } +#pragma omp atomic compare capture release + { + usr = usx == use; + if (usr) { + usx = usd; + } + } +#pragma omp atomic compare capture release + { + usr = use == usx; + if (usr) { + usx = usd; + } + } +#pragma omp atomic compare capture release + { + usr = usx == use; + if (usr) { + usx = usd; + } else { + usv = usx; + } + } +#pragma omp atomic compare capture release + { + usr = use == usx; + if (usr) { + usx = usd; + } else { + usv = usx; + } + } + +#pragma omp atomic compare capture seq_cst + { + usv = usx; + if (use > usx) { + usx = use; + } + } +#pragma omp atomic compare capture seq_cst + { + usv = usx; + if (usx > use) { + usx = use; + } + } +#pragma omp atomic compare capture seq_cst + { + usv = usx; + if (use < usx) { + usx = use; + } + } +#pragma omp atomic compare capture seq_cst + { + usv = usx; + if (usx < use) { + usx = use; + } + } +#pragma omp atomic compare capture seq_cst + { + usv = usx; + if (usx == use) { + usx = usd; + } + } +#pragma omp atomic compare capture seq_cst + { + usv = usx; + if (use == usx) { + usx = usd; + } + } +#pragma omp atomic compare capture seq_cst + { + if (use > usx) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture seq_cst + { + if (usx > use) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture seq_cst + { + if (use < usx) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture seq_cst + { + if (usx < use) { + usx = use; + } + usv = usx; + } +#pragma omp atomic compare capture seq_cst + { + if (usx == use) { + usx = usd; + } + usv = usx; + } +#pragma omp atomic compare capture seq_cst + { + if (use == usx) { + usx = usd; + } + usv = usx; + } +#pragma omp atomic compare capture seq_cst + if (usx == use) { + usx = usd; + } else { + usv = usx; + } +#pragma omp atomic compare capture seq_cst + if (use == usx) { + usx = usd; + } else { + usv = usx; + } +#pragma omp atomic compare capture seq_cst + { + usr = usx == use; + if (usr) { + usx = usd; + } + } +#pragma omp atomic compare capture seq_cst + { + usr = use == usx; + if (usr) { + usx = usd; + } + } +#pragma omp atomic compare capture seq_cst + { + usr = usx == use; + if (usr) { + usx = usd; + } else { + usv = usx; + } + } +#pragma omp atomic compare capture seq_cst + { + usr = use == usx; + if (usr) { + usx = usd; + } else { + usv = usx; + } + } + +#pragma omp atomic compare capture + { + iv = ix; + if (ie > ix) { + ix = ie; + } + } +#pragma omp atomic compare capture + { + iv = ix; + if (ix > ie) { + ix = ie; + } + } +#pragma omp atomic compare capture + { + iv = ix; + if (ie < ix) { + ix = ie; + } + } +#pragma omp atomic compare capture + { + iv = ix; + if (ix < ie) { + ix = ie; + } + } +#pragma omp atomic compare capture + { + iv = ix; + if (ix == ie) { + ix = id; + } + } +#pragma omp atomic compare capture + { + iv = ix; + if (ie == ix) { + ix = id; + } + } +#pragma omp atomic compare capture + { + if (ie > ix) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture + { + if (ix > ie) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture + { + if (ie < ix) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture + { + if (ix < ie) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture + { + if (ix == ie) { + ix = id; + } + iv = ix; + } +#pragma omp atomic compare capture + { + if (ie == ix) { + ix = id; + } + iv = ix; + } +#pragma omp atomic compare capture + if (ix == ie) { + ix = id; + } else { + iv = ix; + } +#pragma omp atomic compare capture + if (ie == ix) { + ix = id; + } else { + iv = ix; + } +#pragma omp atomic compare capture + { + ir = ix == ie; + if (ir) { + ix = id; + } + } +#pragma omp atomic compare capture + { + ir = ie == ix; + if (ir) { + ix = id; + } + } +#pragma omp atomic compare capture + { + ir = ix == ie; + if (ir) { + ix = id; + } else { + iv = ix; + } + } +#pragma omp atomic compare capture + { + ir = ie == ix; + if (ir) { + ix = id; + } else { + iv = ix; + } + } + +#pragma omp atomic compare capture acq_rel + { + iv = ix; + if (ie > ix) { + ix = ie; + } + } +#pragma omp atomic compare capture acq_rel + { + iv = ix; + if (ix > ie) { + ix = ie; + } + } +#pragma omp atomic compare capture acq_rel + { + iv = ix; + if (ie < ix) { + ix = ie; + } + } +#pragma omp atomic compare capture acq_rel + { + iv = ix; + if (ix < ie) { + ix = ie; + } + } +#pragma omp atomic compare capture acq_rel + { + iv = ix; + if (ix == ie) { + ix = id; + } + } +#pragma omp atomic compare capture acq_rel + { + iv = ix; + if (ie == ix) { + ix = id; + } + } +#pragma omp atomic compare capture acq_rel + { + if (ie > ix) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture acq_rel + { + if (ix > ie) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture acq_rel + { + if (ie < ix) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture acq_rel + { + if (ix < ie) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture acq_rel + { + if (ix == ie) { + ix = id; + } + iv = ix; + } +#pragma omp atomic compare capture acq_rel + { + if (ie == ix) { + ix = id; + } + iv = ix; + } +#pragma omp atomic compare capture acq_rel + if (ix == ie) { + ix = id; + } else { + iv = ix; + } +#pragma omp atomic compare capture acq_rel + if (ie == ix) { + ix = id; + } else { + iv = ix; + } +#pragma omp atomic compare capture acq_rel + { + ir = ix == ie; + if (ir) { + ix = id; + } + } +#pragma omp atomic compare capture acq_rel + { + ir = ie == ix; + if (ir) { + ix = id; + } + } +#pragma omp atomic compare capture acq_rel + { + ir = ix == ie; + if (ir) { + ix = id; + } else { + iv = ix; + } + } +#pragma omp atomic compare capture acq_rel + { + ir = ie == ix; + if (ir) { + ix = id; + } else { + iv = ix; + } + } + +#pragma omp atomic compare capture acquire + { + iv = ix; + if (ie > ix) { + ix = ie; + } + } +#pragma omp atomic compare capture acquire + { + iv = ix; + if (ix > ie) { + ix = ie; + } + } +#pragma omp atomic compare capture acquire + { + iv = ix; + if (ie < ix) { + ix = ie; + } + } +#pragma omp atomic compare capture acquire + { + iv = ix; + if (ix < ie) { + ix = ie; + } + } +#pragma omp atomic compare capture acquire + { + iv = ix; + if (ix == ie) { + ix = id; + } + } +#pragma omp atomic compare capture acquire + { + iv = ix; + if (ie == ix) { + ix = id; + } + } +#pragma omp atomic compare capture acquire + { + if (ie > ix) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture acquire + { + if (ix > ie) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture acquire + { + if (ie < ix) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture acquire + { + if (ix < ie) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture acquire + { + if (ix == ie) { + ix = id; + } + iv = ix; + } +#pragma omp atomic compare capture acquire + { + if (ie == ix) { + ix = id; + } + iv = ix; + } +#pragma omp atomic compare capture acquire + if (ix == ie) { + ix = id; + } else { + iv = ix; + } +#pragma omp atomic compare capture acquire + if (ie == ix) { + ix = id; + } else { + iv = ix; + } +#pragma omp atomic compare capture acquire + { + ir = ix == ie; + if (ir) { + ix = id; + } + } +#pragma omp atomic compare capture acquire + { + ir = ie == ix; + if (ir) { + ix = id; + } + } +#pragma omp atomic compare capture acquire + { + ir = ix == ie; + if (ir) { + ix = id; + } else { + iv = ix; + } + } +#pragma omp atomic compare capture acquire + { + ir = ie == ix; + if (ir) { + ix = id; + } else { + iv = ix; + } + } + +#pragma omp atomic compare capture relaxed + { + iv = ix; + if (ie > ix) { + ix = ie; + } + } +#pragma omp atomic compare capture relaxed + { + iv = ix; + if (ix > ie) { + ix = ie; + } + } +#pragma omp atomic compare capture relaxed + { + iv = ix; + if (ie < ix) { + ix = ie; + } + } +#pragma omp atomic compare capture relaxed + { + iv = ix; + if (ix < ie) { + ix = ie; + } + } +#pragma omp atomic compare capture relaxed + { + iv = ix; + if (ix == ie) { + ix = id; + } + } +#pragma omp atomic compare capture relaxed + { + iv = ix; + if (ie == ix) { + ix = id; + } + } +#pragma omp atomic compare capture relaxed + { + if (ie > ix) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture relaxed + { + if (ix > ie) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture relaxed + { + if (ie < ix) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture relaxed + { + if (ix < ie) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture relaxed + { + if (ix == ie) { + ix = id; + } + iv = ix; + } +#pragma omp atomic compare capture relaxed + { + if (ie == ix) { + ix = id; + } + iv = ix; + } +#pragma omp atomic compare capture relaxed + if (ix == ie) { + ix = id; + } else { + iv = ix; + } +#pragma omp atomic compare capture relaxed + if (ie == ix) { + ix = id; + } else { + iv = ix; + } +#pragma omp atomic compare capture relaxed + { + ir = ix == ie; + if (ir) { + ix = id; + } + } +#pragma omp atomic compare capture relaxed + { + ir = ie == ix; + if (ir) { + ix = id; + } + } +#pragma omp atomic compare capture relaxed + { + ir = ix == ie; + if (ir) { + ix = id; + } else { + iv = ix; + } + } +#pragma omp atomic compare capture relaxed + { + ir = ie == ix; + if (ir) { + ix = id; + } else { + iv = ix; + } + } + +#pragma omp atomic compare capture release + { + iv = ix; + if (ie > ix) { + ix = ie; + } + } +#pragma omp atomic compare capture release + { + iv = ix; + if (ix > ie) { + ix = ie; + } + } +#pragma omp atomic compare capture release + { + iv = ix; + if (ie < ix) { + ix = ie; + } + } +#pragma omp atomic compare capture release + { + iv = ix; + if (ix < ie) { + ix = ie; + } + } +#pragma omp atomic compare capture release + { + iv = ix; + if (ix == ie) { + ix = id; + } + } +#pragma omp atomic compare capture release + { + iv = ix; + if (ie == ix) { + ix = id; + } + } +#pragma omp atomic compare capture release + { + if (ie > ix) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture release + { + if (ix > ie) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture release + { + if (ie < ix) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture release + { + if (ix < ie) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture release + { + if (ix == ie) { + ix = id; + } + iv = ix; + } +#pragma omp atomic compare capture release + { + if (ie == ix) { + ix = id; + } + iv = ix; + } +#pragma omp atomic compare capture release + if (ix == ie) { + ix = id; + } else { + iv = ix; + } +#pragma omp atomic compare capture release + if (ie == ix) { + ix = id; + } else { + iv = ix; + } +#pragma omp atomic compare capture release + { + ir = ix == ie; + if (ir) { + ix = id; + } + } +#pragma omp atomic compare capture release + { + ir = ie == ix; + if (ir) { + ix = id; + } + } +#pragma omp atomic compare capture release + { + ir = ix == ie; + if (ir) { + ix = id; + } else { + iv = ix; + } + } +#pragma omp atomic compare capture release + { + ir = ie == ix; + if (ir) { + ix = id; + } else { + iv = ix; + } + } + +#pragma omp atomic compare capture seq_cst + { + iv = ix; + if (ie > ix) { + ix = ie; + } + } +#pragma omp atomic compare capture seq_cst + { + iv = ix; + if (ix > ie) { + ix = ie; + } + } +#pragma omp atomic compare capture seq_cst + { + iv = ix; + if (ie < ix) { + ix = ie; + } + } +#pragma omp atomic compare capture seq_cst + { + iv = ix; + if (ix < ie) { + ix = ie; + } + } +#pragma omp atomic compare capture seq_cst + { + iv = ix; + if (ix == ie) { + ix = id; + } + } +#pragma omp atomic compare capture seq_cst + { + iv = ix; + if (ie == ix) { + ix = id; + } + } +#pragma omp atomic compare capture seq_cst + { + if (ie > ix) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture seq_cst + { + if (ix > ie) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture seq_cst + { + if (ie < ix) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture seq_cst + { + if (ix < ie) { + ix = ie; + } + iv = ix; + } +#pragma omp atomic compare capture seq_cst + { + if (ix == ie) { + ix = id; + } + iv = ix; + } +#pragma omp atomic compare capture seq_cst + { + if (ie == ix) { + ix = id; + } + iv = ix; + } +#pragma omp atomic compare capture seq_cst + if (ix == ie) { + ix = id; + } else { + iv = ix; + } +#pragma omp atomic compare capture seq_cst + if (ie == ix) { + ix = id; + } else { + iv = ix; + } +#pragma omp atomic compare capture seq_cst + { + ir = ix == ie; + if (ir) { + ix = id; + } + } +#pragma omp atomic compare capture seq_cst + { + ir = ie == ix; + if (ir) { + ix = id; + } + } +#pragma omp atomic compare capture seq_cst + { + ir = ix == ie; + if (ir) { + ix = id; + } else { + iv = ix; + } + } +#pragma omp atomic compare capture seq_cst + { + ir = ie == ix; + if (ir) { + ix = id; + } else { + iv = ix; + } + } + +#pragma omp atomic compare capture + { + uiv = uix; + if (uie > uix) { + uix = uie; + } + } +#pragma omp atomic compare capture + { + uiv = uix; + if (uix > uie) { + uix = uie; + } + } +#pragma omp atomic compare capture + { + uiv = uix; + if (uie < uix) { + uix = uie; + } + } +#pragma omp atomic compare capture + { + uiv = uix; + if (uix < uie) { + uix = uie; + } + } +#pragma omp atomic compare capture + { + uiv = uix; + if (uix == uie) { + uix = uid; + } + } +#pragma omp atomic compare capture + { + uiv = uix; + if (uie == uix) { + uix = uid; + } + } +#pragma omp atomic compare capture + { + if (uie > uix) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture + { + if (uix > uie) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture + { + if (uie < uix) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture + { + if (uix < uie) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture + { + if (uix == uie) { + uix = uid; + } + uiv = uix; + } +#pragma omp atomic compare capture + { + if (uie == uix) { + uix = uid; + } + uiv = uix; + } +#pragma omp atomic compare capture + if (uix == uie) { + uix = uid; + } else { + uiv = uix; + } +#pragma omp atomic compare capture + if (uie == uix) { + uix = uid; + } else { + uiv = uix; + } +#pragma omp atomic compare capture + { + uir = uix == uie; + if (uir) { + uix = uid; + } + } +#pragma omp atomic compare capture + { + uir = uie == uix; + if (uir) { + uix = uid; + } + } +#pragma omp atomic compare capture + { + uir = uix == uie; + if (uir) { + uix = uid; + } else { + uiv = uix; + } + } +#pragma omp atomic compare capture + { + uir = uie == uix; + if (uir) { + uix = uid; + } else { + uiv = uix; + } + } + +#pragma omp atomic compare capture acq_rel + { + uiv = uix; + if (uie > uix) { + uix = uie; + } + } +#pragma omp atomic compare capture acq_rel + { + uiv = uix; + if (uix > uie) { + uix = uie; + } + } +#pragma omp atomic compare capture acq_rel + { + uiv = uix; + if (uie < uix) { + uix = uie; + } + } +#pragma omp atomic compare capture acq_rel + { + uiv = uix; + if (uix < uie) { + uix = uie; + } + } +#pragma omp atomic compare capture acq_rel + { + uiv = uix; + if (uix == uie) { + uix = uid; + } + } +#pragma omp atomic compare capture acq_rel + { + uiv = uix; + if (uie == uix) { + uix = uid; + } + } +#pragma omp atomic compare capture acq_rel + { + if (uie > uix) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture acq_rel + { + if (uix > uie) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture acq_rel + { + if (uie < uix) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture acq_rel + { + if (uix < uie) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture acq_rel + { + if (uix == uie) { + uix = uid; + } + uiv = uix; + } +#pragma omp atomic compare capture acq_rel + { + if (uie == uix) { + uix = uid; + } + uiv = uix; + } +#pragma omp atomic compare capture acq_rel + if (uix == uie) { + uix = uid; + } else { + uiv = uix; + } +#pragma omp atomic compare capture acq_rel + if (uie == uix) { + uix = uid; + } else { + uiv = uix; + } +#pragma omp atomic compare capture acq_rel + { + uir = uix == uie; + if (uir) { + uix = uid; + } + } +#pragma omp atomic compare capture acq_rel + { + uir = uie == uix; + if (uir) { + uix = uid; + } + } +#pragma omp atomic compare capture acq_rel + { + uir = uix == uie; + if (uir) { + uix = uid; + } else { + uiv = uix; + } + } +#pragma omp atomic compare capture acq_rel + { + uir = uie == uix; + if (uir) { + uix = uid; + } else { + uiv = uix; + } + } + +#pragma omp atomic compare capture acquire + { + uiv = uix; + if (uie > uix) { + uix = uie; + } + } +#pragma omp atomic compare capture acquire + { + uiv = uix; + if (uix > uie) { + uix = uie; + } + } +#pragma omp atomic compare capture acquire + { + uiv = uix; + if (uie < uix) { + uix = uie; + } + } +#pragma omp atomic compare capture acquire + { + uiv = uix; + if (uix < uie) { + uix = uie; + } + } +#pragma omp atomic compare capture acquire + { + uiv = uix; + if (uix == uie) { + uix = uid; + } + } +#pragma omp atomic compare capture acquire + { + uiv = uix; + if (uie == uix) { + uix = uid; + } + } +#pragma omp atomic compare capture acquire + { + if (uie > uix) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture acquire + { + if (uix > uie) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture acquire + { + if (uie < uix) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture acquire + { + if (uix < uie) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture acquire + { + if (uix == uie) { + uix = uid; + } + uiv = uix; + } +#pragma omp atomic compare capture acquire + { + if (uie == uix) { + uix = uid; + } + uiv = uix; + } +#pragma omp atomic compare capture acquire + if (uix == uie) { + uix = uid; + } else { + uiv = uix; + } +#pragma omp atomic compare capture acquire + if (uie == uix) { + uix = uid; + } else { + uiv = uix; + } +#pragma omp atomic compare capture acquire + { + uir = uix == uie; + if (uir) { + uix = uid; + } + } +#pragma omp atomic compare capture acquire + { + uir = uie == uix; + if (uir) { + uix = uid; + } + } +#pragma omp atomic compare capture acquire + { + uir = uix == uie; + if (uir) { + uix = uid; + } else { + uiv = uix; + } + } +#pragma omp atomic compare capture acquire + { + uir = uie == uix; + if (uir) { + uix = uid; + } else { + uiv = uix; + } + } + +#pragma omp atomic compare capture relaxed + { + uiv = uix; + if (uie > uix) { + uix = uie; + } + } +#pragma omp atomic compare capture relaxed + { + uiv = uix; + if (uix > uie) { + uix = uie; + } + } +#pragma omp atomic compare capture relaxed + { + uiv = uix; + if (uie < uix) { + uix = uie; + } + } +#pragma omp atomic compare capture relaxed + { + uiv = uix; + if (uix < uie) { + uix = uie; + } + } +#pragma omp atomic compare capture relaxed + { + uiv = uix; + if (uix == uie) { + uix = uid; + } + } +#pragma omp atomic compare capture relaxed + { + uiv = uix; + if (uie == uix) { + uix = uid; + } + } +#pragma omp atomic compare capture relaxed + { + if (uie > uix) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture relaxed + { + if (uix > uie) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture relaxed + { + if (uie < uix) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture relaxed + { + if (uix < uie) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture relaxed + { + if (uix == uie) { + uix = uid; + } + uiv = uix; + } +#pragma omp atomic compare capture relaxed + { + if (uie == uix) { + uix = uid; + } + uiv = uix; + } +#pragma omp atomic compare capture relaxed + if (uix == uie) { + uix = uid; + } else { + uiv = uix; + } +#pragma omp atomic compare capture relaxed + if (uie == uix) { + uix = uid; + } else { + uiv = uix; + } +#pragma omp atomic compare capture relaxed + { + uir = uix == uie; + if (uir) { + uix = uid; + } + } +#pragma omp atomic compare capture relaxed + { + uir = uie == uix; + if (uir) { + uix = uid; + } + } +#pragma omp atomic compare capture relaxed + { + uir = uix == uie; + if (uir) { + uix = uid; + } else { + uiv = uix; + } + } +#pragma omp atomic compare capture relaxed + { + uir = uie == uix; + if (uir) { + uix = uid; + } else { + uiv = uix; + } + } + +#pragma omp atomic compare capture release + { + uiv = uix; + if (uie > uix) { + uix = uie; + } + } +#pragma omp atomic compare capture release + { + uiv = uix; + if (uix > uie) { + uix = uie; + } + } +#pragma omp atomic compare capture release + { + uiv = uix; + if (uie < uix) { + uix = uie; + } + } +#pragma omp atomic compare capture release + { + uiv = uix; + if (uix < uie) { + uix = uie; + } + } +#pragma omp atomic compare capture release + { + uiv = uix; + if (uix == uie) { + uix = uid; + } + } +#pragma omp atomic compare capture release + { + uiv = uix; + if (uie == uix) { + uix = uid; + } + } +#pragma omp atomic compare capture release + { + if (uie > uix) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture release + { + if (uix > uie) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture release + { + if (uie < uix) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture release + { + if (uix < uie) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture release + { + if (uix == uie) { + uix = uid; + } + uiv = uix; + } +#pragma omp atomic compare capture release + { + if (uie == uix) { + uix = uid; + } + uiv = uix; + } +#pragma omp atomic compare capture release + if (uix == uie) { + uix = uid; + } else { + uiv = uix; + } +#pragma omp atomic compare capture release + if (uie == uix) { + uix = uid; + } else { + uiv = uix; + } +#pragma omp atomic compare capture release + { + uir = uix == uie; + if (uir) { + uix = uid; + } + } +#pragma omp atomic compare capture release + { + uir = uie == uix; + if (uir) { + uix = uid; + } + } +#pragma omp atomic compare capture release + { + uir = uix == uie; + if (uir) { + uix = uid; + } else { + uiv = uix; + } + } +#pragma omp atomic compare capture release + { + uir = uie == uix; + if (uir) { + uix = uid; + } else { + uiv = uix; + } + } + +#pragma omp atomic compare capture seq_cst + { + uiv = uix; + if (uie > uix) { + uix = uie; + } + } +#pragma omp atomic compare capture seq_cst + { + uiv = uix; + if (uix > uie) { + uix = uie; + } + } +#pragma omp atomic compare capture seq_cst + { + uiv = uix; + if (uie < uix) { + uix = uie; + } + } +#pragma omp atomic compare capture seq_cst + { + uiv = uix; + if (uix < uie) { + uix = uie; + } + } +#pragma omp atomic compare capture seq_cst + { + uiv = uix; + if (uix == uie) { + uix = uid; + } + } +#pragma omp atomic compare capture seq_cst + { + uiv = uix; + if (uie == uix) { + uix = uid; + } + } +#pragma omp atomic compare capture seq_cst + { + if (uie > uix) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture seq_cst + { + if (uix > uie) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture seq_cst + { + if (uie < uix) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture seq_cst + { + if (uix < uie) { + uix = uie; + } + uiv = uix; + } +#pragma omp atomic compare capture seq_cst + { + if (uix == uie) { + uix = uid; + } + uiv = uix; + } +#pragma omp atomic compare capture seq_cst + { + if (uie == uix) { + uix = uid; + } + uiv = uix; + } +#pragma omp atomic compare capture seq_cst + if (uix == uie) { + uix = uid; + } else { + uiv = uix; + } +#pragma omp atomic compare capture seq_cst + if (uie == uix) { + uix = uid; + } else { + uiv = uix; + } +#pragma omp atomic compare capture seq_cst + { + uir = uix == uie; + if (uir) { + uix = uid; + } + } +#pragma omp atomic compare capture seq_cst + { + uir = uie == uix; + if (uir) { + uix = uid; + } + } +#pragma omp atomic compare capture seq_cst + { + uir = uix == uie; + if (uir) { + uix = uid; + } else { + uiv = uix; + } + } +#pragma omp atomic compare capture seq_cst + { + uir = uie == uix; + if (uir) { + uix = uid; + } else { + uiv = uix; + } + } + +#pragma omp atomic compare capture + { + lv = lx; + if (le > lx) { + lx = le; + } + } +#pragma omp atomic compare capture + { + lv = lx; + if (lx > le) { + lx = le; + } + } +#pragma omp atomic compare capture + { + lv = lx; + if (le < lx) { + lx = le; + } + } +#pragma omp atomic compare capture + { + lv = lx; + if (lx < le) { + lx = le; + } + } +#pragma omp atomic compare capture + { + lv = lx; + if (lx == le) { + lx = ld; + } + } +#pragma omp atomic compare capture + { + lv = lx; + if (le == lx) { + lx = ld; + } + } +#pragma omp atomic compare capture + { + if (le > lx) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture + { + if (lx > le) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture + { + if (le < lx) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture + { + if (lx < le) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture + { + if (lx == le) { + lx = ld; + } + lv = lx; + } +#pragma omp atomic compare capture + { + if (le == lx) { + lx = ld; + } + lv = lx; + } +#pragma omp atomic compare capture + if (lx == le) { + lx = ld; + } else { + lv = lx; + } +#pragma omp atomic compare capture + if (le == lx) { + lx = ld; + } else { + lv = lx; + } +#pragma omp atomic compare capture + { + lr = lx == le; + if (lr) { + lx = ld; + } + } +#pragma omp atomic compare capture + { + lr = le == lx; + if (lr) { + lx = ld; + } + } +#pragma omp atomic compare capture + { + lr = lx == le; + if (lr) { + lx = ld; + } else { + lv = lx; + } + } +#pragma omp atomic compare capture + { + lr = le == lx; + if (lr) { + lx = ld; + } else { + lv = lx; + } + } + +#pragma omp atomic compare capture acq_rel + { + lv = lx; + if (le > lx) { + lx = le; + } + } +#pragma omp atomic compare capture acq_rel + { + lv = lx; + if (lx > le) { + lx = le; + } + } +#pragma omp atomic compare capture acq_rel + { + lv = lx; + if (le < lx) { + lx = le; + } + } +#pragma omp atomic compare capture acq_rel + { + lv = lx; + if (lx < le) { + lx = le; + } + } +#pragma omp atomic compare capture acq_rel + { + lv = lx; + if (lx == le) { + lx = ld; + } + } +#pragma omp atomic compare capture acq_rel + { + lv = lx; + if (le == lx) { + lx = ld; + } + } +#pragma omp atomic compare capture acq_rel + { + if (le > lx) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture acq_rel + { + if (lx > le) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture acq_rel + { + if (le < lx) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture acq_rel + { + if (lx < le) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture acq_rel + { + if (lx == le) { + lx = ld; + } + lv = lx; + } +#pragma omp atomic compare capture acq_rel + { + if (le == lx) { + lx = ld; + } + lv = lx; + } +#pragma omp atomic compare capture acq_rel + if (lx == le) { + lx = ld; + } else { + lv = lx; + } +#pragma omp atomic compare capture acq_rel + if (le == lx) { + lx = ld; + } else { + lv = lx; + } +#pragma omp atomic compare capture acq_rel + { + lr = lx == le; + if (lr) { + lx = ld; + } + } +#pragma omp atomic compare capture acq_rel + { + lr = le == lx; + if (lr) { + lx = ld; + } + } +#pragma omp atomic compare capture acq_rel + { + lr = lx == le; + if (lr) { + lx = ld; + } else { + lv = lx; + } + } +#pragma omp atomic compare capture acq_rel + { + lr = le == lx; + if (lr) { + lx = ld; + } else { + lv = lx; + } + } + +#pragma omp atomic compare capture acquire + { + lv = lx; + if (le > lx) { + lx = le; + } + } +#pragma omp atomic compare capture acquire + { + lv = lx; + if (lx > le) { + lx = le; + } + } +#pragma omp atomic compare capture acquire + { + lv = lx; + if (le < lx) { + lx = le; + } + } +#pragma omp atomic compare capture acquire + { + lv = lx; + if (lx < le) { + lx = le; + } + } +#pragma omp atomic compare capture acquire + { + lv = lx; + if (lx == le) { + lx = ld; + } + } +#pragma omp atomic compare capture acquire + { + lv = lx; + if (le == lx) { + lx = ld; + } + } +#pragma omp atomic compare capture acquire + { + if (le > lx) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture acquire + { + if (lx > le) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture acquire + { + if (le < lx) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture acquire + { + if (lx < le) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture acquire + { + if (lx == le) { + lx = ld; + } + lv = lx; + } +#pragma omp atomic compare capture acquire + { + if (le == lx) { + lx = ld; + } + lv = lx; + } +#pragma omp atomic compare capture acquire + if (lx == le) { + lx = ld; + } else { + lv = lx; + } +#pragma omp atomic compare capture acquire + if (le == lx) { + lx = ld; + } else { + lv = lx; + } +#pragma omp atomic compare capture acquire + { + lr = lx == le; + if (lr) { + lx = ld; + } + } +#pragma omp atomic compare capture acquire + { + lr = le == lx; + if (lr) { + lx = ld; + } + } +#pragma omp atomic compare capture acquire + { + lr = lx == le; + if (lr) { + lx = ld; + } else { + lv = lx; + } + } +#pragma omp atomic compare capture acquire + { + lr = le == lx; + if (lr) { + lx = ld; + } else { + lv = lx; + } + } + +#pragma omp atomic compare capture relaxed + { + lv = lx; + if (le > lx) { + lx = le; + } + } +#pragma omp atomic compare capture relaxed + { + lv = lx; + if (lx > le) { + lx = le; + } + } +#pragma omp atomic compare capture relaxed + { + lv = lx; + if (le < lx) { + lx = le; + } + } +#pragma omp atomic compare capture relaxed + { + lv = lx; + if (lx < le) { + lx = le; + } + } +#pragma omp atomic compare capture relaxed + { + lv = lx; + if (lx == le) { + lx = ld; + } + } +#pragma omp atomic compare capture relaxed + { + lv = lx; + if (le == lx) { + lx = ld; + } + } +#pragma omp atomic compare capture relaxed + { + if (le > lx) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture relaxed + { + if (lx > le) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture relaxed + { + if (le < lx) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture relaxed + { + if (lx < le) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture relaxed + { + if (lx == le) { + lx = ld; + } + lv = lx; + } +#pragma omp atomic compare capture relaxed + { + if (le == lx) { + lx = ld; + } + lv = lx; + } +#pragma omp atomic compare capture relaxed + if (lx == le) { + lx = ld; + } else { + lv = lx; + } +#pragma omp atomic compare capture relaxed + if (le == lx) { + lx = ld; + } else { + lv = lx; + } +#pragma omp atomic compare capture relaxed + { + lr = lx == le; + if (lr) { + lx = ld; + } + } +#pragma omp atomic compare capture relaxed + { + lr = le == lx; + if (lr) { + lx = ld; + } + } +#pragma omp atomic compare capture relaxed + { + lr = lx == le; + if (lr) { + lx = ld; + } else { + lv = lx; + } + } +#pragma omp atomic compare capture relaxed + { + lr = le == lx; + if (lr) { + lx = ld; + } else { + lv = lx; + } + } + +#pragma omp atomic compare capture release + { + lv = lx; + if (le > lx) { + lx = le; + } + } +#pragma omp atomic compare capture release + { + lv = lx; + if (lx > le) { + lx = le; + } + } +#pragma omp atomic compare capture release + { + lv = lx; + if (le < lx) { + lx = le; + } + } +#pragma omp atomic compare capture release + { + lv = lx; + if (lx < le) { + lx = le; + } + } +#pragma omp atomic compare capture release + { + lv = lx; + if (lx == le) { + lx = ld; + } + } +#pragma omp atomic compare capture release + { + lv = lx; + if (le == lx) { + lx = ld; + } + } +#pragma omp atomic compare capture release + { + if (le > lx) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture release + { + if (lx > le) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture release + { + if (le < lx) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture release + { + if (lx < le) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture release + { + if (lx == le) { + lx = ld; + } + lv = lx; + } +#pragma omp atomic compare capture release + { + if (le == lx) { + lx = ld; + } + lv = lx; + } +#pragma omp atomic compare capture release + if (lx == le) { + lx = ld; + } else { + lv = lx; + } +#pragma omp atomic compare capture release + if (le == lx) { + lx = ld; + } else { + lv = lx; + } +#pragma omp atomic compare capture release + { + lr = lx == le; + if (lr) { + lx = ld; + } + } +#pragma omp atomic compare capture release + { + lr = le == lx; + if (lr) { + lx = ld; + } + } +#pragma omp atomic compare capture release + { + lr = lx == le; + if (lr) { + lx = ld; + } else { + lv = lx; + } + } +#pragma omp atomic compare capture release + { + lr = le == lx; + if (lr) { + lx = ld; + } else { + lv = lx; + } + } + +#pragma omp atomic compare capture seq_cst + { + lv = lx; + if (le > lx) { + lx = le; + } + } +#pragma omp atomic compare capture seq_cst + { + lv = lx; + if (lx > le) { + lx = le; + } + } +#pragma omp atomic compare capture seq_cst + { + lv = lx; + if (le < lx) { + lx = le; + } + } +#pragma omp atomic compare capture seq_cst + { + lv = lx; + if (lx < le) { + lx = le; + } + } +#pragma omp atomic compare capture seq_cst + { + lv = lx; + if (lx == le) { + lx = ld; + } + } +#pragma omp atomic compare capture seq_cst + { + lv = lx; + if (le == lx) { + lx = ld; + } + } +#pragma omp atomic compare capture seq_cst + { + if (le > lx) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture seq_cst + { + if (lx > le) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture seq_cst + { + if (le < lx) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture seq_cst + { + if (lx < le) { + lx = le; + } + lv = lx; + } +#pragma omp atomic compare capture seq_cst + { + if (lx == le) { + lx = ld; + } + lv = lx; + } +#pragma omp atomic compare capture seq_cst + { + if (le == lx) { + lx = ld; + } + lv = lx; + } +#pragma omp atomic compare capture seq_cst + if (lx == le) { + lx = ld; + } else { + lv = lx; + } +#pragma omp atomic compare capture seq_cst + if (le == lx) { + lx = ld; + } else { + lv = lx; + } +#pragma omp atomic compare capture seq_cst + { + lr = lx == le; + if (lr) { + lx = ld; + } + } +#pragma omp atomic compare capture seq_cst + { + lr = le == lx; + if (lr) { + lx = ld; + } + } +#pragma omp atomic compare capture seq_cst + { + lr = lx == le; + if (lr) { + lx = ld; + } else { + lv = lx; + } + } +#pragma omp atomic compare capture seq_cst + { + lr = le == lx; + if (lr) { + lx = ld; + } else { + lv = lx; + } + } + +#pragma omp atomic compare capture + { + ulv = ulx; + if (ule > ulx) { + ulx = ule; + } + } +#pragma omp atomic compare capture + { + ulv = ulx; + if (ulx > ule) { + ulx = ule; + } + } +#pragma omp atomic compare capture + { + ulv = ulx; + if (ule < ulx) { + ulx = ule; + } + } +#pragma omp atomic compare capture + { + ulv = ulx; + if (ulx < ule) { + ulx = ule; + } + } +#pragma omp atomic compare capture + { + ulv = ulx; + if (ulx == ule) { + ulx = uld; + } + } +#pragma omp atomic compare capture + { + ulv = ulx; + if (ule == ulx) { + ulx = uld; + } + } +#pragma omp atomic compare capture + { + if (ule > ulx) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture + { + if (ulx > ule) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture + { + if (ule < ulx) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture + { + if (ulx < ule) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture + { + if (ulx == ule) { + ulx = uld; + } + ulv = ulx; + } +#pragma omp atomic compare capture + { + if (ule == ulx) { + ulx = uld; + } + ulv = ulx; + } +#pragma omp atomic compare capture + if (ulx == ule) { + ulx = uld; + } else { + ulv = ulx; + } +#pragma omp atomic compare capture + if (ule == ulx) { + ulx = uld; + } else { + ulv = ulx; + } +#pragma omp atomic compare capture + { + ulr = ulx == ule; + if (ulr) { + ulx = uld; + } + } +#pragma omp atomic compare capture + { + ulr = ule == ulx; + if (ulr) { + ulx = uld; + } + } +#pragma omp atomic compare capture + { + ulr = ulx == ule; + if (ulr) { + ulx = uld; + } else { + ulv = ulx; + } + } +#pragma omp atomic compare capture + { + ulr = ule == ulx; + if (ulr) { + ulx = uld; + } else { + ulv = ulx; + } + } + +#pragma omp atomic compare capture acq_rel + { + ulv = ulx; + if (ule > ulx) { + ulx = ule; + } + } +#pragma omp atomic compare capture acq_rel + { + ulv = ulx; + if (ulx > ule) { + ulx = ule; + } + } +#pragma omp atomic compare capture acq_rel + { + ulv = ulx; + if (ule < ulx) { + ulx = ule; + } + } +#pragma omp atomic compare capture acq_rel + { + ulv = ulx; + if (ulx < ule) { + ulx = ule; + } + } +#pragma omp atomic compare capture acq_rel + { + ulv = ulx; + if (ulx == ule) { + ulx = uld; + } + } +#pragma omp atomic compare capture acq_rel + { + ulv = ulx; + if (ule == ulx) { + ulx = uld; + } + } +#pragma omp atomic compare capture acq_rel + { + if (ule > ulx) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture acq_rel + { + if (ulx > ule) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture acq_rel + { + if (ule < ulx) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture acq_rel + { + if (ulx < ule) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture acq_rel + { + if (ulx == ule) { + ulx = uld; + } + ulv = ulx; + } +#pragma omp atomic compare capture acq_rel + { + if (ule == ulx) { + ulx = uld; + } + ulv = ulx; + } +#pragma omp atomic compare capture acq_rel + if (ulx == ule) { + ulx = uld; + } else { + ulv = ulx; + } +#pragma omp atomic compare capture acq_rel + if (ule == ulx) { + ulx = uld; + } else { + ulv = ulx; + } +#pragma omp atomic compare capture acq_rel + { + ulr = ulx == ule; + if (ulr) { + ulx = uld; + } + } +#pragma omp atomic compare capture acq_rel + { + ulr = ule == ulx; + if (ulr) { + ulx = uld; + } + } +#pragma omp atomic compare capture acq_rel + { + ulr = ulx == ule; + if (ulr) { + ulx = uld; + } else { + ulv = ulx; + } + } +#pragma omp atomic compare capture acq_rel + { + ulr = ule == ulx; + if (ulr) { + ulx = uld; + } else { + ulv = ulx; + } + } + +#pragma omp atomic compare capture acquire + { + ulv = ulx; + if (ule > ulx) { + ulx = ule; + } + } +#pragma omp atomic compare capture acquire + { + ulv = ulx; + if (ulx > ule) { + ulx = ule; + } + } +#pragma omp atomic compare capture acquire + { + ulv = ulx; + if (ule < ulx) { + ulx = ule; + } + } +#pragma omp atomic compare capture acquire + { + ulv = ulx; + if (ulx < ule) { + ulx = ule; + } + } +#pragma omp atomic compare capture acquire + { + ulv = ulx; + if (ulx == ule) { + ulx = uld; + } + } +#pragma omp atomic compare capture acquire + { + ulv = ulx; + if (ule == ulx) { + ulx = uld; + } + } +#pragma omp atomic compare capture acquire + { + if (ule > ulx) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture acquire + { + if (ulx > ule) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture acquire + { + if (ule < ulx) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture acquire + { + if (ulx < ule) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture acquire + { + if (ulx == ule) { + ulx = uld; + } + ulv = ulx; + } +#pragma omp atomic compare capture acquire + { + if (ule == ulx) { + ulx = uld; + } + ulv = ulx; + } +#pragma omp atomic compare capture acquire + if (ulx == ule) { + ulx = uld; + } else { + ulv = ulx; + } +#pragma omp atomic compare capture acquire + if (ule == ulx) { + ulx = uld; + } else { + ulv = ulx; + } +#pragma omp atomic compare capture acquire + { + ulr = ulx == ule; + if (ulr) { + ulx = uld; + } + } +#pragma omp atomic compare capture acquire + { + ulr = ule == ulx; + if (ulr) { + ulx = uld; + } + } +#pragma omp atomic compare capture acquire + { + ulr = ulx == ule; + if (ulr) { + ulx = uld; + } else { + ulv = ulx; + } + } +#pragma omp atomic compare capture acquire + { + ulr = ule == ulx; + if (ulr) { + ulx = uld; + } else { + ulv = ulx; + } + } + +#pragma omp atomic compare capture relaxed + { + ulv = ulx; + if (ule > ulx) { + ulx = ule; + } + } +#pragma omp atomic compare capture relaxed + { + ulv = ulx; + if (ulx > ule) { + ulx = ule; + } + } +#pragma omp atomic compare capture relaxed + { + ulv = ulx; + if (ule < ulx) { + ulx = ule; + } + } +#pragma omp atomic compare capture relaxed + { + ulv = ulx; + if (ulx < ule) { + ulx = ule; + } + } +#pragma omp atomic compare capture relaxed + { + ulv = ulx; + if (ulx == ule) { + ulx = uld; + } + } +#pragma omp atomic compare capture relaxed + { + ulv = ulx; + if (ule == ulx) { + ulx = uld; + } + } +#pragma omp atomic compare capture relaxed + { + if (ule > ulx) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture relaxed + { + if (ulx > ule) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture relaxed + { + if (ule < ulx) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture relaxed + { + if (ulx < ule) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture relaxed + { + if (ulx == ule) { + ulx = uld; + } + ulv = ulx; + } +#pragma omp atomic compare capture relaxed + { + if (ule == ulx) { + ulx = uld; + } + ulv = ulx; + } +#pragma omp atomic compare capture relaxed + if (ulx == ule) { + ulx = uld; + } else { + ulv = ulx; + } +#pragma omp atomic compare capture relaxed + if (ule == ulx) { + ulx = uld; + } else { + ulv = ulx; + } +#pragma omp atomic compare capture relaxed + { + ulr = ulx == ule; + if (ulr) { + ulx = uld; + } + } +#pragma omp atomic compare capture relaxed + { + ulr = ule == ulx; + if (ulr) { + ulx = uld; + } + } +#pragma omp atomic compare capture relaxed + { + ulr = ulx == ule; + if (ulr) { + ulx = uld; + } else { + ulv = ulx; + } + } +#pragma omp atomic compare capture relaxed + { + ulr = ule == ulx; + if (ulr) { + ulx = uld; + } else { + ulv = ulx; + } + } + +#pragma omp atomic compare capture release + { + ulv = ulx; + if (ule > ulx) { + ulx = ule; + } + } +#pragma omp atomic compare capture release + { + ulv = ulx; + if (ulx > ule) { + ulx = ule; + } + } +#pragma omp atomic compare capture release + { + ulv = ulx; + if (ule < ulx) { + ulx = ule; + } + } +#pragma omp atomic compare capture release + { + ulv = ulx; + if (ulx < ule) { + ulx = ule; + } + } +#pragma omp atomic compare capture release + { + ulv = ulx; + if (ulx == ule) { + ulx = uld; + } + } +#pragma omp atomic compare capture release + { + ulv = ulx; + if (ule == ulx) { + ulx = uld; + } + } +#pragma omp atomic compare capture release + { + if (ule > ulx) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture release + { + if (ulx > ule) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture release + { + if (ule < ulx) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture release + { + if (ulx < ule) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture release + { + if (ulx == ule) { + ulx = uld; + } + ulv = ulx; + } +#pragma omp atomic compare capture release + { + if (ule == ulx) { + ulx = uld; + } + ulv = ulx; + } +#pragma omp atomic compare capture release + if (ulx == ule) { + ulx = uld; + } else { + ulv = ulx; + } +#pragma omp atomic compare capture release + if (ule == ulx) { + ulx = uld; + } else { + ulv = ulx; + } +#pragma omp atomic compare capture release + { + ulr = ulx == ule; + if (ulr) { + ulx = uld; + } + } +#pragma omp atomic compare capture release + { + ulr = ule == ulx; + if (ulr) { + ulx = uld; + } + } +#pragma omp atomic compare capture release + { + ulr = ulx == ule; + if (ulr) { + ulx = uld; + } else { + ulv = ulx; + } + } +#pragma omp atomic compare capture release + { + ulr = ule == ulx; + if (ulr) { + ulx = uld; + } else { + ulv = ulx; + } + } + +#pragma omp atomic compare capture seq_cst + { + ulv = ulx; + if (ule > ulx) { + ulx = ule; + } + } +#pragma omp atomic compare capture seq_cst + { + ulv = ulx; + if (ulx > ule) { + ulx = ule; + } + } +#pragma omp atomic compare capture seq_cst + { + ulv = ulx; + if (ule < ulx) { + ulx = ule; + } + } +#pragma omp atomic compare capture seq_cst + { + ulv = ulx; + if (ulx < ule) { + ulx = ule; + } + } +#pragma omp atomic compare capture seq_cst + { + ulv = ulx; + if (ulx == ule) { + ulx = uld; + } + } +#pragma omp atomic compare capture seq_cst + { + ulv = ulx; + if (ule == ulx) { + ulx = uld; + } + } +#pragma omp atomic compare capture seq_cst + { + if (ule > ulx) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture seq_cst + { + if (ulx > ule) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture seq_cst + { + if (ule < ulx) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture seq_cst + { + if (ulx < ule) { + ulx = ule; + } + ulv = ulx; + } +#pragma omp atomic compare capture seq_cst + { + if (ulx == ule) { + ulx = uld; + } + ulv = ulx; + } +#pragma omp atomic compare capture seq_cst + { + if (ule == ulx) { + ulx = uld; + } + ulv = ulx; + } +#pragma omp atomic compare capture seq_cst + if (ulx == ule) { + ulx = uld; + } else { + ulv = ulx; + } +#pragma omp atomic compare capture seq_cst + if (ule == ulx) { + ulx = uld; + } else { + ulv = ulx; + } +#pragma omp atomic compare capture seq_cst + { + ulr = ulx == ule; + if (ulr) { + ulx = uld; + } + } +#pragma omp atomic compare capture seq_cst + { + ulr = ule == ulx; + if (ulr) { + ulx = uld; + } + } +#pragma omp atomic compare capture seq_cst + { + ulr = ulx == ule; + if (ulr) { + ulx = uld; + } else { + ulv = ulx; + } + } +#pragma omp atomic compare capture seq_cst + { + ulr = ule == ulx; + if (ulr) { + ulx = uld; + } else { + ulv = ulx; + } + } + +#pragma omp atomic compare capture + { + llv = llx; + if (lle > llx) { + llx = lle; + } + } +#pragma omp atomic compare capture + { + llv = llx; + if (llx > lle) { + llx = lle; + } + } +#pragma omp atomic compare capture + { + llv = llx; + if (lle < llx) { + llx = lle; + } + } +#pragma omp atomic compare capture + { + llv = llx; + if (llx < lle) { + llx = lle; + } + } +#pragma omp atomic compare capture + { + llv = llx; + if (llx == lle) { + llx = lld; + } + } +#pragma omp atomic compare capture + { + llv = llx; + if (lle == llx) { + llx = lld; + } + } +#pragma omp atomic compare capture + { + if (lle > llx) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture + { + if (llx > lle) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture + { + if (lle < llx) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture + { + if (llx < lle) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture + { + if (llx == lle) { + llx = lld; + } + llv = llx; + } +#pragma omp atomic compare capture + { + if (lle == llx) { + llx = lld; + } + llv = llx; + } +#pragma omp atomic compare capture + if (llx == lle) { + llx = lld; + } else { + llv = llx; + } +#pragma omp atomic compare capture + if (lle == llx) { + llx = lld; + } else { + llv = llx; + } +#pragma omp atomic compare capture + { + llr = llx == lle; + if (llr) { + llx = lld; + } + } +#pragma omp atomic compare capture + { + llr = lle == llx; + if (llr) { + llx = lld; + } + } +#pragma omp atomic compare capture + { + llr = llx == lle; + if (llr) { + llx = lld; + } else { + llv = llx; + } + } +#pragma omp atomic compare capture + { + llr = lle == llx; + if (llr) { + llx = lld; + } else { + llv = llx; + } + } + +#pragma omp atomic compare capture acq_rel + { + llv = llx; + if (lle > llx) { + llx = lle; + } + } +#pragma omp atomic compare capture acq_rel + { + llv = llx; + if (llx > lle) { + llx = lle; + } + } +#pragma omp atomic compare capture acq_rel + { + llv = llx; + if (lle < llx) { + llx = lle; + } + } +#pragma omp atomic compare capture acq_rel + { + llv = llx; + if (llx < lle) { + llx = lle; + } + } +#pragma omp atomic compare capture acq_rel + { + llv = llx; + if (llx == lle) { + llx = lld; + } + } +#pragma omp atomic compare capture acq_rel + { + llv = llx; + if (lle == llx) { + llx = lld; + } + } +#pragma omp atomic compare capture acq_rel + { + if (lle > llx) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture acq_rel + { + if (llx > lle) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture acq_rel + { + if (lle < llx) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture acq_rel + { + if (llx < lle) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture acq_rel + { + if (llx == lle) { + llx = lld; + } + llv = llx; + } +#pragma omp atomic compare capture acq_rel + { + if (lle == llx) { + llx = lld; + } + llv = llx; + } +#pragma omp atomic compare capture acq_rel + if (llx == lle) { + llx = lld; + } else { + llv = llx; + } +#pragma omp atomic compare capture acq_rel + if (lle == llx) { + llx = lld; + } else { + llv = llx; + } +#pragma omp atomic compare capture acq_rel + { + llr = llx == lle; + if (llr) { + llx = lld; + } + } +#pragma omp atomic compare capture acq_rel + { + llr = lle == llx; + if (llr) { + llx = lld; + } + } +#pragma omp atomic compare capture acq_rel + { + llr = llx == lle; + if (llr) { + llx = lld; + } else { + llv = llx; + } + } +#pragma omp atomic compare capture acq_rel + { + llr = lle == llx; + if (llr) { + llx = lld; + } else { + llv = llx; + } + } + +#pragma omp atomic compare capture acquire + { + llv = llx; + if (lle > llx) { + llx = lle; + } + } +#pragma omp atomic compare capture acquire + { + llv = llx; + if (llx > lle) { + llx = lle; + } + } +#pragma omp atomic compare capture acquire + { + llv = llx; + if (lle < llx) { + llx = lle; + } + } +#pragma omp atomic compare capture acquire + { + llv = llx; + if (llx < lle) { + llx = lle; + } + } +#pragma omp atomic compare capture acquire + { + llv = llx; + if (llx == lle) { + llx = lld; + } + } +#pragma omp atomic compare capture acquire + { + llv = llx; + if (lle == llx) { + llx = lld; + } + } +#pragma omp atomic compare capture acquire + { + if (lle > llx) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture acquire + { + if (llx > lle) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture acquire + { + if (lle < llx) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture acquire + { + if (llx < lle) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture acquire + { + if (llx == lle) { + llx = lld; + } + llv = llx; + } +#pragma omp atomic compare capture acquire + { + if (lle == llx) { + llx = lld; + } + llv = llx; + } +#pragma omp atomic compare capture acquire + if (llx == lle) { + llx = lld; + } else { + llv = llx; + } +#pragma omp atomic compare capture acquire + if (lle == llx) { + llx = lld; + } else { + llv = llx; + } +#pragma omp atomic compare capture acquire + { + llr = llx == lle; + if (llr) { + llx = lld; + } + } +#pragma omp atomic compare capture acquire + { + llr = lle == llx; + if (llr) { + llx = lld; + } + } +#pragma omp atomic compare capture acquire + { + llr = llx == lle; + if (llr) { + llx = lld; + } else { + llv = llx; + } + } +#pragma omp atomic compare capture acquire + { + llr = lle == llx; + if (llr) { + llx = lld; + } else { + llv = llx; + } + } + +#pragma omp atomic compare capture relaxed + { + llv = llx; + if (lle > llx) { + llx = lle; + } + } +#pragma omp atomic compare capture relaxed + { + llv = llx; + if (llx > lle) { + llx = lle; + } + } +#pragma omp atomic compare capture relaxed + { + llv = llx; + if (lle < llx) { + llx = lle; + } + } +#pragma omp atomic compare capture relaxed + { + llv = llx; + if (llx < lle) { + llx = lle; + } + } +#pragma omp atomic compare capture relaxed + { + llv = llx; + if (llx == lle) { + llx = lld; + } + } +#pragma omp atomic compare capture relaxed + { + llv = llx; + if (lle == llx) { + llx = lld; + } + } +#pragma omp atomic compare capture relaxed + { + if (lle > llx) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture relaxed + { + if (llx > lle) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture relaxed + { + if (lle < llx) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture relaxed + { + if (llx < lle) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture relaxed + { + if (llx == lle) { + llx = lld; + } + llv = llx; + } +#pragma omp atomic compare capture relaxed + { + if (lle == llx) { + llx = lld; + } + llv = llx; + } +#pragma omp atomic compare capture relaxed + if (llx == lle) { + llx = lld; + } else { + llv = llx; + } +#pragma omp atomic compare capture relaxed + if (lle == llx) { + llx = lld; + } else { + llv = llx; + } +#pragma omp atomic compare capture relaxed + { + llr = llx == lle; + if (llr) { + llx = lld; + } + } +#pragma omp atomic compare capture relaxed + { + llr = lle == llx; + if (llr) { + llx = lld; + } + } +#pragma omp atomic compare capture relaxed + { + llr = llx == lle; + if (llr) { + llx = lld; + } else { + llv = llx; + } + } +#pragma omp atomic compare capture relaxed + { + llr = lle == llx; + if (llr) { + llx = lld; + } else { + llv = llx; + } + } + +#pragma omp atomic compare capture release + { + llv = llx; + if (lle > llx) { + llx = lle; + } + } +#pragma omp atomic compare capture release + { + llv = llx; + if (llx > lle) { + llx = lle; + } + } +#pragma omp atomic compare capture release + { + llv = llx; + if (lle < llx) { + llx = lle; + } + } +#pragma omp atomic compare capture release + { + llv = llx; + if (llx < lle) { + llx = lle; + } + } +#pragma omp atomic compare capture release + { + llv = llx; + if (llx == lle) { + llx = lld; + } + } +#pragma omp atomic compare capture release + { + llv = llx; + if (lle == llx) { + llx = lld; + } + } +#pragma omp atomic compare capture release + { + if (lle > llx) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture release + { + if (llx > lle) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture release + { + if (lle < llx) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture release + { + if (llx < lle) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture release + { + if (llx == lle) { + llx = lld; + } + llv = llx; + } +#pragma omp atomic compare capture release + { + if (lle == llx) { + llx = lld; + } + llv = llx; + } +#pragma omp atomic compare capture release + if (llx == lle) { + llx = lld; + } else { + llv = llx; + } +#pragma omp atomic compare capture release + if (lle == llx) { + llx = lld; + } else { + llv = llx; + } +#pragma omp atomic compare capture release + { + llr = llx == lle; + if (llr) { + llx = lld; + } + } +#pragma omp atomic compare capture release + { + llr = lle == llx; + if (llr) { + llx = lld; + } + } +#pragma omp atomic compare capture release + { + llr = llx == lle; + if (llr) { + llx = lld; + } else { + llv = llx; + } + } +#pragma omp atomic compare capture release + { + llr = lle == llx; + if (llr) { + llx = lld; + } else { + llv = llx; + } + } + +#pragma omp atomic compare capture seq_cst + { + llv = llx; + if (lle > llx) { + llx = lle; + } + } +#pragma omp atomic compare capture seq_cst + { + llv = llx; + if (llx > lle) { + llx = lle; + } + } +#pragma omp atomic compare capture seq_cst + { + llv = llx; + if (lle < llx) { + llx = lle; + } + } +#pragma omp atomic compare capture seq_cst + { + llv = llx; + if (llx < lle) { + llx = lle; + } + } +#pragma omp atomic compare capture seq_cst + { + llv = llx; + if (llx == lle) { + llx = lld; + } + } +#pragma omp atomic compare capture seq_cst + { + llv = llx; + if (lle == llx) { + llx = lld; + } + } +#pragma omp atomic compare capture seq_cst + { + if (lle > llx) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture seq_cst + { + if (llx > lle) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture seq_cst + { + if (lle < llx) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture seq_cst + { + if (llx < lle) { + llx = lle; + } + llv = llx; + } +#pragma omp atomic compare capture seq_cst + { + if (llx == lle) { + llx = lld; + } + llv = llx; + } +#pragma omp atomic compare capture seq_cst + { + if (lle == llx) { + llx = lld; + } + llv = llx; + } +#pragma omp atomic compare capture seq_cst + if (llx == lle) { + llx = lld; + } else { + llv = llx; + } +#pragma omp atomic compare capture seq_cst + if (lle == llx) { + llx = lld; + } else { + llv = llx; + } +#pragma omp atomic compare capture seq_cst + { + llr = llx == lle; + if (llr) { + llx = lld; + } + } +#pragma omp atomic compare capture seq_cst + { + llr = lle == llx; + if (llr) { + llx = lld; + } + } +#pragma omp atomic compare capture seq_cst + { + llr = llx == lle; + if (llr) { + llx = lld; + } else { + llv = llx; + } + } +#pragma omp atomic compare capture seq_cst + { + llr = lle == llx; + if (llr) { + llx = lld; + } else { + llv = llx; + } + } + +#pragma omp atomic compare capture + { + ullv = ullx; + if (ulle > ullx) { + ullx = ulle; + } + } +#pragma omp atomic compare capture + { + ullv = ullx; + if (ullx > ulle) { + ullx = ulle; + } + } +#pragma omp atomic compare capture + { + ullv = ullx; + if (ulle < ullx) { + ullx = ulle; + } + } +#pragma omp atomic compare capture + { + ullv = ullx; + if (ullx < ulle) { + ullx = ulle; + } + } +#pragma omp atomic compare capture + { + ullv = ullx; + if (ullx == ulle) { + ullx = ulld; + } + } +#pragma omp atomic compare capture + { + ullv = ullx; + if (ulle == ullx) { + ullx = ulld; + } + } +#pragma omp atomic compare capture + { + if (ulle > ullx) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture + { + if (ullx > ulle) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture + { + if (ulle < ullx) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture + { + if (ullx < ulle) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture + { + if (ullx == ulle) { + ullx = ulld; + } + ullv = ullx; + } +#pragma omp atomic compare capture + { + if (ulle == ullx) { + ullx = ulld; + } + ullv = ullx; + } +#pragma omp atomic compare capture + if (ullx == ulle) { + ullx = ulld; + } else { + ullv = ullx; + } +#pragma omp atomic compare capture + if (ulle == ullx) { + ullx = ulld; + } else { + ullv = ullx; + } +#pragma omp atomic compare capture + { + ullr = ullx == ulle; + if (ullr) { + ullx = ulld; + } + } +#pragma omp atomic compare capture + { + ullr = ulle == ullx; + if (ullr) { + ullx = ulld; + } + } +#pragma omp atomic compare capture + { + ullr = ullx == ulle; + if (ullr) { + ullx = ulld; + } else { + ullv = ullx; + } + } +#pragma omp atomic compare capture + { + ullr = ulle == ullx; + if (ullr) { + ullx = ulld; + } else { + ullv = ullx; + } + } + +#pragma omp atomic compare capture acq_rel + { + ullv = ullx; + if (ulle > ullx) { + ullx = ulle; + } + } +#pragma omp atomic compare capture acq_rel + { + ullv = ullx; + if (ullx > ulle) { + ullx = ulle; + } + } +#pragma omp atomic compare capture acq_rel + { + ullv = ullx; + if (ulle < ullx) { + ullx = ulle; + } + } +#pragma omp atomic compare capture acq_rel + { + ullv = ullx; + if (ullx < ulle) { + ullx = ulle; + } + } +#pragma omp atomic compare capture acq_rel + { + ullv = ullx; + if (ullx == ulle) { + ullx = ulld; + } + } +#pragma omp atomic compare capture acq_rel + { + ullv = ullx; + if (ulle == ullx) { + ullx = ulld; + } + } +#pragma omp atomic compare capture acq_rel + { + if (ulle > ullx) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture acq_rel + { + if (ullx > ulle) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture acq_rel + { + if (ulle < ullx) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture acq_rel + { + if (ullx < ulle) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture acq_rel + { + if (ullx == ulle) { + ullx = ulld; + } + ullv = ullx; + } +#pragma omp atomic compare capture acq_rel + { + if (ulle == ullx) { + ullx = ulld; + } + ullv = ullx; + } +#pragma omp atomic compare capture acq_rel + if (ullx == ulle) { + ullx = ulld; + } else { + ullv = ullx; + } +#pragma omp atomic compare capture acq_rel + if (ulle == ullx) { + ullx = ulld; + } else { + ullv = ullx; + } +#pragma omp atomic compare capture acq_rel + { + ullr = ullx == ulle; + if (ullr) { + ullx = ulld; + } + } +#pragma omp atomic compare capture acq_rel + { + ullr = ulle == ullx; + if (ullr) { + ullx = ulld; + } + } +#pragma omp atomic compare capture acq_rel + { + ullr = ullx == ulle; + if (ullr) { + ullx = ulld; + } else { + ullv = ullx; + } + } +#pragma omp atomic compare capture acq_rel + { + ullr = ulle == ullx; + if (ullr) { + ullx = ulld; + } else { + ullv = ullx; + } + } + +#pragma omp atomic compare capture acquire + { + ullv = ullx; + if (ulle > ullx) { + ullx = ulle; + } + } +#pragma omp atomic compare capture acquire + { + ullv = ullx; + if (ullx > ulle) { + ullx = ulle; + } + } +#pragma omp atomic compare capture acquire + { + ullv = ullx; + if (ulle < ullx) { + ullx = ulle; + } + } +#pragma omp atomic compare capture acquire + { + ullv = ullx; + if (ullx < ulle) { + ullx = ulle; + } + } +#pragma omp atomic compare capture acquire + { + ullv = ullx; + if (ullx == ulle) { + ullx = ulld; + } + } +#pragma omp atomic compare capture acquire + { + ullv = ullx; + if (ulle == ullx) { + ullx = ulld; + } + } +#pragma omp atomic compare capture acquire + { + if (ulle > ullx) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture acquire + { + if (ullx > ulle) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture acquire + { + if (ulle < ullx) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture acquire + { + if (ullx < ulle) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture acquire + { + if (ullx == ulle) { + ullx = ulld; + } + ullv = ullx; + } +#pragma omp atomic compare capture acquire + { + if (ulle == ullx) { + ullx = ulld; + } + ullv = ullx; + } +#pragma omp atomic compare capture acquire + if (ullx == ulle) { + ullx = ulld; + } else { + ullv = ullx; + } +#pragma omp atomic compare capture acquire + if (ulle == ullx) { + ullx = ulld; + } else { + ullv = ullx; + } +#pragma omp atomic compare capture acquire + { + ullr = ullx == ulle; + if (ullr) { + ullx = ulld; + } + } +#pragma omp atomic compare capture acquire + { + ullr = ulle == ullx; + if (ullr) { + ullx = ulld; + } + } +#pragma omp atomic compare capture acquire + { + ullr = ullx == ulle; + if (ullr) { + ullx = ulld; + } else { + ullv = ullx; + } + } +#pragma omp atomic compare capture acquire + { + ullr = ulle == ullx; + if (ullr) { + ullx = ulld; + } else { + ullv = ullx; + } + } + +#pragma omp atomic compare capture relaxed + { + ullv = ullx; + if (ulle > ullx) { + ullx = ulle; + } + } +#pragma omp atomic compare capture relaxed + { + ullv = ullx; + if (ullx > ulle) { + ullx = ulle; + } + } +#pragma omp atomic compare capture relaxed + { + ullv = ullx; + if (ulle < ullx) { + ullx = ulle; + } + } +#pragma omp atomic compare capture relaxed + { + ullv = ullx; + if (ullx < ulle) { + ullx = ulle; + } + } +#pragma omp atomic compare capture relaxed + { + ullv = ullx; + if (ullx == ulle) { + ullx = ulld; + } + } +#pragma omp atomic compare capture relaxed + { + ullv = ullx; + if (ulle == ullx) { + ullx = ulld; + } + } +#pragma omp atomic compare capture relaxed + { + if (ulle > ullx) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture relaxed + { + if (ullx > ulle) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture relaxed + { + if (ulle < ullx) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture relaxed + { + if (ullx < ulle) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture relaxed + { + if (ullx == ulle) { + ullx = ulld; + } + ullv = ullx; + } +#pragma omp atomic compare capture relaxed + { + if (ulle == ullx) { + ullx = ulld; + } + ullv = ullx; + } +#pragma omp atomic compare capture relaxed + if (ullx == ulle) { + ullx = ulld; + } else { + ullv = ullx; + } +#pragma omp atomic compare capture relaxed + if (ulle == ullx) { + ullx = ulld; + } else { + ullv = ullx; + } +#pragma omp atomic compare capture relaxed + { + ullr = ullx == ulle; + if (ullr) { + ullx = ulld; + } + } +#pragma omp atomic compare capture relaxed + { + ullr = ulle == ullx; + if (ullr) { + ullx = ulld; + } + } +#pragma omp atomic compare capture relaxed + { + ullr = ullx == ulle; + if (ullr) { + ullx = ulld; + } else { + ullv = ullx; + } + } +#pragma omp atomic compare capture relaxed + { + ullr = ulle == ullx; + if (ullr) { + ullx = ulld; + } else { + ullv = ullx; + } + } + +#pragma omp atomic compare capture release + { + ullv = ullx; + if (ulle > ullx) { + ullx = ulle; + } + } +#pragma omp atomic compare capture release + { + ullv = ullx; + if (ullx > ulle) { + ullx = ulle; + } + } +#pragma omp atomic compare capture release + { + ullv = ullx; + if (ulle < ullx) { + ullx = ulle; + } + } +#pragma omp atomic compare capture release + { + ullv = ullx; + if (ullx < ulle) { + ullx = ulle; + } + } +#pragma omp atomic compare capture release + { + ullv = ullx; + if (ullx == ulle) { + ullx = ulld; + } + } +#pragma omp atomic compare capture release + { + ullv = ullx; + if (ulle == ullx) { + ullx = ulld; + } + } +#pragma omp atomic compare capture release + { + if (ulle > ullx) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture release + { + if (ullx > ulle) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture release + { + if (ulle < ullx) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture release + { + if (ullx < ulle) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture release + { + if (ullx == ulle) { + ullx = ulld; + } + ullv = ullx; + } +#pragma omp atomic compare capture release + { + if (ulle == ullx) { + ullx = ulld; + } + ullv = ullx; + } +#pragma omp atomic compare capture release + if (ullx == ulle) { + ullx = ulld; + } else { + ullv = ullx; + } +#pragma omp atomic compare capture release + if (ulle == ullx) { + ullx = ulld; + } else { + ullv = ullx; + } +#pragma omp atomic compare capture release + { + ullr = ullx == ulle; + if (ullr) { + ullx = ulld; + } + } +#pragma omp atomic compare capture release + { + ullr = ulle == ullx; + if (ullr) { + ullx = ulld; + } + } +#pragma omp atomic compare capture release + { + ullr = ullx == ulle; + if (ullr) { + ullx = ulld; + } else { + ullv = ullx; + } + } +#pragma omp atomic compare capture release + { + ullr = ulle == ullx; + if (ullr) { + ullx = ulld; + } else { + ullv = ullx; + } + } + +#pragma omp atomic compare capture seq_cst + { + ullv = ullx; + if (ulle > ullx) { + ullx = ulle; + } + } +#pragma omp atomic compare capture seq_cst + { + ullv = ullx; + if (ullx > ulle) { + ullx = ulle; + } + } +#pragma omp atomic compare capture seq_cst + { + ullv = ullx; + if (ulle < ullx) { + ullx = ulle; + } + } +#pragma omp atomic compare capture seq_cst + { + ullv = ullx; + if (ullx < ulle) { + ullx = ulle; + } + } +#pragma omp atomic compare capture seq_cst + { + ullv = ullx; + if (ullx == ulle) { + ullx = ulld; + } + } +#pragma omp atomic compare capture seq_cst + { + ullv = ullx; + if (ulle == ullx) { + ullx = ulld; + } + } +#pragma omp atomic compare capture seq_cst + { + if (ulle > ullx) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture seq_cst + { + if (ullx > ulle) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture seq_cst + { + if (ulle < ullx) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture seq_cst + { + if (ullx < ulle) { + ullx = ulle; + } + ullv = ullx; + } +#pragma omp atomic compare capture seq_cst + { + if (ullx == ulle) { + ullx = ulld; + } + ullv = ullx; + } +#pragma omp atomic compare capture seq_cst + { + if (ulle == ullx) { + ullx = ulld; + } + ullv = ullx; + } +#pragma omp atomic compare capture seq_cst + if (ullx == ulle) { + ullx = ulld; + } else { + ullv = ullx; + } +#pragma omp atomic compare capture seq_cst + if (ulle == ullx) { + ullx = ulld; + } else { + ullv = ullx; + } +#pragma omp atomic compare capture seq_cst + { + ullr = ullx == ulle; + if (ullr) { + ullx = ulld; + } + } +#pragma omp atomic compare capture seq_cst + { + ullr = ulle == ullx; + if (ullr) { + ullx = ulld; + } + } +#pragma omp atomic compare capture seq_cst + { + ullr = ullx == ulle; + if (ullr) { + ullx = ulld; + } else { + ullv = ullx; + } + } +#pragma omp atomic compare capture seq_cst + { + ullr = ulle == ullx; + if (ullr) { + ullx = ulld; + } else { + ullv = ullx; + } + } +} + #endif // CHECK-LABEL: @foo( // CHECK-NEXT: entry: diff --git a/clang/test/Parser/MicrosoftExtensions.cpp b/clang/test/Parser/MicrosoftExtensions.cpp index c625bf3d6befc..01e59aa1945a8 100644 --- a/clang/test/Parser/MicrosoftExtensions.cpp +++ b/clang/test/Parser/MicrosoftExtensions.cpp @@ -57,6 +57,14 @@ struct __declspec(uuid("000000A0-0000-0000-C000-000000000046")) struct_with_uuid { }; struct struct_without_uuid { }; +struct base { + int a; +}; +struct derived : base { + // Can't apply a UUID to a using declaration. + [uuid("000000A0-0000-0000-C000-00000000004A")] using base::a; // expected-error {{expected member name}} +}; + struct __declspec(uuid("000000A0-0000-0000-C000-000000000049")) struct_with_uuid2; diff --git a/clang/test/Parser/asm.c b/clang/test/Parser/asm.c index 37b3ba3f46561..480acb7b6ffd9 100644 --- a/clang/test/Parser/asm.c +++ b/clang/test/Parser/asm.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -fdouble-square-bracket-attributes -verify %s #if !__has_extension(gnu_asm) #error Extension 'gnu_asm' should be available by default @@ -12,6 +12,9 @@ void f1(void) { void f2(void) { asm("foo" : "=r" (a)); // expected-error {{use of undeclared identifier 'a'}} asm("foo" : : "r" (b)); // expected-error {{use of undeclared identifier 'b'}} + + [[]] asm(""); + [[gnu::deprecated]] asm(""); // expected-warning {{'deprecated' attribute ignored}} } void a(void) __asm__(""); // expected-error {{cannot use an empty string literal in 'asm'}} diff --git a/clang/test/Parser/asm.cpp b/clang/test/Parser/asm.cpp index 9f64dfea476ed..de156877ec470 100644 --- a/clang/test/Parser/asm.cpp +++ b/clang/test/Parser/asm.cpp @@ -7,3 +7,8 @@ int foo4 asm (u"bar4"); // expected-error {{cannot use unicode string literal in int foo5 asm (U"bar5"); // expected-error {{cannot use unicode string literal in 'asm'}} int foo6 asm ("bar6"_x); // expected-error {{string literal with user-defined suffix cannot be used here}} int foo6 asm ("" L"bar7"); // expected-error {{cannot use wide string literal in 'asm'}} + +void f() { + [[]] asm(""); + [[gnu::deprecated]] asm(""); // expected-warning {{'deprecated' attribute ignored}} +} diff --git a/clang/test/Parser/attributes.c b/clang/test/Parser/attributes.c index 9f017c6958c2a..fe22c7e98a537 100644 --- a/clang/test/Parser/attributes.c +++ b/clang/test/Parser/attributes.c @@ -113,3 +113,10 @@ __attribute__((,,,const)) int PR38352_1(void); __attribute__((const,,,)) int PR38352_2(void); __attribute__((const,,,const)) int PR38352_3(void); __attribute__((,,,const,,,const,,,)) int PR38352_4(void); + +// Test that we allow attributes on free-standing decl-specifier-seqs. +// GCC appears to allow this. +__attribute__(()) struct t; +void f5() { + __attribute__(()) struct t; +} diff --git a/clang/test/Parser/c2x-attributes.c b/clang/test/Parser/c2x-attributes.c index e1265f73a4767..f8ed1eda14886 100644 --- a/clang/test/Parser/c2x-attributes.c +++ b/clang/test/Parser/c2x-attributes.c @@ -34,6 +34,8 @@ struct [[]] S1 { int [[]] : 0; // OK, attribute applies to the type. int p, [[]] : 0; // expected-error {{an attribute list cannot appear here}} int q, [[]] r; // expected-error {{an attribute list cannot appear here}} + [[]] int; // expected-error {{an attribute list cannot appear here}} \ + // expected-warning {{declaration does not declare anything}} }; [[]] struct S2 { int a; }; // expected-error {{misplaced attributes}} diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp index 25113d35b8544..3cb4e180e5f5f 100644 --- a/clang/test/Parser/cxx0x-attributes.cpp +++ b/clang/test/Parser/cxx0x-attributes.cpp @@ -126,6 +126,7 @@ class foo { void const_after_attr () [[]] const; // expected-error {{expected ';'}} }; extern "C++" [[]] { } // expected-error {{an attribute list cannot appear here}} +[[]] extern "C++" { } // expected-error {{an attribute list cannot appear here}} [[]] template void before_template_attr (); // expected-error {{an attribute list cannot appear here}} [[]] namespace ns { int i; } // expected-error {{an attribute list cannot appear here}} expected-note {{declared here}} [[]] static_assert(true, ""); //expected-error {{an attribute list cannot appear here}} @@ -421,3 +422,26 @@ class FriendClassesWithAttributes { // prefered "protected" vendor namespace. We support __clang__ only for // people expecting it to behave the same as __gnu__. [[__clang__::annotate("test")]] void annotate3(); // expected-warning {{'__clang__' is a predefined macro name, not an attribute scope specifier; did you mean '_Clang' instead?}} + +// Check ordering: C++11 attributes must appear before GNU attributes. +class Ordering { + void f1( + int ([[]] __attribute__(()) int n) + ) { + } + + void f2( + int (*)([[]] __attribute__(()) int n) + ) { + } + + void f3( + int (__attribute__(()) [[]] int n) // expected-error {{an attribute list cannot appear here}} + ) { + } + + void f4( + int (*)(__attribute__(()) [[]] int n) // expected-error {{an attribute list cannot appear here}} + ) { + } +}; diff --git a/clang/test/Parser/opencl-pragma.cl b/clang/test/Parser/opencl-pragma.cl index 02f053fb40d94..76e2cdd474423 100644 --- a/clang/test/Parser/opencl-pragma.cl +++ b/clang/test/Parser/opencl-pragma.cl @@ -2,7 +2,7 @@ #pragma OPENCL EXTENSION cl_khr_fp16 : enable -#pragma OPENCL EXTENSION cl_no_such_extension : disable /* expected-warning {{unknown OpenCL extension 'cl_no_such_extension' - ignoring}} */ +#pragma OPENCL EXTENSION cl_no_such_extension : disable /* expected-warning {{OpenCL extension 'cl_no_such_extension' unknown or does not require pragma - ignoring}} */ #pragma OPENCL EXTENSION all : disable #pragma OPENCL EXTENSION all : enable /* expected-warning {{expected 'disable' - ignoring}} */ diff --git a/clang/test/Preprocessor/file_test.c b/clang/test/Preprocessor/file_test.c index c800ab07eb62b..945882ded7a6a 100644 --- a/clang/test/Preprocessor/file_test.c +++ b/clang/test/Preprocessor/file_test.c @@ -8,9 +8,16 @@ // RUN: %clang -E -fmacro-prefix-map=%p/= -target x86_64-pc-win32 -c -o - %s | FileCheck %s --check-prefix CHECK-WINDOWS // RUN: %clang -E -ffile-prefix-map=%p/= -target x86_64-pc-win32 -c -o - %s | FileCheck %s --check-prefix CHECK-WINDOWS // RUN: %clang -E -ffile-reproducible -target x86_64-pc-win32 -c -o - %s | FileCheck %s --check-prefix CHECK-WINDOWS-REPRODUCIBLE +// RUN: %clang -E -ffile-reproducible -target x86_64-pc-linux-gnu -c -o - %s | FileCheck %s --check-prefix CHECK-LINUX-REPRODUCIBLE + +/// Clang-format wants to do something unreasonable to this file. +// clang-format off filename: __FILE__ -#include "Inputs/include-file-test/file_test.h" + +/// This line tests that the __FILE__ in included header is canonicalized +/// (has "./" removed). +#include "./Inputs/./include-file-test/file_test.h" // CHECK: filename: "/UNLIKELY_PATH/empty/file_test.c" // CHECK: filename: "/UNLIKELY_PATH/empty/Inputs/include-file-test/file_test.h" @@ -23,7 +30,7 @@ filename: __FILE__ // CHECK-EVIL-NOT: filename: // CHECK-REMOVE: filename: "file_test.c" -// CHECK-REMOVE: filename: "Inputs/include-file-test/file_test.h" +// CHECK-REMOVE: filename: "{{.*}}Inputs/{{.*}}include-file-test/file_test.h" // CHECK-REMOVE: basefile: "file_test.c" // CHECK-REMOVE-NOT: filename: @@ -32,7 +39,12 @@ filename: __FILE__ // CHECK-WINDOWS: basefile: "file_test.c" // CHECK-WINDOWS-NOT: filename: -// CHECK-WINDOWS-REPRODUCIBLE: filename: "{{[^/]*}}file_test.c" -// CHECK-WINDOWS-REPRODUCIBLE: filename: "{{[^/]*}}Inputs\\include-file-test\\file_test.h" -// CHECK-WINDOWS-REPRODUCIBLE: basefile: "{{[^/]*}}file_test.c" +// CHECK-WINDOWS-REPRODUCIBLE: filename: "{{.*}}\\file_test.c" +// CHECK-WINDOWS-REPRODUCIBLE: filename: "{{.*}}\\Inputs\\include-file-test\\file_test.h" +// CHECK-WINDOWS-REPRODUCIBLE: basefile: "{{.*}}\\file_test.c" // CHECK-WINDOWS-REPRODUCIBLE-NOT: filename: + +// CHECK-LINUX-REPRODUCIBLE: filename: "{{.*}}/file_test.c" +// CHECK-LINUX-REPRODUCIBLE: filename: "{{.*}}/Inputs/include-file-test/file_test.h" +// CHECK-LINUX-REPRODUCIBLE: basefile: "{{.*}}/file_test.c" +// CHECK-LINUX-REPRODUCIBLE-NOT: filename: diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c index 07b5fb86c45c2..61324fd5e43d8 100644 --- a/clang/test/Preprocessor/init.c +++ b/clang/test/Preprocessor/init.c @@ -1241,7 +1241,8 @@ // TCE:#define __tce__ 1 // TCE:#define tce 1 // -// RUN: %clang_cc1 -E -dM -ffreestanding -fgnuc-version=4.2.1 -triple=x86_64-scei-ps4 < /dev/null | FileCheck -match-full-lines -check-prefix PS4 %s +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-scei-ps4 < /dev/null | FileCheck --match-full-lines --check-prefixes=PS4,PS4ONLY %s +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-sie-ps5 < /dev/null | FileCheck --match-full-lines --check-prefixes=PS4,PS5ONLY %s // // PS4:#define _LP64 1 // PS4:#define __BIGGEST_ALIGNMENT__ 32 @@ -1311,8 +1312,9 @@ // PS4:#define __LP64__ 1 // PS4:#define __MMX__ 1 // PS4:#define __NO_MATH_INLINES 1 -// PS4:#define __ORBIS__ 1 +// PS4ONLY:#define __ORBIS__ 1 // PS4:#define __POINTER_WIDTH__ 64 +// PS5ONLY:#define __PROSPERO__ 1 // PS4:#define __PTRDIFF_MAX__ 9223372036854775807L // PS4:#define __PTRDIFF_TYPE__ long int // PS4:#define __PTRDIFF_WIDTH__ 64 @@ -1357,7 +1359,8 @@ // PS4:#define __x86_64__ 1 // PS4:#define unix 1 // -// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=x86_64-scei-ps4 < /dev/null | FileCheck -match-full-lines -check-prefix PS4-CXX %s +// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=x86_64-scei-ps4 < /dev/null | FileCheck --match-full-lines --check-prefix PS4-CXX %s +// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=x86_64-sie-ps5 < /dev/null | FileCheck --match-full-lines --check-prefix PS4-CXX %s // PS4-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 32UL // // RUN: %clang_cc1 -E -dM -triple=x86_64-pc-mingw32 < /dev/null | FileCheck -match-full-lines -check-prefix X86-64-DECLSPEC %s diff --git a/clang/test/Preprocessor/pragma-comment-elf.c b/clang/test/Preprocessor/pragma-comment-elf.c new file mode 100644 index 0000000000000..7b84aba51a0da --- /dev/null +++ b/clang/test/Preprocessor/pragma-comment-elf.c @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-extensions -triple x86_64-scei-ps4 +// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-extensions -triple x86_64-sie-ps5 +// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-extensions -triple i686-unknown-linux-gnu + +// On ELF targets, issue a diagnostic that pragma comments are ignored except: +// #pragma comment lib + +#pragma comment(lib) +#pragma comment(lib,"foo") +__pragma(comment(lib, "bar")) + +#pragma comment(linker) // expected-warning {{'#pragma comment linker' ignored}} +#pragma comment(linker,"foo") // expected-warning {{'#pragma comment linker' ignored}} +__pragma(comment(linker, " bar=" "2")) // expected-warning {{'#pragma comment linker' ignored}} + +#pragma comment(user) // expected-warning {{'#pragma comment user' ignored}} +#pragma comment(user, "Compiled on " __DATE__ " at " __TIME__ ) // expected-warning {{'#pragma comment user' ignored}} +__pragma(comment(user, "foo")) // expected-warning {{'#pragma comment user' ignored}} + +#pragma comment(compiler) // expected-warning {{'#pragma comment compiler' ignored}} +#pragma comment(compiler, "foo") // expected-warning {{'#pragma comment compiler' ignored}} +__pragma(comment(compiler, "foo")) // expected-warning {{'#pragma comment compiler' ignored}} + +#pragma comment(exestr) // expected-warning {{'#pragma comment exestr' ignored}} +#pragma comment(exestr, "foo") // expected-warning {{'#pragma comment exestr' ignored}} +__pragma(comment(exestr, "foo")) // expected-warning {{'#pragma comment exestr' ignored}} + +#pragma comment(foo) // expected-error {{unknown kind of pragma comment}} +__pragma(comment(foo)) // expected-error {{unknown kind of pragma comment}} diff --git a/clang/test/Preprocessor/pragma-comment-linux.c b/clang/test/Preprocessor/pragma-comment-linux.c deleted file mode 100644 index fcac049f46e83..0000000000000 --- a/clang/test/Preprocessor/pragma-comment-linux.c +++ /dev/null @@ -1,5 +0,0 @@ -// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fsyntax-only -verify %s -Wunknown-pragmas - -#pragma comment(linker, "") -// expected-warning@-1 {{'#pragma comment linker' ignored}} - diff --git a/clang/test/Preprocessor/pragma_ps4.c b/clang/test/Preprocessor/pragma_ps4.c deleted file mode 100644 index 63651b6a96fb1..0000000000000 --- a/clang/test/Preprocessor/pragma_ps4.c +++ /dev/null @@ -1,27 +0,0 @@ -// RUN: %clang_cc1 %s -triple x86_64-scei-ps4 -fsyntax-only -verify -fms-extensions - -// On PS4, issue a diagnostic that pragma comments are ignored except: -// #pragma comment lib - -#pragma comment(lib) -#pragma comment(lib,"foo") -__pragma(comment(lib, "bar")) - -#pragma comment(linker) // expected-warning {{'#pragma comment linker' ignored}} -#pragma comment(linker,"foo") // expected-warning {{'#pragma comment linker' ignored}} -__pragma(comment(linker, " bar=" "2")) // expected-warning {{'#pragma comment linker' ignored}} - -#pragma comment(user) // expected-warning {{'#pragma comment user' ignored}} -#pragma comment(user, "Compiled on " __DATE__ " at " __TIME__ ) // expected-warning {{'#pragma comment user' ignored}} -__pragma(comment(user, "foo")) // expected-warning {{'#pragma comment user' ignored}} - -#pragma comment(compiler) // expected-warning {{'#pragma comment compiler' ignored}} -#pragma comment(compiler, "foo") // expected-warning {{'#pragma comment compiler' ignored}} -__pragma(comment(compiler, "foo")) // expected-warning {{'#pragma comment compiler' ignored}} - -#pragma comment(exestr) // expected-warning {{'#pragma comment exestr' ignored}} -#pragma comment(exestr, "foo") // expected-warning {{'#pragma comment exestr' ignored}} -__pragma(comment(exestr, "foo")) // expected-warning {{'#pragma comment exestr' ignored}} - -#pragma comment(foo) // expected-error {{unknown kind of pragma comment}} -__pragma(comment(foo)) // expected-error {{unknown kind of pragma comment}} diff --git a/clang/test/Preprocessor/suggest-typoed-directive.c b/clang/test/Preprocessor/suggest-typoed-directive.c index 8dd7ef4feaf69..cc15efee09e1c 100644 --- a/clang/test/Preprocessor/suggest-typoed-directive.c +++ b/clang/test/Preprocessor/suggest-typoed-directive.c @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify=pre-c2x-cpp2b %s // RUN: %clang_cc1 -std=c2x -fsyntax-only -verify=c2x-cpp2b %s // RUN: %clang_cc1 -x c++ -std=c++2b -fsyntax-only -verify=c2x-cpp2b %s +// RUN: %clang_cc1 -x c++ -std=c++2b -fsyntax-only %s -fdiagnostics-parseable-fixits 2>&1 | FileCheck %s // id: pre-c2x-cpp2b-warning@+12 {{invalid preprocessing directive, did you mean '#if'?}} // ifd: pre-c2x-cpp2b-warning@+12 {{invalid preprocessing directive, did you mean '#if'?}} @@ -17,8 +18,8 @@ #id #ifd #ifde -#elf -#elsif +# elf +# elsif #elseif #elfidef #elfindef @@ -38,6 +39,18 @@ // els: c2x-cpp2b-warning@-12 {{invalid preprocessing directive, did you mean '#else'?}} // endi: c2x-cpp2b-warning@-12 {{invalid preprocessing directive, did you mean '#endif'?}} +// CHECK: fix-it:{{.*}}:{[[@LINE-24]]:2-[[@LINE-24]]:4}:"if" +// CHECK: fix-it:{{.*}}:{[[@LINE-24]]:2-[[@LINE-24]]:5}:"if" +// CHECK: fix-it:{{.*}}:{[[@LINE-24]]:2-[[@LINE-24]]:6}:"ifdef" +// CHECK: fix-it:{{.*}}:{[[@LINE-24]]:3-[[@LINE-24]]:6}:"elif" +// CHECK: fix-it:{{.*}}:{[[@LINE-24]]:4-[[@LINE-24]]:9}:"elif" +// CHECK: fix-it:{{.*}}:{[[@LINE-24]]:2-[[@LINE-24]]:8}:"elif" +// CHECK: fix-it:{{.*}}:{[[@LINE-24]]:2-[[@LINE-24]]:9}:"elifdef" +// CHECK: fix-it:{{.*}}:{[[@LINE-24]]:2-[[@LINE-24]]:10}:"elifdef" +// CHECK: fix-it:{{.*}}:{[[@LINE-24]]:2-[[@LINE-24]]:11}:"elifndef" +// CHECK: fix-it:{{.*}}:{[[@LINE-24]]:2-[[@LINE-24]]:5}:"else" +// CHECK: fix-it:{{.*}}:{[[@LINE-24]]:2-[[@LINE-24]]:6}:"endif" + #ifdef UNDEFINED #i // no diagnostic #endif diff --git a/clang/test/Sema/aarch64-sve-vector-arith-ops.c b/clang/test/Sema/aarch64-sve-vector-arith-ops.c index 89f4778f1575c..c8147d287f647 100644 --- a/clang/test/Sema/aarch64-sve-vector-arith-ops.c +++ b/clang/test/Sema/aarch64-sve-vector-arith-ops.c @@ -4,895 +4,659 @@ #include +struct S { + int x; +}; + void add(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, - svbool_t b) { + svbool_t b, struct S s) { (void)(b + b); // expected-error{{invalid operands to binary expression}} (void)(i8 + b); // expected-error{{invalid operands to binary expression}} - (void)(i8 + i16); // expected-error{{invalid operands to binary expression}} - (void)(i8 + i32); // expected-error{{invalid operands to binary expression}} - (void)(i8 + i64); // expected-error{{invalid operands to binary expression}} - (void)(i8 + u16); // expected-error{{invalid operands to binary expression}} - (void)(i8 + u32); // expected-error{{invalid operands to binary expression}} - (void)(i8 + u64); // expected-error{{invalid operands to binary expression}} - (void)(i8 + f16); // expected-error{{invalid operands to binary expression}} - (void)(i8 + f32); // expected-error{{invalid operands to binary expression}} - (void)(i8 + f64); // expected-error{{invalid operands to binary expression}} - (void)(i8 + 0); // expected-error{{invalid operands to binary expression}} - (void)(i8 + 0l); // expected-error{{invalid operands to binary expression}} - (void)(i8 + 0u); // expected-error{{invalid operands to binary expression}} - (void)(i8 + 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i8 + 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i8 + 0.); // expected-error{{invalid operands to binary expression}} + (void)(i8 + i16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i8 + i32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i8 + i64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i8 + u16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i8 + u32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i8 + u64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i8 + f16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i8 + f32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i8 + f64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(u8 + b); // expected-error{{invalid operands to binary expression}} - (void)(u8 + i16); // expected-error{{invalid operands to binary expression}} - (void)(u8 + i32); // expected-error{{invalid operands to binary expression}} - (void)(u8 + i64); // expected-error{{invalid operands to binary expression}} - (void)(u8 + u16); // expected-error{{invalid operands to binary expression}} - (void)(u8 + u32); // expected-error{{invalid operands to binary expression}} - (void)(u8 + u64); // expected-error{{invalid operands to binary expression}} - (void)(u8 + f16); // expected-error{{invalid operands to binary expression}} - (void)(u8 + f32); // expected-error{{invalid operands to binary expression}} - (void)(u8 + f64); // expected-error{{invalid operands to binary expression}} - (void)(u8 + 0); // expected-error{{invalid operands to binary expression}} - (void)(u8 + 0l); // expected-error{{invalid operands to binary expression}} - (void)(u8 + 0u); // expected-error{{invalid operands to binary expression}} - (void)(u8 + 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u8 + 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u8 + 0.); // expected-error{{invalid operands to binary expression}} + (void)(u8 + i16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u8 + i32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u8 + i64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u8 + u16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u8 + u32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u8 + u64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u8 + f16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u8 + f32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u8 + f64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(i16 + b); // expected-error{{invalid operands to binary expression}} - (void)(i16 + i8); // expected-error{{invalid operands to binary expression}} - (void)(i16 + i32); // expected-error{{invalid operands to binary expression}} - (void)(i16 + i64); // expected-error{{invalid operands to binary expression}} - (void)(i16 + u8); // expected-error{{invalid operands to binary expression}} - (void)(i16 + u32); // expected-error{{invalid operands to binary expression}} - (void)(i16 + u64); // expected-error{{invalid operands to binary expression}} - (void)(i16 + f16); // expected-error{{invalid operands to binary expression}} - (void)(i16 + f32); // expected-error{{invalid operands to binary expression}} - (void)(i16 + f64); // expected-error{{invalid operands to binary expression}} - (void)(i16 + 0); // expected-error{{invalid operands to binary expression}} - (void)(i16 + 0l); // expected-error{{invalid operands to binary expression}} - (void)(i16 + 0u); // expected-error{{invalid operands to binary expression}} - (void)(i16 + 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i16 + 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i16 + 0.); // expected-error{{invalid operands to binary expression}} + (void)(i16 + i8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i16 + i32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i16 + i64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i16 + u8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i16 + u32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i16 + u64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i16 + f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svint16_t' (aka '__SVInt16_t') as implicit conversion would cause truncation}} + (void)(i16 + f32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i16 + f64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(u16 + b); // expected-error{{invalid operands to binary expression}} - (void)(u16 + i8); // expected-error{{invalid operands to binary expression}} - (void)(u16 + i32); // expected-error{{invalid operands to binary expression}} - (void)(u16 + i64); // expected-error{{invalid operands to binary expression}} - (void)(u16 + u8); // expected-error{{invalid operands to binary expression}} - (void)(u16 + u32); // expected-error{{invalid operands to binary expression}} - (void)(u16 + u64); // expected-error{{invalid operands to binary expression}} - (void)(u16 + f16); // expected-error{{invalid operands to binary expression}} - (void)(u16 + f32); // expected-error{{invalid operands to binary expression}} - (void)(u16 + f64); // expected-error{{invalid operands to binary expression}} - (void)(u16 + 0); // expected-error{{invalid operands to binary expression}} - (void)(u16 + 0l); // expected-error{{invalid operands to binary expression}} - (void)(u16 + 0u); // expected-error{{invalid operands to binary expression}} - (void)(u16 + 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u16 + 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u16 + 0.); // expected-error{{invalid operands to binary expression}} + (void)(u16 + i8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u16 + i32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u16 + i64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u16 + u8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u16 + u32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u16 + u64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u16 + f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svuint16_t' (aka '__SVUint16_t') as implicit conversion would cause truncation}} + (void)(u16 + f32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u16 + f64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(i32 + b); // expected-error{{invalid operands to binary expression}} - (void)(i32 + i8); // expected-error{{invalid operands to binary expression}} - (void)(i32 + i16); // expected-error{{invalid operands to binary expression}} - (void)(i32 + i64); // expected-error{{invalid operands to binary expression}} - (void)(i32 + u8); // expected-error{{invalid operands to binary expression}} - (void)(i32 + u16); // expected-error{{invalid operands to binary expression}} - (void)(i32 + u64); // expected-error{{invalid operands to binary expression}} - (void)(i32 + f16); // expected-error{{invalid operands to binary expression}} - (void)(i32 + f32); // expected-error{{invalid operands to binary expression}} - (void)(i32 + f64); // expected-error{{invalid operands to binary expression}} - (void)(i32 + 0l); // expected-error{{invalid operands to binary expression}} - (void)(i32 + 0u); // expected-error{{invalid operands to binary expression}} - (void)(i32 + 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i32 + 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i32 + 0.); // expected-error{{invalid operands to binary expression}} + (void)(i32 + i8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i32 + i16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i32 + i64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i32 + u8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i32 + u16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i32 + u64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i32 + f16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i32 + f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svint32_t' (aka '__SVInt32_t') as implicit conversion would cause truncation}} + (void)(i32 + f64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(u32 + b); // expected-error{{invalid operands to binary expression}} - (void)(u32 + i8); // expected-error{{invalid operands to binary expression}} - (void)(u32 + i16); // expected-error{{invalid operands to binary expression}} - (void)(u32 + i64); // expected-error{{invalid operands to binary expression}} - (void)(u32 + u8); // expected-error{{invalid operands to binary expression}} - (void)(u32 + u16); // expected-error{{invalid operands to binary expression}} - (void)(u32 + u64); // expected-error{{invalid operands to binary expression}} - (void)(u32 + f16); // expected-error{{invalid operands to binary expression}} - (void)(u32 + f32); // expected-error{{invalid operands to binary expression}} - (void)(u32 + f64); // expected-error{{invalid operands to binary expression}} - (void)(u32 + 0); // expected-error{{invalid operands to binary expression}} - (void)(u32 + 0l); // expected-error{{invalid operands to binary expression}} - (void)(u32 + 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u32 + 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u32 + 0.); // expected-error{{invalid operands to binary expression}} + (void)(u32 + i8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u32 + i16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u32 + i64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u32 + u8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u32 + u16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u32 + u64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u32 + f16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u32 + f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svuint32_t' (aka '__SVUint32_t') as implicit conversion would cause truncation}} + (void)(u32 + f64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(i64 + b); // expected-error{{invalid operands to binary expression}} - (void)(i64 + i8); // expected-error{{invalid operands to binary expression}} - (void)(i64 + i16); // expected-error{{invalid operands to binary expression}} - (void)(i64 + i32); // expected-error{{invalid operands to binary expression}} - (void)(i64 + u8); // expected-error{{invalid operands to binary expression}} - (void)(i64 + u16); // expected-error{{invalid operands to binary expression}} - (void)(i64 + u32); // expected-error{{invalid operands to binary expression}} - (void)(i64 + f16); // expected-error{{invalid operands to binary expression}} - (void)(i64 + f32); // expected-error{{invalid operands to binary expression}} - (void)(i64 + f64); // expected-error{{invalid operands to binary expression}} - (void)(i64 + 0); // expected-error{{invalid operands to binary expression}} - (void)(i64 + 0u); // expected-error{{invalid operands to binary expression}} - (void)(i64 + 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i64 + 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i64 + 0.); // expected-error{{invalid operands to binary expression}} + (void)(i64 + i8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i64 + i16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i64 + i32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i64 + u8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i64 + u16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i64 + u32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i64 + f16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i64 + f32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i64 + f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svint64_t' (aka '__SVInt64_t') as implicit conversion would cause truncation}} (void)(u64 + b); // expected-error{{invalid operands to binary expression}} - (void)(u64 + i8); // expected-error{{invalid operands to binary expression}} - (void)(u64 + i16); // expected-error{{invalid operands to binary expression}} - (void)(u64 + i32); // expected-error{{invalid operands to binary expression}} - (void)(u64 + u8); // expected-error{{invalid operands to binary expression}} - (void)(u64 + u16); // expected-error{{invalid operands to binary expression}} - (void)(u64 + u32); // expected-error{{invalid operands to binary expression}} - (void)(u64 + f16); // expected-error{{invalid operands to binary expression}} - (void)(u64 + f32); // expected-error{{invalid operands to binary expression}} - (void)(u64 + f64); // expected-error{{invalid operands to binary expression}} - (void)(u64 + 0); // expected-error{{invalid operands to binary expression}} - (void)(u64 + 0l); // expected-error{{invalid operands to binary expression}} - (void)(u64 + 0u); // expected-error{{invalid operands to binary expression}} - (void)(u64 + 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u64 + 0.); // expected-error{{invalid operands to binary expression}} + (void)(u64 + i8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u64 + i16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u64 + i32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u64 + u8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u64 + u16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u64 + u32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u64 + f16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u64 + f32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u64 + f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svuint64_t' (aka '__SVUint64_t') as implicit conversion would cause truncation}} (void)(f16 + b); // expected-error{{invalid operands to binary expression}} - (void)(f16 + i8); // expected-error{{invalid operands to binary expression}} - (void)(f16 + i16); // expected-error{{invalid operands to binary expression}} - (void)(f16 + i32); // expected-error{{invalid operands to binary expression}} - (void)(f16 + i64); // expected-error{{invalid operands to binary expression}} - (void)(f16 + u8); // expected-error{{invalid operands to binary expression}} - (void)(f16 + u32); // expected-error{{invalid operands to binary expression}} - (void)(f16 + u64); // expected-error{{invalid operands to binary expression}} - (void)(f16 + f32); // expected-error{{invalid operands to binary expression}} - (void)(f16 + f64); // expected-error{{invalid operands to binary expression}} - (void)(f16 + 0); // expected-error{{invalid operands to binary expression}} - (void)(f16 + 0l); // expected-error{{invalid operands to binary expression}} - (void)(f16 + 0u); // expected-error{{invalid operands to binary expression}} - (void)(f16 + 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f16 + 0.f); // expected-error{{invalid operands to binary expression}} - (void)(f16 + 0.); // expected-error{{invalid operands to binary expression}} + (void)(f16 + i8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f16 + i16); // expected-error{{cannot convert between vector type 'svint16_t' (aka '__SVInt16_t') and vector type 'svfloat16_t' (aka '__SVFloat16_t') as implicit conversion would cause truncation}} + (void)(f16 + i32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f16 + i64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f16 + u8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f16 + u32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f16 + u64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f16 + f32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(f16 + f64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(f32 + b); // expected-error{{invalid operands to binary expression}} - (void)(f32 + i8); // expected-error{{invalid operands to binary expression}} - (void)(f32 + i16); // expected-error{{invalid operands to binary expression}} - (void)(f32 + i32); // expected-error{{invalid operands to binary expression}} - (void)(f32 + i64); // expected-error{{invalid operands to binary expression}} - (void)(f32 + u8); // expected-error{{invalid operands to binary expression}} - (void)(f32 + u16); // expected-error{{invalid operands to binary expression}} - (void)(f32 + u64); // expected-error{{invalid operands to binary expression}} - (void)(f32 + f16); // expected-error{{invalid operands to binary expression}} - (void)(f32 + f64); // expected-error{{invalid operands to binary expression}} - (void)(f32 + 0); // expected-error{{invalid operands to binary expression}} - (void)(f32 + 0l); // expected-error{{invalid operands to binary expression}} - (void)(f32 + 0u); // expected-error{{invalid operands to binary expression}} - (void)(f32 + 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f32 + 0.); // expected-error{{invalid operands to binary expression}} + (void)(f32 + i8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f32 + i16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f32 + i32); // expected-error{{cannot convert between vector type 'svint32_t' (aka '__SVInt32_t') and vector type 'svfloat32_t' (aka '__SVFloat32_t') as implicit conversion would cause truncation}} + (void)(f32 + i64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f32 + u8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f32 + u16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f32 + u64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f32 + f16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f32 + f64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(f64 + b); // expected-error{{invalid operands to binary expression}} - (void)(f64 + i8); // expected-error{{invalid operands to binary expression}} - (void)(f64 + i16); // expected-error{{invalid operands to binary expression}} - (void)(f64 + i32); // expected-error{{invalid operands to binary expression}} - (void)(f64 + i64); // expected-error{{invalid operands to binary expression}} - (void)(f64 + u8); // expected-error{{invalid operands to binary expression}} - (void)(f64 + u16); // expected-error{{invalid operands to binary expression}} - (void)(f64 + u32); // expected-error{{invalid operands to binary expression}} - (void)(f64 + f16); // expected-error{{invalid operands to binary expression}} - (void)(f64 + f32); // expected-error{{invalid operands to binary expression}} - (void)(f64 + 0); // expected-error{{invalid operands to binary expression}} - (void)(f64 + 0l); // expected-error{{invalid operands to binary expression}} - (void)(f64 + 0u); // expected-error{{invalid operands to binary expression}} - (void)(f64 + 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f64 + 0.f); // expected-error{{invalid operands to binary expression}} + (void)(f64 + i8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f64 + i16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f64 + i32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f64 + i64); // expected-error{{cannot convert between vector type 'svint64_t' (aka '__SVInt64_t') and vector type 'svfloat64_t' (aka '__SVFloat64_t') as implicit conversion would cause truncation}} + (void)(f64 + u8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f64 + u16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f64 + u32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f64 + f16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f64 + f32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + + (void)(s + i8); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s + i16); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s + i32); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s + i64); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s + u16); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s + u32); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s + u64); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s + f16); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s + f32); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s + f64); // expected-error{{cannot convert between vector and non-scalar values}} } void sub(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, - svbool_t b) { + svbool_t b, struct S s) { (void)(b - b); // expected-error{{invalid operands to binary expression}} (void)(i8 - b); // expected-error{{invalid operands to binary expression}} - (void)(i8 - i16); // expected-error{{invalid operands to binary expression}} - (void)(i8 - i32); // expected-error{{invalid operands to binary expression}} - (void)(i8 - i64); // expected-error{{invalid operands to binary expression}} - (void)(i8 - u16); // expected-error{{invalid operands to binary expression}} - (void)(i8 - u32); // expected-error{{invalid operands to binary expression}} - (void)(i8 - u64); // expected-error{{invalid operands to binary expression}} - (void)(i8 - f16); // expected-error{{invalid operands to binary expression}} - (void)(i8 - f32); // expected-error{{invalid operands to binary expression}} - (void)(i8 - f64); // expected-error{{invalid operands to binary expression}} - (void)(i8 - 0); // expected-error{{invalid operands to binary expression}} - (void)(i8 - 0l); // expected-error{{invalid operands to binary expression}} - (void)(i8 - 0u); // expected-error{{invalid operands to binary expression}} - (void)(i8 - 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i8 - 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i8 - 0.); // expected-error{{invalid operands to binary expression}} + (void)(i8 - i16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i8 - i32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i8 - i64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i8 - u16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i8 - u32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i8 - u64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i8 - f16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i8 - f32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i8 - f64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(u8 - b); // expected-error{{invalid operands to binary expression}} - (void)(u8 - i16); // expected-error{{invalid operands to binary expression}} - (void)(u8 - i32); // expected-error{{invalid operands to binary expression}} - (void)(u8 - i64); // expected-error{{invalid operands to binary expression}} - (void)(u8 - u16); // expected-error{{invalid operands to binary expression}} - (void)(u8 - u32); // expected-error{{invalid operands to binary expression}} - (void)(u8 - u64); // expected-error{{invalid operands to binary expression}} - (void)(u8 - f16); // expected-error{{invalid operands to binary expression}} - (void)(u8 - f32); // expected-error{{invalid operands to binary expression}} - (void)(u8 - f64); // expected-error{{invalid operands to binary expression}} - (void)(u8 - 0); // expected-error{{invalid operands to binary expression}} - (void)(u8 - 0l); // expected-error{{invalid operands to binary expression}} - (void)(u8 - 0u); // expected-error{{invalid operands to binary expression}} - (void)(u8 - 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u8 - 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u8 - 0.); // expected-error{{invalid operands to binary expression}} + (void)(u8 - i16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u8 - i32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u8 - i64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u8 - u16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u8 - u32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u8 - u64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u8 - f16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u8 - f32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u8 - f64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(i16 - b); // expected-error{{invalid operands to binary expression}} - (void)(i16 - i8); // expected-error{{invalid operands to binary expression}} - (void)(i16 - i32); // expected-error{{invalid operands to binary expression}} - (void)(i16 - i64); // expected-error{{invalid operands to binary expression}} - (void)(i16 - u8); // expected-error{{invalid operands to binary expression}} - (void)(i16 - u32); // expected-error{{invalid operands to binary expression}} - (void)(i16 - u64); // expected-error{{invalid operands to binary expression}} - (void)(i16 - f16); // expected-error{{invalid operands to binary expression}} - (void)(i16 - f32); // expected-error{{invalid operands to binary expression}} - (void)(i16 - f64); // expected-error{{invalid operands to binary expression}} - (void)(i16 - 0); // expected-error{{invalid operands to binary expression}} - (void)(i16 - 0l); // expected-error{{invalid operands to binary expression}} - (void)(i16 - 0u); // expected-error{{invalid operands to binary expression}} - (void)(i16 - 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i16 - 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i16 - 0.); // expected-error{{invalid operands to binary expression}} + (void)(i16 - i8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i16 - i32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i16 - i64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i16 - u8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i16 - u32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i16 - u64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i16 - f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svint16_t' (aka '__SVInt16_t') as implicit conversion would cause truncation}} + (void)(i16 - f32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i16 - f64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(u16 - b); // expected-error{{invalid operands to binary expression}} - (void)(u16 - i8); // expected-error{{invalid operands to binary expression}} - (void)(u16 - i32); // expected-error{{invalid operands to binary expression}} - (void)(u16 - i64); // expected-error{{invalid operands to binary expression}} - (void)(u16 - u8); // expected-error{{invalid operands to binary expression}} - (void)(u16 - u32); // expected-error{{invalid operands to binary expression}} - (void)(u16 - u64); // expected-error{{invalid operands to binary expression}} - (void)(u16 - f16); // expected-error{{invalid operands to binary expression}} - (void)(u16 - f32); // expected-error{{invalid operands to binary expression}} - (void)(u16 - f64); // expected-error{{invalid operands to binary expression}} - (void)(u16 - 0); // expected-error{{invalid operands to binary expression}} - (void)(u16 - 0l); // expected-error{{invalid operands to binary expression}} - (void)(u16 - 0u); // expected-error{{invalid operands to binary expression}} - (void)(u16 - 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u16 - 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u16 - 0.); // expected-error{{invalid operands to binary expression}} + (void)(u16 - i8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u16 - i32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u16 - i64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u16 - u8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u16 - u32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u16 - u64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u16 - f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svuint16_t' (aka '__SVUint16_t') as implicit conversion would cause truncation}} + (void)(u16 - f32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u16 - f64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(i32 - b); // expected-error{{invalid operands to binary expression}} - (void)(i32 - i8); // expected-error{{invalid operands to binary expression}} - (void)(i32 - i16); // expected-error{{invalid operands to binary expression}} - (void)(i32 - i64); // expected-error{{invalid operands to binary expression}} - (void)(i32 - u8); // expected-error{{invalid operands to binary expression}} - (void)(i32 - u16); // expected-error{{invalid operands to binary expression}} - (void)(i32 - u64); // expected-error{{invalid operands to binary expression}} - (void)(i32 - f16); // expected-error{{invalid operands to binary expression}} - (void)(i32 - f32); // expected-error{{invalid operands to binary expression}} - (void)(i32 - f64); // expected-error{{invalid operands to binary expression}} - (void)(i32 - 0l); // expected-error{{invalid operands to binary expression}} - (void)(i32 - 0u); // expected-error{{invalid operands to binary expression}} - (void)(i32 - 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i32 - 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i32 - 0.); // expected-error{{invalid operands to binary expression}} + (void)(i32 - i8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i32 - i16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i32 - i64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i32 - u8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i32 - u16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i32 - u64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i32 - f16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i32 - f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svint32_t' (aka '__SVInt32_t') as implicit conversion would cause truncation}} + (void)(i32 - f64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(u32 - b); // expected-error{{invalid operands to binary expression}} - (void)(u32 - i8); // expected-error{{invalid operands to binary expression}} - (void)(u32 - i16); // expected-error{{invalid operands to binary expression}} - (void)(u32 - i64); // expected-error{{invalid operands to binary expression}} - (void)(u32 - u8); // expected-error{{invalid operands to binary expression}} - (void)(u32 - u16); // expected-error{{invalid operands to binary expression}} - (void)(u32 - u64); // expected-error{{invalid operands to binary expression}} - (void)(u32 - f16); // expected-error{{invalid operands to binary expression}} - (void)(u32 - f32); // expected-error{{invalid operands to binary expression}} - (void)(u32 - f64); // expected-error{{invalid operands to binary expression}} - (void)(u32 - 0); // expected-error{{invalid operands to binary expression}} - (void)(u32 - 0l); // expected-error{{invalid operands to binary expression}} - (void)(u32 - 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u32 - 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u32 - 0.); // expected-error{{invalid operands to binary expression}} + (void)(u32 - i8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u32 - i16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u32 - i64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u32 - u8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u32 - u16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u32 - u64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u32 - f16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u32 - f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svuint32_t' (aka '__SVUint32_t') as implicit conversion would cause truncation}} + (void)(u32 - f64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(i64 - b); // expected-error{{invalid operands to binary expression}} - (void)(i64 - i8); // expected-error{{invalid operands to binary expression}} - (void)(i64 - i16); // expected-error{{invalid operands to binary expression}} - (void)(i64 - i32); // expected-error{{invalid operands to binary expression}} - (void)(i64 - u8); // expected-error{{invalid operands to binary expression}} - (void)(i64 - u16); // expected-error{{invalid operands to binary expression}} - (void)(i64 - u32); // expected-error{{invalid operands to binary expression}} - (void)(i64 - f16); // expected-error{{invalid operands to binary expression}} - (void)(i64 - f32); // expected-error{{invalid operands to binary expression}} - (void)(i64 - f64); // expected-error{{invalid operands to binary expression}} - (void)(i64 - 0); // expected-error{{invalid operands to binary expression}} - (void)(i64 - 0u); // expected-error{{invalid operands to binary expression}} - (void)(i64 - 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i64 - 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i64 - 0.); // expected-error{{invalid operands to binary expression}} + (void)(i64 - i8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i64 - i16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i64 - i32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i64 - u8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i64 - u16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i64 - u32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i64 - f16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i64 - f32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i64 - f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svint64_t' (aka '__SVInt64_t') as implicit conversion would cause truncation}} (void)(u64 - b); // expected-error{{invalid operands to binary expression}} - (void)(u64 - i8); // expected-error{{invalid operands to binary expression}} - (void)(u64 - i16); // expected-error{{invalid operands to binary expression}} - (void)(u64 - i32); // expected-error{{invalid operands to binary expression}} - (void)(u64 - u8); // expected-error{{invalid operands to binary expression}} - (void)(u64 - u16); // expected-error{{invalid operands to binary expression}} - (void)(u64 - u32); // expected-error{{invalid operands to binary expression}} - (void)(u64 - f16); // expected-error{{invalid operands to binary expression}} - (void)(u64 - f32); // expected-error{{invalid operands to binary expression}} - (void)(u64 - f64); // expected-error{{invalid operands to binary expression}} - (void)(u64 - 0); // expected-error{{invalid operands to binary expression}} - (void)(u64 - 0l); // expected-error{{invalid operands to binary expression}} - (void)(u64 - 0u); // expected-error{{invalid operands to binary expression}} - (void)(u64 - 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u64 - 0.); // expected-error{{invalid operands to binary expression}} + (void)(u64 - i8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u64 - i16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u64 - i32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u64 - u8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u64 - u16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u64 - u32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u64 - f16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u64 - f32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u64 - f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svuint64_t' (aka '__SVUint64_t') as implicit conversion would cause truncation}} (void)(f16 - b); // expected-error{{invalid operands to binary expression}} - (void)(f16 - i8); // expected-error{{invalid operands to binary expression}} - (void)(f16 - i16); // expected-error{{invalid operands to binary expression}} - (void)(f16 - i32); // expected-error{{invalid operands to binary expression}} - (void)(f16 - i64); // expected-error{{invalid operands to binary expression}} - (void)(f16 - u8); // expected-error{{invalid operands to binary expression}} - (void)(f16 - u32); // expected-error{{invalid operands to binary expression}} - (void)(f16 - u64); // expected-error{{invalid operands to binary expression}} - (void)(f16 - f32); // expected-error{{invalid operands to binary expression}} - (void)(f16 - f64); // expected-error{{invalid operands to binary expression}} - (void)(f16 - 0); // expected-error{{invalid operands to binary expression}} - (void)(f16 - 0l); // expected-error{{invalid operands to binary expression}} - (void)(f16 - 0u); // expected-error{{invalid operands to binary expression}} - (void)(f16 - 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f16 - 0.f); // expected-error{{invalid operands to binary expression}} - (void)(f16 - 0.); // expected-error{{invalid operands to binary expression}} + (void)(f16 - i8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f16 - i16); // expected-error{{cannot convert between vector type 'svint16_t' (aka '__SVInt16_t') and vector type 'svfloat16_t' (aka '__SVFloat16_t') as implicit conversion would cause truncation}} + (void)(f16 - i32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f16 - i64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f16 - u8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f16 - u32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f16 - u64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f16 - f32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(f16 - f64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(f32 - b); // expected-error{{invalid operands to binary expression}} - (void)(f32 - i8); // expected-error{{invalid operands to binary expression}} - (void)(f32 - i16); // expected-error{{invalid operands to binary expression}} - (void)(f32 - i32); // expected-error{{invalid operands to binary expression}} - (void)(f32 - i64); // expected-error{{invalid operands to binary expression}} - (void)(f32 - u8); // expected-error{{invalid operands to binary expression}} - (void)(f32 - u16); // expected-error{{invalid operands to binary expression}} - (void)(f32 - u64); // expected-error{{invalid operands to binary expression}} - (void)(f32 - f16); // expected-error{{invalid operands to binary expression}} - (void)(f32 - f64); // expected-error{{invalid operands to binary expression}} - (void)(f32 - 0); // expected-error{{invalid operands to binary expression}} - (void)(f32 - 0l); // expected-error{{invalid operands to binary expression}} - (void)(f32 - 0u); // expected-error{{invalid operands to binary expression}} - (void)(f32 - 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f32 - 0.); // expected-error{{invalid operands to binary expression}} + (void)(f32 - i8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f32 - i16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f32 - i32); // expected-error{{cannot convert between vector type 'svint32_t' (aka '__SVInt32_t') and vector type 'svfloat32_t' (aka '__SVFloat32_t') as implicit conversion would cause truncation}} + (void)(f32 - i64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f32 - u8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f32 - u16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f32 - u64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f32 - f16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f32 - f64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(f64 - b); // expected-error{{invalid operands to binary expression}} - (void)(f64 - i8); // expected-error{{invalid operands to binary expression}} - (void)(f64 - i16); // expected-error{{invalid operands to binary expression}} - (void)(f64 - i32); // expected-error{{invalid operands to binary expression}} - (void)(f64 - i64); // expected-error{{invalid operands to binary expression}} - (void)(f64 - u8); // expected-error{{invalid operands to binary expression}} - (void)(f64 - u16); // expected-error{{invalid operands to binary expression}} - (void)(f64 - u32); // expected-error{{invalid operands to binary expression}} - (void)(f64 - f16); // expected-error{{invalid operands to binary expression}} - (void)(f64 - f32); // expected-error{{invalid operands to binary expression}} - (void)(f64 - 0); // expected-error{{invalid operands to binary expression}} - (void)(f64 - 0l); // expected-error{{invalid operands to binary expression}} - (void)(f64 - 0u); // expected-error{{invalid operands to binary expression}} - (void)(f64 - 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f64 - 0.f); // expected-error{{invalid operands to binary expression}} + (void)(f64 - i8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f64 - i16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f64 - i32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f64 - i64); // expected-error{{cannot convert between vector type 'svint64_t' (aka '__SVInt64_t') and vector type 'svfloat64_t' (aka '__SVFloat64_t') as implicit conversion would cause truncation}} + (void)(f64 - u8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f64 - u16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f64 - u32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f64 - f16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f64 - f32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + + (void)(s - i8); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s - i16); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s - i32); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s - i64); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s - u16); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s - u32); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s - u64); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s - f16); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s - f32); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s - f64); // expected-error{{cannot convert between vector and non-scalar values}} } void mul(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, - svbool_t b) { + svbool_t b, struct S s) { (void)(b * b); // expected-error{{invalid operands to binary expression}} (void)(i8 * b); // expected-error{{invalid operands to binary expression}} - (void)(i8 * i16); // expected-error{{invalid operands to binary expression}} - (void)(i8 * i32); // expected-error{{invalid operands to binary expression}} - (void)(i8 * i64); // expected-error{{invalid operands to binary expression}} - (void)(i8 * u16); // expected-error{{invalid operands to binary expression}} - (void)(i8 * u32); // expected-error{{invalid operands to binary expression}} - (void)(i8 * u64); // expected-error{{invalid operands to binary expression}} - (void)(i8 * f16); // expected-error{{invalid operands to binary expression}} - (void)(i8 * f32); // expected-error{{invalid operands to binary expression}} - (void)(i8 * f64); // expected-error{{invalid operands to binary expression}} - (void)(i8 * 0); // expected-error{{invalid operands to binary expression}} - (void)(i8 * 0l); // expected-error{{invalid operands to binary expression}} - (void)(i8 * 0u); // expected-error{{invalid operands to binary expression}} - (void)(i8 * 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i8 * 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i8 * 0.); // expected-error{{invalid operands to binary expression}} + (void)(i8 * i16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i8 * i32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i8 * i64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i8 * u16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i8 * u32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i8 * u64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i8 * f16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i8 * f32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i8 * f64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(u8 * b); // expected-error{{invalid operands to binary expression}} - (void)(u8 * i16); // expected-error{{invalid operands to binary expression}} - (void)(u8 * i32); // expected-error{{invalid operands to binary expression}} - (void)(u8 * i64); // expected-error{{invalid operands to binary expression}} - (void)(u8 * u16); // expected-error{{invalid operands to binary expression}} - (void)(u8 * u32); // expected-error{{invalid operands to binary expression}} - (void)(u8 * u64); // expected-error{{invalid operands to binary expression}} - (void)(u8 * f16); // expected-error{{invalid operands to binary expression}} - (void)(u8 * f32); // expected-error{{invalid operands to binary expression}} - (void)(u8 * f64); // expected-error{{invalid operands to binary expression}} - (void)(u8 * 0); // expected-error{{invalid operands to binary expression}} - (void)(u8 * 0l); // expected-error{{invalid operands to binary expression}} - (void)(u8 * 0u); // expected-error{{invalid operands to binary expression}} - (void)(u8 * 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u8 * 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u8 * 0.); // expected-error{{invalid operands to binary expression}} + (void)(u8 * i16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u8 * i32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u8 * i64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u8 * u16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u8 * u32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u8 * u64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u8 * f16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u8 * f32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u8 * f64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(i16 * b); // expected-error{{invalid operands to binary expression}} - (void)(i16 * i8); // expected-error{{invalid operands to binary expression}} - (void)(i16 * i32); // expected-error{{invalid operands to binary expression}} - (void)(i16 * i64); // expected-error{{invalid operands to binary expression}} - (void)(i16 * u8); // expected-error{{invalid operands to binary expression}} - (void)(i16 * u32); // expected-error{{invalid operands to binary expression}} - (void)(i16 * u64); // expected-error{{invalid operands to binary expression}} - (void)(i16 * f16); // expected-error{{invalid operands to binary expression}} - (void)(i16 * f32); // expected-error{{invalid operands to binary expression}} - (void)(i16 * f64); // expected-error{{invalid operands to binary expression}} - (void)(i16 * 0); // expected-error{{invalid operands to binary expression}} - (void)(i16 * 0l); // expected-error{{invalid operands to binary expression}} - (void)(i16 * 0u); // expected-error{{invalid operands to binary expression}} - (void)(i16 * 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i16 * 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i16 * 0.); // expected-error{{invalid operands to binary expression}} + (void)(i16 * i8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i16 * i32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i16 * i64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i16 * u8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i16 * u32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i16 * u64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i16 * f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svint16_t' (aka '__SVInt16_t') as implicit conversion would cause truncation}} + (void)(i16 * f32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i16 * f64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(u16 * b); // expected-error{{invalid operands to binary expression}} - (void)(u16 * i8); // expected-error{{invalid operands to binary expression}} - (void)(u16 * i32); // expected-error{{invalid operands to binary expression}} - (void)(u16 * i64); // expected-error{{invalid operands to binary expression}} - (void)(u16 * u8); // expected-error{{invalid operands to binary expression}} - (void)(u16 * u32); // expected-error{{invalid operands to binary expression}} - (void)(u16 * u64); // expected-error{{invalid operands to binary expression}} - (void)(u16 * f16); // expected-error{{invalid operands to binary expression}} - (void)(u16 * f32); // expected-error{{invalid operands to binary expression}} - (void)(u16 * f64); // expected-error{{invalid operands to binary expression}} - (void)(u16 * 0); // expected-error{{invalid operands to binary expression}} - (void)(u16 * 0l); // expected-error{{invalid operands to binary expression}} - (void)(u16 * 0u); // expected-error{{invalid operands to binary expression}} - (void)(u16 * 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u16 * 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u16 * 0.); // expected-error{{invalid operands to binary expression}} + (void)(u16 * i8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u16 * i32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u16 * i64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u16 * u8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u16 * u32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u16 * u64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u16 * f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svuint16_t' (aka '__SVUint16_t') as implicit conversion would cause truncation}} + (void)(u16 * f32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u16 * f64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(i32 * b); // expected-error{{invalid operands to binary expression}} - (void)(i32 * i8); // expected-error{{invalid operands to binary expression}} - (void)(i32 * i16); // expected-error{{invalid operands to binary expression}} - (void)(i32 * i64); // expected-error{{invalid operands to binary expression}} - (void)(i32 * u8); // expected-error{{invalid operands to binary expression}} - (void)(i32 * u16); // expected-error{{invalid operands to binary expression}} - (void)(i32 * u64); // expected-error{{invalid operands to binary expression}} - (void)(i32 * f16); // expected-error{{invalid operands to binary expression}} - (void)(i32 * f32); // expected-error{{invalid operands to binary expression}} - (void)(i32 * f64); // expected-error{{invalid operands to binary expression}} - (void)(i32 * 0l); // expected-error{{invalid operands to binary expression}} - (void)(i32 * 0u); // expected-error{{invalid operands to binary expression}} - (void)(i32 * 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i32 * 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i32 * 0.); // expected-error{{invalid operands to binary expression}} + (void)(i32 * i8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i32 * i16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i32 * i64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i32 * u8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i32 * u16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i32 * u64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i32 * f16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i32 * f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svint32_t' (aka '__SVInt32_t') as implicit conversion would cause truncation}} + (void)(i32 * f64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(u32 * b); // expected-error{{invalid operands to binary expression}} - (void)(u32 * i8); // expected-error{{invalid operands to binary expression}} - (void)(u32 * i16); // expected-error{{invalid operands to binary expression}} - (void)(u32 * i64); // expected-error{{invalid operands to binary expression}} - (void)(u32 * u8); // expected-error{{invalid operands to binary expression}} - (void)(u32 * u16); // expected-error{{invalid operands to binary expression}} - (void)(u32 * u64); // expected-error{{invalid operands to binary expression}} - (void)(u32 * f16); // expected-error{{invalid operands to binary expression}} - (void)(u32 * f32); // expected-error{{invalid operands to binary expression}} - (void)(u32 * f64); // expected-error{{invalid operands to binary expression}} - (void)(u32 * 0); // expected-error{{invalid operands to binary expression}} - (void)(u32 * 0l); // expected-error{{invalid operands to binary expression}} - (void)(u32 * 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u32 * 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u32 * 0.); // expected-error{{invalid operands to binary expression}} + (void)(u32 * i8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u32 * i16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u32 * i64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u32 * u8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u32 * u16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u32 * u64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u32 * f16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u32 * f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svuint32_t' (aka '__SVUint32_t') as implicit conversion would cause truncation}} + (void)(u32 * f64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(i64 * b); // expected-error{{invalid operands to binary expression}} - (void)(i64 * i8); // expected-error{{invalid operands to binary expression}} - (void)(i64 * i16); // expected-error{{invalid operands to binary expression}} - (void)(i64 * i32); // expected-error{{invalid operands to binary expression}} - (void)(i64 * u8); // expected-error{{invalid operands to binary expression}} - (void)(i64 * u16); // expected-error{{invalid operands to binary expression}} - (void)(i64 * u32); // expected-error{{invalid operands to binary expression}} - (void)(i64 * f16); // expected-error{{invalid operands to binary expression}} - (void)(i64 * f32); // expected-error{{invalid operands to binary expression}} - (void)(i64 * f64); // expected-error{{invalid operands to binary expression}} - (void)(i64 * 0); // expected-error{{invalid operands to binary expression}} - (void)(i64 * 0u); // expected-error{{invalid operands to binary expression}} - (void)(i64 * 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i64 * 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i64 * 0.); // expected-error{{invalid operands to binary expression}} + (void)(i64 * i8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i64 * i16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i64 * i32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i64 * u8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i64 * u16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i64 * u32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i64 * f16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i64 * f32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i64 * f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svint64_t' (aka '__SVInt64_t') as implicit conversion would cause truncation}} (void)(u64 * b); // expected-error{{invalid operands to binary expression}} - (void)(u64 * i8); // expected-error{{invalid operands to binary expression}} - (void)(u64 * i16); // expected-error{{invalid operands to binary expression}} - (void)(u64 * i32); // expected-error{{invalid operands to binary expression}} - (void)(u64 * u8); // expected-error{{invalid operands to binary expression}} - (void)(u64 * u16); // expected-error{{invalid operands to binary expression}} - (void)(u64 * u32); // expected-error{{invalid operands to binary expression}} - (void)(u64 * f16); // expected-error{{invalid operands to binary expression}} - (void)(u64 * f32); // expected-error{{invalid operands to binary expression}} - (void)(u64 * f64); // expected-error{{invalid operands to binary expression}} - (void)(u64 * 0); // expected-error{{invalid operands to binary expression}} - (void)(u64 * 0l); // expected-error{{invalid operands to binary expression}} - (void)(u64 * 0u); // expected-error{{invalid operands to binary expression}} - (void)(u64 * 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u64 * 0.); // expected-error{{invalid operands to binary expression}} + (void)(u64 * i8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u64 * i16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u64 * i32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u64 * u8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u64 * u16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u64 * u32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u64 * f16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u64 * f32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u64 * f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svuint64_t' (aka '__SVUint64_t') as implicit conversion would cause truncation}} (void)(f16 * b); // expected-error{{invalid operands to binary expression}} - (void)(f16 * i8); // expected-error{{invalid operands to binary expression}} - (void)(f16 * i16); // expected-error{{invalid operands to binary expression}} - (void)(f16 * i32); // expected-error{{invalid operands to binary expression}} - (void)(f16 * i64); // expected-error{{invalid operands to binary expression}} - (void)(f16 * u8); // expected-error{{invalid operands to binary expression}} - (void)(f16 * u32); // expected-error{{invalid operands to binary expression}} - (void)(f16 * u64); // expected-error{{invalid operands to binary expression}} - (void)(f16 * f32); // expected-error{{invalid operands to binary expression}} - (void)(f16 * f64); // expected-error{{invalid operands to binary expression}} - (void)(f16 * 0); // expected-error{{invalid operands to binary expression}} - (void)(f16 * 0l); // expected-error{{invalid operands to binary expression}} - (void)(f16 * 0u); // expected-error{{invalid operands to binary expression}} - (void)(f16 * 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f16 * 0.f); // expected-error{{invalid operands to binary expression}} - (void)(f16 * 0.); // expected-error{{invalid operands to binary expression}} + (void)(f16 * i8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f16 * i16); // expected-error{{cannot convert between vector type 'svint16_t' (aka '__SVInt16_t') and vector type 'svfloat16_t' (aka '__SVFloat16_t') as implicit conversion would cause truncation}} + (void)(f16 * i32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f16 * i64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f16 * u8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f16 * u32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f16 * u64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f16 * f32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(f16 * f64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(f32 * b); // expected-error{{invalid operands to binary expression}} - (void)(f32 * i8); // expected-error{{invalid operands to binary expression}} - (void)(f32 * i16); // expected-error{{invalid operands to binary expression}} - (void)(f32 * i32); // expected-error{{invalid operands to binary expression}} - (void)(f32 * i64); // expected-error{{invalid operands to binary expression}} - (void)(f32 * u8); // expected-error{{invalid operands to binary expression}} - (void)(f32 * u16); // expected-error{{invalid operands to binary expression}} - (void)(f32 * u64); // expected-error{{invalid operands to binary expression}} - (void)(f32 * f16); // expected-error{{invalid operands to binary expression}} - (void)(f32 * f64); // expected-error{{invalid operands to binary expression}} - (void)(f32 * 0); // expected-error{{invalid operands to binary expression}} - (void)(f32 * 0l); // expected-error{{invalid operands to binary expression}} - (void)(f32 * 0u); // expected-error{{invalid operands to binary expression}} - (void)(f32 * 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f32 * 0.); // expected-error{{invalid operands to binary expression}} + (void)(f32 * i8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f32 * i16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f32 * i32); // expected-error{{cannot convert between vector type 'svint32_t' (aka '__SVInt32_t') and vector type 'svfloat32_t' (aka '__SVFloat32_t') as implicit conversion would cause truncation}} + (void)(f32 * i64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f32 * u8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f32 * u16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f32 * u64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f32 * f16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f32 * f64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(f64 * b); // expected-error{{invalid operands to binary expression}} - (void)(f64 * i8); // expected-error{{invalid operands to binary expression}} - (void)(f64 * i16); // expected-error{{invalid operands to binary expression}} - (void)(f64 * i32); // expected-error{{invalid operands to binary expression}} - (void)(f64 * i64); // expected-error{{invalid operands to binary expression}} - (void)(f64 * u8); // expected-error{{invalid operands to binary expression}} - (void)(f64 * u16); // expected-error{{invalid operands to binary expression}} - (void)(f64 * u32); // expected-error{{invalid operands to binary expression}} - (void)(f64 * f16); // expected-error{{invalid operands to binary expression}} - (void)(f64 * f32); // expected-error{{invalid operands to binary expression}} - (void)(f64 * 0); // expected-error{{invalid operands to binary expression}} - (void)(f64 * 0l); // expected-error{{invalid operands to binary expression}} - (void)(f64 * 0u); // expected-error{{invalid operands to binary expression}} - (void)(f64 * 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f64 * 0.f); // expected-error{{invalid operands to binary expression}} + (void)(f64 * i8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f64 * i16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f64 * i32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f64 * i64); // expected-error{{cannot convert between vector type 'svint64_t' (aka '__SVInt64_t') and vector type 'svfloat64_t' (aka '__SVFloat64_t') as implicit conversion would cause truncation}} + (void)(f64 * u8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f64 * u16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f64 * u32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f64 * f16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f64 * f32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + + (void)(s * i8); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s * i16); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s * i32); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s * i64); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s * u16); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s * u32); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s * u64); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s * f16); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s * f32); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s * f64); // expected-error{{cannot convert between vector and non-scalar values}} } void div(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, - svbool_t b) { + svbool_t b, struct S s) { (void)(b / b); // expected-error{{invalid operands to binary expression}} (void)(i8 / b); // expected-error{{invalid operands to binary expression}} - (void)(i8 / i16); // expected-error{{invalid operands to binary expression}} - (void)(i8 / i32); // expected-error{{invalid operands to binary expression}} - (void)(i8 / i64); // expected-error{{invalid operands to binary expression}} - (void)(i8 / u16); // expected-error{{invalid operands to binary expression}} - (void)(i8 / u32); // expected-error{{invalid operands to binary expression}} - (void)(i8 / u64); // expected-error{{invalid operands to binary expression}} - (void)(i8 / f16); // expected-error{{invalid operands to binary expression}} - (void)(i8 / f32); // expected-error{{invalid operands to binary expression}} - (void)(i8 / f64); // expected-error{{invalid operands to binary expression}} - (void)(i8 / 0); // expected-error{{invalid operands to binary expression}} - (void)(i8 / 0l); // expected-error{{invalid operands to binary expression}} - (void)(i8 / 0u); // expected-error{{invalid operands to binary expression}} - (void)(i8 / 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i8 / 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i8 / 0.); // expected-error{{invalid operands to binary expression}} + (void)(i8 / i16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i8 / i32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i8 / i64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i8 / u16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i8 / u32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i8 / u64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i8 / f16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i8 / f32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i8 / f64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(u8 / b); // expected-error{{invalid operands to binary expression}} - (void)(u8 / i16); // expected-error{{invalid operands to binary expression}} - (void)(u8 / i32); // expected-error{{invalid operands to binary expression}} - (void)(u8 / i64); // expected-error{{invalid operands to binary expression}} - (void)(u8 / u16); // expected-error{{invalid operands to binary expression}} - (void)(u8 / u32); // expected-error{{invalid operands to binary expression}} - (void)(u8 / u64); // expected-error{{invalid operands to binary expression}} - (void)(u8 / f16); // expected-error{{invalid operands to binary expression}} - (void)(u8 / f32); // expected-error{{invalid operands to binary expression}} - (void)(u8 / f64); // expected-error{{invalid operands to binary expression}} - (void)(u8 / 0); // expected-error{{invalid operands to binary expression}} - (void)(u8 / 0l); // expected-error{{invalid operands to binary expression}} - (void)(u8 / 0u); // expected-error{{invalid operands to binary expression}} - (void)(u8 / 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u8 / 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u8 / 0.); // expected-error{{invalid operands to binary expression}} + (void)(u8 / i16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u8 / i32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u8 / i64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u8 / u16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u8 / u32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u8 / u64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u8 / f16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u8 / f32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u8 / f64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(i16 / b); // expected-error{{invalid operands to binary expression}} - (void)(i16 / i8); // expected-error{{invalid operands to binary expression}} - (void)(i16 / i32); // expected-error{{invalid operands to binary expression}} - (void)(i16 / i64); // expected-error{{invalid operands to binary expression}} - (void)(i16 / u8); // expected-error{{invalid operands to binary expression}} - (void)(i16 / u32); // expected-error{{invalid operands to binary expression}} - (void)(i16 / u64); // expected-error{{invalid operands to binary expression}} - (void)(i16 / f16); // expected-error{{invalid operands to binary expression}} - (void)(i16 / f32); // expected-error{{invalid operands to binary expression}} - (void)(i16 / f64); // expected-error{{invalid operands to binary expression}} - (void)(i16 / 0); // expected-error{{invalid operands to binary expression}} - (void)(i16 / 0l); // expected-error{{invalid operands to binary expression}} - (void)(i16 / 0u); // expected-error{{invalid operands to binary expression}} - (void)(i16 / 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i16 / 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i16 / 0.); // expected-error{{invalid operands to binary expression}} + (void)(i16 / i8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i16 / i32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i16 / i64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i16 / u8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i16 / u32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i16 / u64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i16 / f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svint16_t' (aka '__SVInt16_t') as implicit conversion would cause truncation}} + (void)(i16 / f32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i16 / f64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(u16 / b); // expected-error{{invalid operands to binary expression}} - (void)(u16 / i8); // expected-error{{invalid operands to binary expression}} - (void)(u16 / i32); // expected-error{{invalid operands to binary expression}} - (void)(u16 / i64); // expected-error{{invalid operands to binary expression}} - (void)(u16 / u8); // expected-error{{invalid operands to binary expression}} - (void)(u16 / u32); // expected-error{{invalid operands to binary expression}} - (void)(u16 / u64); // expected-error{{invalid operands to binary expression}} - (void)(u16 / f16); // expected-error{{invalid operands to binary expression}} - (void)(u16 / f32); // expected-error{{invalid operands to binary expression}} - (void)(u16 / f64); // expected-error{{invalid operands to binary expression}} - (void)(u16 / 0); // expected-error{{invalid operands to binary expression}} - (void)(u16 / 0l); // expected-error{{invalid operands to binary expression}} - (void)(u16 / 0u); // expected-error{{invalid operands to binary expression}} - (void)(u16 / 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u16 / 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u16 / 0.); // expected-error{{invalid operands to binary expression}} + (void)(u16 / i8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u16 / i32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u16 / i64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u16 / u8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u16 / u32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u16 / u64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u16 / f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svuint16_t' (aka '__SVUint16_t') as implicit conversion would cause truncation}} + (void)(u16 / f32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u16 / f64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(i32 / b); // expected-error{{invalid operands to binary expression}} - (void)(i32 / i8); // expected-error{{invalid operands to binary expression}} - (void)(i32 / i16); // expected-error{{invalid operands to binary expression}} - (void)(i32 / i64); // expected-error{{invalid operands to binary expression}} - (void)(i32 / u8); // expected-error{{invalid operands to binary expression}} - (void)(i32 / u16); // expected-error{{invalid operands to binary expression}} - (void)(i32 / u64); // expected-error{{invalid operands to binary expression}} - (void)(i32 / f16); // expected-error{{invalid operands to binary expression}} - (void)(i32 / f32); // expected-error{{invalid operands to binary expression}} - (void)(i32 / f64); // expected-error{{invalid operands to binary expression}} - (void)(i32 / 0l); // expected-error{{invalid operands to binary expression}} - (void)(i32 / 0u); // expected-error{{invalid operands to binary expression}} - (void)(i32 / 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i32 / 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i32 / 0.); // expected-error{{invalid operands to binary expression}} + (void)(i32 / i8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i32 / i16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i32 / i64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i32 / u8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i32 / u16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i32 / u64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i32 / f16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i32 / f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svint32_t' (aka '__SVInt32_t') as implicit conversion would cause truncation}} + (void)(i32 / f64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(u32 / b); // expected-error{{invalid operands to binary expression}} - (void)(u32 / i8); // expected-error{{invalid operands to binary expression}} - (void)(u32 / i16); // expected-error{{invalid operands to binary expression}} - (void)(u32 / i64); // expected-error{{invalid operands to binary expression}} - (void)(u32 / u8); // expected-error{{invalid operands to binary expression}} - (void)(u32 / u16); // expected-error{{invalid operands to binary expression}} - (void)(u32 / u64); // expected-error{{invalid operands to binary expression}} - (void)(u32 / f16); // expected-error{{invalid operands to binary expression}} - (void)(u32 / f32); // expected-error{{invalid operands to binary expression}} - (void)(u32 / f64); // expected-error{{invalid operands to binary expression}} - (void)(u32 / 0); // expected-error{{invalid operands to binary expression}} - (void)(u32 / 0l); // expected-error{{invalid operands to binary expression}} - (void)(u32 / 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u32 / 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u32 / 0.); // expected-error{{invalid operands to binary expression}} + (void)(u32 / i8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u32 / i16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u32 / i64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u32 / u8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u32 / u16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u32 / u64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u32 / f16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u32 / f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svuint32_t' (aka '__SVUint32_t') as implicit conversion would cause truncation}} + (void)(u32 / f64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(i64 / b); // expected-error{{invalid operands to binary expression}} - (void)(i64 / i8); // expected-error{{invalid operands to binary expression}} - (void)(i64 / i16); // expected-error{{invalid operands to binary expression}} - (void)(i64 / i32); // expected-error{{invalid operands to binary expression}} - (void)(i64 / u8); // expected-error{{invalid operands to binary expression}} - (void)(i64 / u16); // expected-error{{invalid operands to binary expression}} - (void)(i64 / u32); // expected-error{{invalid operands to binary expression}} - (void)(i64 / f16); // expected-error{{invalid operands to binary expression}} - (void)(i64 / f32); // expected-error{{invalid operands to binary expression}} - (void)(i64 / f64); // expected-error{{invalid operands to binary expression}} - (void)(i64 / 0); // expected-error{{invalid operands to binary expression}} - (void)(i64 / 0u); // expected-error{{invalid operands to binary expression}} - (void)(i64 / 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i64 / 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i64 / 0.); // expected-error{{invalid operands to binary expression}} + (void)(i64 / i8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i64 / i16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i64 / i32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i64 / u8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i64 / u16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i64 / u32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i64 / f16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i64 / f32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i64 / f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svint64_t' (aka '__SVInt64_t') as implicit conversion would cause truncation}} (void)(u64 / b); // expected-error{{invalid operands to binary expression}} - (void)(u64 / i8); // expected-error{{invalid operands to binary expression}} - (void)(u64 / i16); // expected-error{{invalid operands to binary expression}} - (void)(u64 / i32); // expected-error{{invalid operands to binary expression}} - (void)(u64 / u8); // expected-error{{invalid operands to binary expression}} - (void)(u64 / u16); // expected-error{{invalid operands to binary expression}} - (void)(u64 / u32); // expected-error{{invalid operands to binary expression}} - (void)(u64 / f16); // expected-error{{invalid operands to binary expression}} - (void)(u64 / f32); // expected-error{{invalid operands to binary expression}} - (void)(u64 / f64); // expected-error{{invalid operands to binary expression}} - (void)(u64 / 0); // expected-error{{invalid operands to binary expression}} - (void)(u64 / 0l); // expected-error{{invalid operands to binary expression}} - (void)(u64 / 0u); // expected-error{{invalid operands to binary expression}} - (void)(u64 / 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u64 / 0.); // expected-error{{invalid operands to binary expression}} + (void)(u64 / i8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u64 / i16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u64 / i32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u64 / u8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u64 / u16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u64 / u32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u64 / f16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u64 / f32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u64 / f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svuint64_t' (aka '__SVUint64_t') as implicit conversion would cause truncation}} (void)(f16 / b); // expected-error{{invalid operands to binary expression}} - (void)(f16 / i8); // expected-error{{invalid operands to binary expression}} - (void)(f16 / i16); // expected-error{{invalid operands to binary expression}} - (void)(f16 / i32); // expected-error{{invalid operands to binary expression}} - (void)(f16 / i64); // expected-error{{invalid operands to binary expression}} - (void)(f16 / u8); // expected-error{{invalid operands to binary expression}} - (void)(f16 / u32); // expected-error{{invalid operands to binary expression}} - (void)(f16 / u64); // expected-error{{invalid operands to binary expression}} - (void)(f16 / f32); // expected-error{{invalid operands to binary expression}} - (void)(f16 / f64); // expected-error{{invalid operands to binary expression}} - (void)(f16 / 0); // expected-error{{invalid operands to binary expression}} - (void)(f16 / 0l); // expected-error{{invalid operands to binary expression}} - (void)(f16 / 0u); // expected-error{{invalid operands to binary expression}} - (void)(f16 / 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f16 / 0.f); // expected-error{{invalid operands to binary expression}} - (void)(f16 / 0.); // expected-error{{invalid operands to binary expression}} + (void)(f16 / i8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f16 / i16); // expected-error{{cannot convert between vector type 'svint16_t' (aka '__SVInt16_t') and vector type 'svfloat16_t' (aka '__SVFloat16_t') as implicit conversion would cause truncation}} + (void)(f16 / i32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f16 / i64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f16 / u8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f16 / u32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f16 / u64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f16 / f32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(f16 / f64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(f32 / b); // expected-error{{invalid operands to binary expression}} - (void)(f32 / i8); // expected-error{{invalid operands to binary expression}} - (void)(f32 / i16); // expected-error{{invalid operands to binary expression}} - (void)(f32 / i32); // expected-error{{invalid operands to binary expression}} - (void)(f32 / i64); // expected-error{{invalid operands to binary expression}} - (void)(f32 / u8); // expected-error{{invalid operands to binary expression}} - (void)(f32 / u16); // expected-error{{invalid operands to binary expression}} - (void)(f32 / u64); // expected-error{{invalid operands to binary expression}} - (void)(f32 / f16); // expected-error{{invalid operands to binary expression}} - (void)(f32 / f64); // expected-error{{invalid operands to binary expression}} - (void)(f32 / 0); // expected-error{{invalid operands to binary expression}} - (void)(f32 / 0l); // expected-error{{invalid operands to binary expression}} - (void)(f32 / 0u); // expected-error{{invalid operands to binary expression}} - (void)(f32 / 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f32 / 0.); // expected-error{{invalid operands to binary expression}} + (void)(f32 / i8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f32 / i16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f32 / i32); // expected-error{{cannot convert between vector type 'svint32_t' (aka '__SVInt32_t') and vector type 'svfloat32_t' (aka '__SVFloat32_t') as implicit conversion would cause truncation}} + (void)(f32 / i64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f32 / u8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f32 / u16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f32 / u64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f32 / f16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f32 / f64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} (void)(f64 / b); // expected-error{{invalid operands to binary expression}} - (void)(f64 / i8); // expected-error{{invalid operands to binary expression}} - (void)(f64 / i16); // expected-error{{invalid operands to binary expression}} - (void)(f64 / i32); // expected-error{{invalid operands to binary expression}} - (void)(f64 / i64); // expected-error{{invalid operands to binary expression}} - (void)(f64 / u8); // expected-error{{invalid operands to binary expression}} - (void)(f64 / u16); // expected-error{{invalid operands to binary expression}} - (void)(f64 / u32); // expected-error{{invalid operands to binary expression}} - (void)(f64 / f16); // expected-error{{invalid operands to binary expression}} - (void)(f64 / f32); // expected-error{{invalid operands to binary expression}} - (void)(f64 / 0); // expected-error{{invalid operands to binary expression}} - (void)(f64 / 0l); // expected-error{{invalid operands to binary expression}} - (void)(f64 / 0u); // expected-error{{invalid operands to binary expression}} - (void)(f64 / 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f64 / 0.f); // expected-error{{invalid operands to binary expression}} + (void)(f64 / i8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f64 / i16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f64 / i32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f64 / i64); // expected-error{{cannot convert between vector type 'svint64_t' (aka '__SVInt64_t') and vector type 'svfloat64_t' (aka '__SVFloat64_t') as implicit conversion would cause truncation}} + (void)(f64 / u8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f64 / u16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f64 / u32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f64 / f16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f64 / f32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + + (void)(s / i8); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s / i16); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s / i32); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s / i64); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s / u16); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s / u32); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s / u64); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s / f16); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s / f32); // expected-error{{cannot convert between vector and non-scalar values}} + (void)(s / f64); // expected-error{{cannot convert between vector and non-scalar values}} } void mod(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, - svbool_t b) { + svbool_t b, struct S s) { (void)(b % b); // expected-error{{invalid operands to binary expression}} (void)(i8 % b); // expected-error{{invalid operands to binary expression}} - (void)(i8 % i16); // expected-error{{invalid operands to binary expression}} - (void)(i8 % i32); // expected-error{{invalid operands to binary expression}} - (void)(i8 % i64); // expected-error{{invalid operands to binary expression}} - (void)(i8 % u16); // expected-error{{invalid operands to binary expression}} - (void)(i8 % u32); // expected-error{{invalid operands to binary expression}} - (void)(i8 % u64); // expected-error{{invalid operands to binary expression}} + (void)(i8 % i16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i8 % i32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i8 % i64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i8 % u16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i8 % u32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i8 % u64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(i8 % f16); // expected-error{{invalid operands to binary expression}} (void)(i8 % f32); // expected-error{{invalid operands to binary expression}} (void)(i8 % f64); // expected-error{{invalid operands to binary expression}} - (void)(i8 % 0); // expected-error{{invalid operands to binary expression}} - (void)(i8 % 0l); // expected-error{{invalid operands to binary expression}} - (void)(i8 % 0u); // expected-error{{invalid operands to binary expression}} - (void)(i8 % 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i8 % 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i8 % 0.); // expected-error{{invalid operands to binary expression}} (void)(u8 % b); // expected-error{{invalid operands to binary expression}} - (void)(u8 % i16); // expected-error{{invalid operands to binary expression}} - (void)(u8 % i32); // expected-error{{invalid operands to binary expression}} - (void)(u8 % i64); // expected-error{{invalid operands to binary expression}} - (void)(u8 % u16); // expected-error{{invalid operands to binary expression}} - (void)(u8 % u32); // expected-error{{invalid operands to binary expression}} - (void)(u8 % u64); // expected-error{{invalid operands to binary expression}} + (void)(u8 % i16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u8 % i32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u8 % i64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u8 % u16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u8 % u32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u8 % u64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(u8 % f16); // expected-error{{invalid operands to binary expression}} (void)(u8 % f32); // expected-error{{invalid operands to binary expression}} (void)(u8 % f64); // expected-error{{invalid operands to binary expression}} - (void)(u8 % 0); // expected-error{{invalid operands to binary expression}} - (void)(u8 % 0l); // expected-error{{invalid operands to binary expression}} - (void)(u8 % 0u); // expected-error{{invalid operands to binary expression}} - (void)(u8 % 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u8 % 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u8 % 0.); // expected-error{{invalid operands to binary expression}} (void)(i16 % b); // expected-error{{invalid operands to binary expression}} - (void)(i16 % i8); // expected-error{{invalid operands to binary expression}} - (void)(i16 % i32); // expected-error{{invalid operands to binary expression}} - (void)(i16 % i64); // expected-error{{invalid operands to binary expression}} - (void)(i16 % u8); // expected-error{{invalid operands to binary expression}} - (void)(i16 % u32); // expected-error{{invalid operands to binary expression}} - (void)(i16 % u64); // expected-error{{invalid operands to binary expression}} + (void)(i16 % i8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i16 % i32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i16 % i64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i16 % u8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i16 % u32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i16 % u64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(i16 % f16); // expected-error{{invalid operands to binary expression}} (void)(i16 % f32); // expected-error{{invalid operands to binary expression}} (void)(i16 % f64); // expected-error{{invalid operands to binary expression}} - (void)(i16 % 0); // expected-error{{invalid operands to binary expression}} - (void)(i16 % 0l); // expected-error{{invalid operands to binary expression}} - (void)(i16 % 0u); // expected-error{{invalid operands to binary expression}} - (void)(i16 % 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i16 % 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i16 % 0.); // expected-error{{invalid operands to binary expression}} (void)(u16 % b); // expected-error{{invalid operands to binary expression}} - (void)(u16 % i8); // expected-error{{invalid operands to binary expression}} - (void)(u16 % i32); // expected-error{{invalid operands to binary expression}} - (void)(u16 % i64); // expected-error{{invalid operands to binary expression}} - (void)(u16 % u8); // expected-error{{invalid operands to binary expression}} - (void)(u16 % u32); // expected-error{{invalid operands to binary expression}} - (void)(u16 % u64); // expected-error{{invalid operands to binary expression}} + (void)(u16 % i8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u16 % i32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u16 % i64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u16 % u8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u16 % u32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u16 % u64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(u16 % f16); // expected-error{{invalid operands to binary expression}} (void)(u16 % f32); // expected-error{{invalid operands to binary expression}} (void)(u16 % f64); // expected-error{{invalid operands to binary expression}} - (void)(u16 % 0); // expected-error{{invalid operands to binary expression}} - (void)(u16 % 0l); // expected-error{{invalid operands to binary expression}} - (void)(u16 % 0u); // expected-error{{invalid operands to binary expression}} - (void)(u16 % 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u16 % 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u16 % 0.); // expected-error{{invalid operands to binary expression}} (void)(i32 % b); // expected-error{{invalid operands to binary expression}} - (void)(i32 % i8); // expected-error{{invalid operands to binary expression}} - (void)(i32 % i16); // expected-error{{invalid operands to binary expression}} - (void)(i32 % i64); // expected-error{{invalid operands to binary expression}} - (void)(i32 % u8); // expected-error{{invalid operands to binary expression}} - (void)(i32 % u16); // expected-error{{invalid operands to binary expression}} - (void)(i32 % u64); // expected-error{{invalid operands to binary expression}} + (void)(i32 % i8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i32 % i16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i32 % i64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i32 % u8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i32 % u16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i32 % u64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(i32 % f16); // expected-error{{invalid operands to binary expression}} (void)(i32 % f32); // expected-error{{invalid operands to binary expression}} (void)(i32 % f64); // expected-error{{invalid operands to binary expression}} - (void)(i32 % 0l); // expected-error{{invalid operands to binary expression}} - (void)(i32 % 0u); // expected-error{{invalid operands to binary expression}} - (void)(i32 % 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i32 % 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i32 % 0.); // expected-error{{invalid operands to binary expression}} (void)(u32 % b); // expected-error{{invalid operands to binary expression}} - (void)(u32 % i8); // expected-error{{invalid operands to binary expression}} - (void)(u32 % i16); // expected-error{{invalid operands to binary expression}} - (void)(u32 % i64); // expected-error{{invalid operands to binary expression}} - (void)(u32 % u8); // expected-error{{invalid operands to binary expression}} - (void)(u32 % u16); // expected-error{{invalid operands to binary expression}} - (void)(u32 % u64); // expected-error{{invalid operands to binary expression}} + (void)(u32 % i8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u32 % i16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u32 % i64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u32 % u8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u32 % u16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u32 % u64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(u32 % f16); // expected-error{{invalid operands to binary expression}} (void)(u32 % f32); // expected-error{{invalid operands to binary expression}} (void)(u32 % f64); // expected-error{{invalid operands to binary expression}} - (void)(u32 % 0); // expected-error{{invalid operands to binary expression}} - (void)(u32 % 0l); // expected-error{{invalid operands to binary expression}} - (void)(u32 % 0ul); // expected-error{{invalid operands to binary expression}} - (void)(u32 % 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u32 % 0.); // expected-error{{invalid operands to binary expression}} (void)(i64 % b); // expected-error{{invalid operands to binary expression}} - (void)(i64 % i8); // expected-error{{invalid operands to binary expression}} - (void)(i64 % i16); // expected-error{{invalid operands to binary expression}} - (void)(i64 % i32); // expected-error{{invalid operands to binary expression}} - (void)(i64 % u8); // expected-error{{invalid operands to binary expression}} - (void)(i64 % u16); // expected-error{{invalid operands to binary expression}} - (void)(i64 % u32); // expected-error{{invalid operands to binary expression}} + (void)(i64 % i8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i64 % i16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i64 % i32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i64 % u8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i64 % u16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i64 % u32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} (void)(i64 % f16); // expected-error{{invalid operands to binary expression}} (void)(i64 % f32); // expected-error{{invalid operands to binary expression}} (void)(i64 % f64); // expected-error{{invalid operands to binary expression}} - (void)(i64 % 0); // expected-error{{invalid operands to binary expression}} - (void)(i64 % 0u); // expected-error{{invalid operands to binary expression}} - (void)(i64 % 0ul); // expected-error{{invalid operands to binary expression}} - (void)(i64 % 0.f); // expected-error{{invalid operands to binary expression}} - (void)(i64 % 0.); // expected-error{{invalid operands to binary expression}} (void)(u64 % b); // expected-error{{invalid operands to binary expression}} - (void)(u64 % i8); // expected-error{{invalid operands to binary expression}} - (void)(u64 % i16); // expected-error{{invalid operands to binary expression}} - (void)(u64 % i32); // expected-error{{invalid operands to binary expression}} - (void)(u64 % u8); // expected-error{{invalid operands to binary expression}} - (void)(u64 % u16); // expected-error{{invalid operands to binary expression}} - (void)(u64 % u32); // expected-error{{invalid operands to binary expression}} + (void)(u64 % i8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u64 % i16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u64 % i32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u64 % u8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u64 % u16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u64 % u32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} (void)(u64 % f16); // expected-error{{invalid operands to binary expression}} (void)(u64 % f32); // expected-error{{invalid operands to binary expression}} (void)(u64 % f64); // expected-error{{invalid operands to binary expression}} - (void)(u64 % 0); // expected-error{{invalid operands to binary expression}} - (void)(u64 % 0l); // expected-error{{invalid operands to binary expression}} - (void)(u64 % 0u); // expected-error{{invalid operands to binary expression}} - (void)(u64 % 0.f); // expected-error{{invalid operands to binary expression}} - (void)(u64 % 0.); // expected-error{{invalid operands to binary expression}} (void)(f16 % b); // expected-error{{invalid operands to binary expression}} (void)(f16 % i8); // expected-error{{invalid operands to binary expression}} @@ -904,12 +668,6 @@ void mod(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, (void)(f16 % u64); // expected-error{{invalid operands to binary expression}} (void)(f16 % f32); // expected-error{{invalid operands to binary expression}} (void)(f16 % f64); // expected-error{{invalid operands to binary expression}} - (void)(f16 % 0); // expected-error{{invalid operands to binary expression}} - (void)(f16 % 0l); // expected-error{{invalid operands to binary expression}} - (void)(f16 % 0u); // expected-error{{invalid operands to binary expression}} - (void)(f16 % 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f16 % 0.f); // expected-error{{invalid operands to binary expression}} - (void)(f16 % 0.); // expected-error{{invalid operands to binary expression}} (void)(f32 % b); // expected-error{{invalid operands to binary expression}} (void)(f32 % i8); // expected-error{{invalid operands to binary expression}} @@ -921,12 +679,6 @@ void mod(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, (void)(f32 % u64); // expected-error{{invalid operands to binary expression}} (void)(f32 % f16); // expected-error{{invalid operands to binary expression}} (void)(f32 % f64); // expected-error{{invalid operands to binary expression}} - (void)(f32 % 0); // expected-error{{invalid operands to binary expression}} - (void)(f32 % 0l); // expected-error{{invalid operands to binary expression}} - (void)(f32 % 0u); // expected-error{{invalid operands to binary expression}} - (void)(f32 % 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f32 % 0.f); // expected-error{{invalid operands to binary expression}} - (void)(f32 % 0.); // expected-error{{invalid operands to binary expression}} (void)(f64 % b); // expected-error{{invalid operands to binary expression}} (void)(f64 % i8); // expected-error{{invalid operands to binary expression}} @@ -938,10 +690,22 @@ void mod(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, (void)(f64 % u32); // expected-error{{invalid operands to binary expression}} (void)(f64 % f16); // expected-error{{invalid operands to binary expression}} (void)(f64 % f32); // expected-error{{invalid operands to binary expression}} - (void)(f64 % 0); // expected-error{{invalid operands to binary expression}} - (void)(f64 % 0l); // expected-error{{invalid operands to binary expression}} - (void)(f64 % 0u); // expected-error{{invalid operands to binary expression}} - (void)(f64 % 0ul); // expected-error{{invalid operands to binary expression}} - (void)(f64 % 0.f); // expected-error{{invalid operands to binary expression}} - (void)(f64 % 0.); // expected-error{{invalid operands to binary expression}} + + (void)(s % i8); // expected-error{{invalid operands to binary expression}} + (void)(s % i16); // expected-error{{invalid operands to binary expression}} + (void)(s % i32); // expected-error{{invalid operands to binary expression}} + (void)(s % i64); // expected-error{{invalid operands to binary expression}} + (void)(s % u8); // expected-error{{invalid operands to binary expression}} + (void)(s % u16); // expected-error{{invalid operands to binary expression}} + (void)(s % u32); // expected-error{{invalid operands to binary expression}} + (void)(s % f16); // expected-error{{invalid operands to binary expression}} + (void)(s % f32); // expected-error{{invalid operands to binary expression}} +} + +svint8_t svi8(svint8_t a) { + return a + 256; // expected-error{{cannot convert between scalar type 'int' and vector type 'svint8_t' (aka '__SVInt8_t') as implicit conversion would cause truncation}} +} + +svint8_t svi8_128(svint8_t a) { + return a + 128; // expected-warning{{implicit conversion from 'int' to 'svint8_t' (aka '__SVInt8_t') changes value from 128 to -128}} } diff --git a/clang/test/Sema/aarch64-sve-vector-bitwise-ops.c b/clang/test/Sema/aarch64-sve-vector-bitwise-ops.c index d1afd116a7758..e2d9045c3a0d8 100644 --- a/clang/test/Sema/aarch64-sve-vector-bitwise-ops.c +++ b/clang/test/Sema/aarch64-sve-vector-bitwise-ops.c @@ -8,90 +8,90 @@ void and (svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, svbool_t b) { - (void)(i8 & b); // expected-error{{invalid operands to binary expression}} - (void)(i8 & i16); // expected-error{{invalid operands to binary expression}} - (void)(i8 & i32); // expected-error{{invalid operands to binary expression}} - (void)(i8 & i64); // expected-error{{invalid operands to binary expression}} - (void)(i8 & u16); // expected-error{{invalid operands to binary expression}} - (void)(i8 & u32); // expected-error{{invalid operands to binary expression}} - (void)(i8 & u64); // expected-error{{invalid operands to binary expression}} + (void)(i8 & b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svint8_t' (aka '__SVInt8_t') as implicit conversion would cause truncation}} + (void)(i8 & i16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i8 & i32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i8 & i64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i8 & u16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i8 & u32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i8 & u64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(i8 & f16); // expected-error{{invalid operands to binary expression}} (void)(i8 & f32); // expected-error{{invalid operands to binary expression}} (void)(i8 & f64); // expected-error{{invalid operands to binary expression}} - (void)(u8 & b); // expected-error{{invalid operands to binary expression}} - (void)(u8 & i16); // expected-error{{invalid operands to binary expression}} - (void)(u8 & i32); // expected-error{{invalid operands to binary expression}} - (void)(u8 & i64); // expected-error{{invalid operands to binary expression}} - (void)(u8 & u16); // expected-error{{invalid operands to binary expression}} - (void)(u8 & u32); // expected-error{{invalid operands to binary expression}} - (void)(u8 & u64); // expected-error{{invalid operands to binary expression}} + (void)(u8 & b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svuint8_t' (aka '__SVUint8_t') as implicit conversion would cause truncation}} + (void)(u8 & i16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u8 & i32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u8 & i64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u8 & u16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u8 & u32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u8 & u64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(u8 & f16); // expected-error{{invalid operands to binary expression}} (void)(u8 & f32); // expected-error{{invalid operands to binary expression}} (void)(u8 & f64); // expected-error{{invalid operands to binary expression}} - (void)(i16 & b); // expected-error{{invalid operands to binary expression}} - (void)(i16 & i8); // expected-error{{invalid operands to binary expression}} - (void)(i16 & i32); // expected-error{{invalid operands to binary expression}} - (void)(i16 & i64); // expected-error{{invalid operands to binary expression}} - (void)(i16 & u8); // expected-error{{invalid operands to binary expression}} - (void)(i16 & u32); // expected-error{{invalid operands to binary expression}} - (void)(i16 & u64); // expected-error{{invalid operands to binary expression}} + (void)(i16 & b); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i16 & i8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i16 & i32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i16 & i64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i16 & u8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i16 & u32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i16 & u64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(i16 & f16); // expected-error{{invalid operands to binary expression}} (void)(i16 & f32); // expected-error{{invalid operands to binary expression}} (void)(i16 & f64); // expected-error{{invalid operands to binary expression}} - (void)(u16 & b); // expected-error{{invalid operands to binary expression}} - (void)(u16 & i8); // expected-error{{invalid operands to binary expression}} - (void)(u16 & i32); // expected-error{{invalid operands to binary expression}} - (void)(u16 & i64); // expected-error{{invalid operands to binary expression}} - (void)(u16 & u8); // expected-error{{invalid operands to binary expression}} - (void)(u16 & u32); // expected-error{{invalid operands to binary expression}} - (void)(u16 & u64); // expected-error{{invalid operands to binary expression}} + (void)(u16 & b); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u16 & i8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u16 & i32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u16 & i64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u16 & u8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u16 & u32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u16 & u64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(u16 & f16); // expected-error{{invalid operands to binary expression}} (void)(u16 & f32); // expected-error{{invalid operands to binary expression}} (void)(u16 & f64); // expected-error{{invalid operands to binary expression}} - (void)(i32 & b); // expected-error{{invalid operands to binary expression}} - (void)(i32 & i8); // expected-error{{invalid operands to binary expression}} - (void)(i32 & i16); // expected-error{{invalid operands to binary expression}} - (void)(i32 & i64); // expected-error{{invalid operands to binary expression}} - (void)(i32 & u8); // expected-error{{invalid operands to binary expression}} - (void)(i32 & u16); // expected-error{{invalid operands to binary expression}} - (void)(i32 & u64); // expected-error{{invalid operands to binary expression}} + (void)(i32 & b); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i32 & i8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i32 & i16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i32 & i64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i32 & u8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i32 & u16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i32 & u64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(i32 & f16); // expected-error{{invalid operands to binary expression}} (void)(i32 & f32); // expected-error{{invalid operands to binary expression}} (void)(i32 & f64); // expected-error{{invalid operands to binary expression}} - (void)(u32 & b); // expected-error{{invalid operands to binary expression}} - (void)(u32 & i8); // expected-error{{invalid operands to binary expression}} - (void)(u32 & i16); // expected-error{{invalid operands to binary expression}} - (void)(u32 & i64); // expected-error{{invalid operands to binary expression}} - (void)(u32 & u8); // expected-error{{invalid operands to binary expression}} - (void)(u32 & u16); // expected-error{{invalid operands to binary expression}} - (void)(u32 & u64); // expected-error{{invalid operands to binary expression}} + (void)(u32 & b); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u32 & i8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u32 & i16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u32 & i64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u32 & u8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u32 & u16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u32 & u64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(u32 & f16); // expected-error{{invalid operands to binary expression}} (void)(u32 & f32); // expected-error{{invalid operands to binary expression}} (void)(u32 & f64); // expected-error{{invalid operands to binary expression}} - (void)(i64 & b); // expected-error{{invalid operands to binary expression}} - (void)(i64 & i8); // expected-error{{invalid operands to binary expression}} - (void)(i64 & i16); // expected-error{{invalid operands to binary expression}} - (void)(i64 & i32); // expected-error{{invalid operands to binary expression}} - (void)(i64 & u8); // expected-error{{invalid operands to binary expression}} - (void)(i64 & u16); // expected-error{{invalid operands to binary expression}} - (void)(i64 & u32); // expected-error{{invalid operands to binary expression}} + (void)(i64 & b); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i64 & i8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i64 & i16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i64 & i32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i64 & u8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i64 & u16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i64 & u32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} (void)(i64 & f16); // expected-error{{invalid operands to binary expression}} (void)(i64 & f32); // expected-error{{invalid operands to binary expression}} (void)(i64 & f64); // expected-error{{invalid operands to binary expression}} - (void)(u64 & b); // expected-error{{invalid operands to binary expression}} - (void)(u64 & i8); // expected-error{{invalid operands to binary expression}} - (void)(u64 & i16); // expected-error{{invalid operands to binary expression}} - (void)(u64 & i32); // expected-error{{invalid operands to binary expression}} - (void)(u64 & u8); // expected-error{{invalid operands to binary expression}} - (void)(u64 & u16); // expected-error{{invalid operands to binary expression}} - (void)(u64 & u32); // expected-error{{invalid operands to binary expression}} + (void)(u64 & b); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u64 & i8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u64 & i16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u64 & i32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u64 & u8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u64 & u16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u64 & u32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} (void)(u64 & f16); // expected-error{{invalid operands to binary expression}} (void)(u64 & f32); // expected-error{{invalid operands to binary expression}} (void)(u64 & f64); // expected-error{{invalid operands to binary expression}} @@ -136,90 +136,90 @@ void or (svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, svbool_t b) { - (void)(i8 | b); // expected-error{{invalid operands to binary expression}} - (void)(i8 | i16); // expected-error{{invalid operands to binary expression}} - (void)(i8 | i32); // expected-error{{invalid operands to binary expression}} - (void)(i8 | i64); // expected-error{{invalid operands to binary expression}} - (void)(i8 | u16); // expected-error{{invalid operands to binary expression}} - (void)(i8 | u32); // expected-error{{invalid operands to binary expression}} - (void)(i8 | u64); // expected-error{{invalid operands to binary expression}} + (void)(i8 | b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svint8_t' (aka '__SVInt8_t') as implicit conversion would cause truncation}} + (void)(i8 | i16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i8 | i32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i8 | i64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i8 | u16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i8 | u32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i8 | u64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(i8 | f16); // expected-error{{invalid operands to binary expression}} (void)(i8 | f32); // expected-error{{invalid operands to binary expression}} (void)(i8 | f64); // expected-error{{invalid operands to binary expression}} - (void)(u8 | b); // expected-error{{invalid operands to binary expression}} - (void)(u8 | i16); // expected-error{{invalid operands to binary expression}} - (void)(u8 | i32); // expected-error{{invalid operands to binary expression}} - (void)(u8 | i64); // expected-error{{invalid operands to binary expression}} - (void)(u8 | u16); // expected-error{{invalid operands to binary expression}} - (void)(u8 | u32); // expected-error{{invalid operands to binary expression}} - (void)(u8 | u64); // expected-error{{invalid operands to binary expression}} + (void)(u8 | b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svuint8_t' (aka '__SVUint8_t') as implicit conversion would cause truncation}} + (void)(u8 | i16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u8 | i32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u8 | i64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u8 | u16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u8 | u32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u8 | u64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(u8 | f16); // expected-error{{invalid operands to binary expression}} (void)(u8 | f32); // expected-error{{invalid operands to binary expression}} (void)(u8 | f64); // expected-error{{invalid operands to binary expression}} - (void)(i16 | b); // expected-error{{invalid operands to binary expression}} - (void)(i16 | i8); // expected-error{{invalid operands to binary expression}} - (void)(i16 | i32); // expected-error{{invalid operands to binary expression}} - (void)(i16 | i64); // expected-error{{invalid operands to binary expression}} - (void)(i16 | u8); // expected-error{{invalid operands to binary expression}} - (void)(i16 | u32); // expected-error{{invalid operands to binary expression}} - (void)(i16 | u64); // expected-error{{invalid operands to binary expression}} + (void)(i16 | b); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i16 | i8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i16 | i32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i16 | i64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i16 | u8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i16 | u32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i16 | u64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(i16 | f16); // expected-error{{invalid operands to binary expression}} (void)(i16 | f32); // expected-error{{invalid operands to binary expression}} (void)(i16 | f64); // expected-error{{invalid operands to binary expression}} - (void)(u16 | b); // expected-error{{invalid operands to binary expression}} - (void)(u16 | i8); // expected-error{{invalid operands to binary expression}} - (void)(u16 | i32); // expected-error{{invalid operands to binary expression}} - (void)(u16 | i64); // expected-error{{invalid operands to binary expression}} - (void)(u16 | u8); // expected-error{{invalid operands to binary expression}} - (void)(u16 | u32); // expected-error{{invalid operands to binary expression}} - (void)(u16 | u64); // expected-error{{invalid operands to binary expression}} + (void)(u16 | b); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u16 | i8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u16 | i32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u16 | i64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u16 | u8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u16 | u32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u16 | u64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(u16 | f16); // expected-error{{invalid operands to binary expression}} (void)(u16 | f32); // expected-error{{invalid operands to binary expression}} (void)(u16 | f64); // expected-error{{invalid operands to binary expression}} - (void)(i32 | b); // expected-error{{invalid operands to binary expression}} - (void)(i32 | i8); // expected-error{{invalid operands to binary expression}} - (void)(i32 | i16); // expected-error{{invalid operands to binary expression}} - (void)(i32 | i64); // expected-error{{invalid operands to binary expression}} - (void)(i32 | u8); // expected-error{{invalid operands to binary expression}} - (void)(i32 | u16); // expected-error{{invalid operands to binary expression}} - (void)(i32 | u64); // expected-error{{invalid operands to binary expression}} + (void)(i32 | b); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i32 | i8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i32 | i16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i32 | i64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i32 | u8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i32 | u16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i32 | u64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(i32 | f16); // expected-error{{invalid operands to binary expression}} (void)(i32 | f32); // expected-error{{invalid operands to binary expression}} (void)(i32 | f64); // expected-error{{invalid operands to binary expression}} - (void)(u32 | b); // expected-error{{invalid operands to binary expression}} - (void)(u32 | i8); // expected-error{{invalid operands to binary expression}} - (void)(u32 | i16); // expected-error{{invalid operands to binary expression}} - (void)(u32 | i64); // expected-error{{invalid operands to binary expression}} - (void)(u32 | u8); // expected-error{{invalid operands to binary expression}} - (void)(u32 | u16); // expected-error{{invalid operands to binary expression}} - (void)(u32 | u64); // expected-error{{invalid operands to binary expression}} + (void)(u32 | b); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u32 | i8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u32 | i16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u32 | i64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u32 | u8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u32 | u16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u32 | u64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(u32 | f16); // expected-error{{invalid operands to binary expression}} (void)(u32 | f32); // expected-error{{invalid operands to binary expression}} (void)(u32 | f64); // expected-error{{invalid operands to binary expression}} - (void)(i64 | b); // expected-error{{invalid operands to binary expression}} - (void)(i64 | i8); // expected-error{{invalid operands to binary expression}} - (void)(i64 | i16); // expected-error{{invalid operands to binary expression}} - (void)(i64 | i32); // expected-error{{invalid operands to binary expression}} - (void)(i64 | u8); // expected-error{{invalid operands to binary expression}} - (void)(i64 | u16); // expected-error{{invalid operands to binary expression}} - (void)(i64 | u32); // expected-error{{invalid operands to binary expression}} + (void)(i64 | b); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i64 | i8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i64 | i16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i64 | i32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i64 | u8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i64 | u16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i64 | u32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} (void)(i64 | f16); // expected-error{{invalid operands to binary expression}} (void)(i64 | f32); // expected-error{{invalid operands to binary expression}} (void)(i64 | f64); // expected-error{{invalid operands to binary expression}} - (void)(u64 | b); // expected-error{{invalid operands to binary expression}} - (void)(u64 | i8); // expected-error{{invalid operands to binary expression}} - (void)(u64 | i16); // expected-error{{invalid operands to binary expression}} - (void)(u64 | i32); // expected-error{{invalid operands to binary expression}} - (void)(u64 | u8); // expected-error{{invalid operands to binary expression}} - (void)(u64 | u16); // expected-error{{invalid operands to binary expression}} - (void)(u64 | u32); // expected-error{{invalid operands to binary expression}} + (void)(u64 | b); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u64 | i8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u64 | i16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u64 | i32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u64 | u8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u64 | u16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u64 | u32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} (void)(u64 | f16); // expected-error{{invalid operands to binary expression}} (void)(u64 | f32); // expected-error{{invalid operands to binary expression}} (void)(u64 | f64); // expected-error{{invalid operands to binary expression}} @@ -262,90 +262,90 @@ void or (svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, } void xor (svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, svbool_t b) { - (void)(i8 ^ b); // expected-error{{invalid operands to binary expression}} - (void)(i8 ^ i16); // expected-error{{invalid operands to binary expression}} - (void)(i8 ^ i32); // expected-error{{invalid operands to binary expression}} - (void)(i8 ^ i64); // expected-error{{invalid operands to binary expression}} - (void)(i8 ^ u16); // expected-error{{invalid operands to binary expression}} - (void)(i8 ^ u32); // expected-error{{invalid operands to binary expression}} - (void)(i8 ^ u64); // expected-error{{invalid operands to binary expression}} + (void)(i8 ^ b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svint8_t' (aka '__SVInt8_t') as implicit conversion would cause truncation}} + (void)(i8 ^ i16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i8 ^ i32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i8 ^ i64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i8 ^ u16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i8 ^ u32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i8 ^ u64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(i8 ^ f16); // expected-error{{invalid operands to binary expression}} (void)(i8 ^ f32); // expected-error{{invalid operands to binary expression}} (void)(i8 ^ f64); // expected-error{{invalid operands to binary expression}} - (void)(u8 ^ b); // expected-error{{invalid operands to binary expression}} - (void)(u8 ^ i16); // expected-error{{invalid operands to binary expression}} - (void)(u8 ^ i32); // expected-error{{invalid operands to binary expression}} - (void)(u8 ^ i64); // expected-error{{invalid operands to binary expression}} - (void)(u8 ^ u16); // expected-error{{invalid operands to binary expression}} - (void)(u8 ^ u32); // expected-error{{invalid operands to binary expression}} - (void)(u8 ^ u64); // expected-error{{invalid operands to binary expression}} + (void)(u8 ^ b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svuint8_t' (aka '__SVUint8_t') as implicit conversion would cause truncation}} + (void)(u8 ^ i16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u8 ^ i32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u8 ^ i64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u8 ^ u16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u8 ^ u32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u8 ^ u64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(u8 ^ f16); // expected-error{{invalid operands to binary expression}} (void)(u8 ^ f32); // expected-error{{invalid operands to binary expression}} (void)(u8 ^ f64); // expected-error{{invalid operands to binary expression}} - (void)(i16 ^ b); // expected-error{{invalid operands to binary expression}} - (void)(i16 ^ i8); // expected-error{{invalid operands to binary expression}} - (void)(i16 ^ i32); // expected-error{{invalid operands to binary expression}} - (void)(i16 ^ i64); // expected-error{{invalid operands to binary expression}} - (void)(i16 ^ u8); // expected-error{{invalid operands to binary expression}} - (void)(i16 ^ u32); // expected-error{{invalid operands to binary expression}} - (void)(i16 ^ u64); // expected-error{{invalid operands to binary expression}} + (void)(i16 ^ b); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i16 ^ i8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i16 ^ i32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i16 ^ i64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i16 ^ u8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i16 ^ u32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i16 ^ u64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(i16 ^ f16); // expected-error{{invalid operands to binary expression}} (void)(i16 ^ f32); // expected-error{{invalid operands to binary expression}} (void)(i16 ^ f64); // expected-error{{invalid operands to binary expression}} - (void)(u16 ^ b); // expected-error{{invalid operands to binary expression}} - (void)(u16 ^ i8); // expected-error{{invalid operands to binary expression}} - (void)(u16 ^ i32); // expected-error{{invalid operands to binary expression}} - (void)(u16 ^ i64); // expected-error{{invalid operands to binary expression}} - (void)(u16 ^ u8); // expected-error{{invalid operands to binary expression}} - (void)(u16 ^ u32); // expected-error{{invalid operands to binary expression}} - (void)(u16 ^ u64); // expected-error{{invalid operands to binary expression}} + (void)(u16 ^ b); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u16 ^ i8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u16 ^ i32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u16 ^ i64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u16 ^ u8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u16 ^ u32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u16 ^ u64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(u16 ^ f16); // expected-error{{invalid operands to binary expression}} (void)(u16 ^ f32); // expected-error{{invalid operands to binary expression}} (void)(u16 ^ f64); // expected-error{{invalid operands to binary expression}} - (void)(i32 ^ b); // expected-error{{invalid operands to binary expression}} - (void)(i32 ^ i8); // expected-error{{invalid operands to binary expression}} - (void)(i32 ^ i16); // expected-error{{invalid operands to binary expression}} - (void)(i32 ^ i64); // expected-error{{invalid operands to binary expression}} - (void)(i32 ^ u8); // expected-error{{invalid operands to binary expression}} - (void)(i32 ^ u16); // expected-error{{invalid operands to binary expression}} - (void)(i32 ^ u64); // expected-error{{invalid operands to binary expression}} + (void)(i32 ^ b); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i32 ^ i8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i32 ^ i16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i32 ^ i64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i32 ^ u8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i32 ^ u16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i32 ^ u64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(i32 ^ f16); // expected-error{{invalid operands to binary expression}} (void)(i32 ^ f32); // expected-error{{invalid operands to binary expression}} (void)(i32 ^ f64); // expected-error{{invalid operands to binary expression}} - (void)(u32 ^ b); // expected-error{{invalid operands to binary expression}} - (void)(u32 ^ i8); // expected-error{{invalid operands to binary expression}} - (void)(u32 ^ i16); // expected-error{{invalid operands to binary expression}} - (void)(u32 ^ i64); // expected-error{{invalid operands to binary expression}} - (void)(u32 ^ u8); // expected-error{{invalid operands to binary expression}} - (void)(u32 ^ u16); // expected-error{{invalid operands to binary expression}} - (void)(u32 ^ u64); // expected-error{{invalid operands to binary expression}} + (void)(u32 ^ b); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u32 ^ i8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u32 ^ i16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u32 ^ i64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u32 ^ u8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u32 ^ u16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u32 ^ u64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} (void)(u32 ^ f16); // expected-error{{invalid operands to binary expression}} (void)(u32 ^ f32); // expected-error{{invalid operands to binary expression}} (void)(u32 ^ f64); // expected-error{{invalid operands to binary expression}} - (void)(i64 ^ b); // expected-error{{invalid operands to binary expression}} - (void)(i64 ^ i8); // expected-error{{invalid operands to binary expression}} - (void)(i64 ^ i16); // expected-error{{invalid operands to binary expression}} - (void)(i64 ^ i32); // expected-error{{invalid operands to binary expression}} - (void)(i64 ^ u8); // expected-error{{invalid operands to binary expression}} - (void)(i64 ^ u16); // expected-error{{invalid operands to binary expression}} - (void)(i64 ^ u32); // expected-error{{invalid operands to binary expression}} + (void)(i64 ^ b); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i64 ^ i8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i64 ^ i16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i64 ^ i32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i64 ^ u8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i64 ^ u16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i64 ^ u32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} (void)(i64 ^ f16); // expected-error{{invalid operands to binary expression}} (void)(i64 ^ f32); // expected-error{{invalid operands to binary expression}} (void)(i64 ^ f64); // expected-error{{invalid operands to binary expression}} - (void)(u64 ^ b); // expected-error{{invalid operands to binary expression}} - (void)(u64 ^ i8); // expected-error{{invalid operands to binary expression}} - (void)(u64 ^ i16); // expected-error{{invalid operands to binary expression}} - (void)(u64 ^ i32); // expected-error{{invalid operands to binary expression}} - (void)(u64 ^ u8); // expected-error{{invalid operands to binary expression}} - (void)(u64 ^ u16); // expected-error{{invalid operands to binary expression}} - (void)(u64 ^ u32); // expected-error{{invalid operands to binary expression}} + (void)(u64 ^ b); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u64 ^ i8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u64 ^ i16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u64 ^ i32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u64 ^ u8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u64 ^ u16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u64 ^ u32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} (void)(u64 ^ f16); // expected-error{{invalid operands to binary expression}} (void)(u64 ^ f32); // expected-error{{invalid operands to binary expression}} (void)(u64 ^ f64); // expected-error{{invalid operands to binary expression}} diff --git a/clang/test/Sema/aarch64-sve-vector-compare-ops.c b/clang/test/Sema/aarch64-sve-vector-compare-ops.c index 6ff91f4c0e33c..1d8f49187f819 100644 --- a/clang/test/Sema/aarch64-sve-vector-compare-ops.c +++ b/clang/test/Sema/aarch64-sve-vector-compare-ops.c @@ -8,754 +8,754 @@ void eq(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, svbool_t b) { - (void)(i8 == b); // expected-error{{invalid operands to binary expression}} - (void)(i8 == i16); // expected-error{{invalid operands to binary expression}} - (void)(i8 == i32); // expected-error{{invalid operands to binary expression}} - (void)(i8 == i64); // expected-error{{invalid operands to binary expression}} - (void)(i8 == u16); // expected-error{{invalid operands to binary expression}} - (void)(i8 == u32); // expected-error{{invalid operands to binary expression}} - (void)(i8 == u64); // expected-error{{invalid operands to binary expression}} - (void)(i8 == f16); // expected-error{{invalid operands to binary expression}} - (void)(i8 == f32); // expected-error{{invalid operands to binary expression}} - (void)(i8 == f64); // expected-error{{invalid operands to binary expression}} - - (void)(u8 == b); // expected-error{{invalid operands to binary expression}} - (void)(u8 == i16); // expected-error{{invalid operands to binary expression}} - (void)(u8 == i32); // expected-error{{invalid operands to binary expression}} - (void)(u8 == i64); // expected-error{{invalid operands to binary expression}} - (void)(u8 == u16); // expected-error{{invalid operands to binary expression}} - (void)(u8 == u32); // expected-error{{invalid operands to binary expression}} - (void)(u8 == u64); // expected-error{{invalid operands to binary expression}} - (void)(u8 == f16); // expected-error{{invalid operands to binary expression}} - (void)(u8 == f32); // expected-error{{invalid operands to binary expression}} - (void)(u8 == f64); // expected-error{{invalid operands to binary expression}} - - (void)(i16 == b); // expected-error{{invalid operands to binary expression}} - (void)(i16 == i8); // expected-error{{invalid operands to binary expression}} - (void)(i16 == i32); // expected-error{{invalid operands to binary expression}} - (void)(i16 == i64); // expected-error{{invalid operands to binary expression}} - (void)(i16 == u8); // expected-error{{invalid operands to binary expression}} - (void)(i16 == u32); // expected-error{{invalid operands to binary expression}} - (void)(i16 == u64); // expected-error{{invalid operands to binary expression}} - (void)(i16 == f16); // expected-error{{invalid operands to binary expression}} - (void)(i16 == f32); // expected-error{{invalid operands to binary expression}} - (void)(i16 == f64); // expected-error{{invalid operands to binary expression}} - - (void)(u16 == b); // expected-error{{invalid operands to binary expression}} - (void)(u16 == i8); // expected-error{{invalid operands to binary expression}} - (void)(u16 == i32); // expected-error{{invalid operands to binary expression}} - (void)(u16 == i64); // expected-error{{invalid operands to binary expression}} - (void)(u16 == u8); // expected-error{{invalid operands to binary expression}} - (void)(u16 == u32); // expected-error{{invalid operands to binary expression}} - (void)(u16 == u64); // expected-error{{invalid operands to binary expression}} - (void)(u16 == f16); // expected-error{{invalid operands to binary expression}} - (void)(u16 == f32); // expected-error{{invalid operands to binary expression}} - (void)(u16 == f64); // expected-error{{invalid operands to binary expression}} - - (void)(i32 == b); // expected-error{{invalid operands to binary expression}} - (void)(i32 == i8); // expected-error{{invalid operands to binary expression}} - (void)(i32 == i16); // expected-error{{invalid operands to binary expression}} - (void)(i32 == i64); // expected-error{{invalid operands to binary expression}} - (void)(i32 == u8); // expected-error{{invalid operands to binary expression}} - (void)(i32 == u16); // expected-error{{invalid operands to binary expression}} - (void)(i32 == u64); // expected-error{{invalid operands to binary expression}} - (void)(i32 == f16); // expected-error{{invalid operands to binary expression}} - (void)(i32 == f32); // expected-error{{invalid operands to binary expression}} - (void)(i32 == f64); // expected-error{{invalid operands to binary expression}} - - (void)(u32 == b); // expected-error{{invalid operands to binary expression}} - (void)(u32 == i8); // expected-error{{invalid operands to binary expression}} - (void)(u32 == i16); // expected-error{{invalid operands to binary expression}} - (void)(u32 == i64); // expected-error{{invalid operands to binary expression}} - (void)(u32 == u8); // expected-error{{invalid operands to binary expression}} - (void)(u32 == u16); // expected-error{{invalid operands to binary expression}} - (void)(u32 == u64); // expected-error{{invalid operands to binary expression}} - (void)(u32 == f16); // expected-error{{invalid operands to binary expression}} - (void)(u32 == f32); // expected-error{{invalid operands to binary expression}} - (void)(u32 == f64); // expected-error{{invalid operands to binary expression}} - - (void)(i64 == b); // expected-error{{invalid operands to binary expression}} - (void)(i64 == i8); // expected-error{{invalid operands to binary expression}} - (void)(i64 == i16); // expected-error{{invalid operands to binary expression}} - (void)(i64 == i32); // expected-error{{invalid operands to binary expression}} - (void)(i64 == u8); // expected-error{{invalid operands to binary expression}} - (void)(i64 == u16); // expected-error{{invalid operands to binary expression}} - (void)(i64 == u32); // expected-error{{invalid operands to binary expression}} - (void)(i64 == f16); // expected-error{{invalid operands to binary expression}} - (void)(i64 == f32); // expected-error{{invalid operands to binary expression}} - (void)(i64 == f64); // expected-error{{invalid operands to binary expression}} - - (void)(u64 == b); // expected-error{{invalid operands to binary expression}} - (void)(u64 == i8); // expected-error{{invalid operands to binary expression}} - (void)(u64 == i16); // expected-error{{invalid operands to binary expression}} - (void)(u64 == i32); // expected-error{{invalid operands to binary expression}} - (void)(u64 == u8); // expected-error{{invalid operands to binary expression}} - (void)(u64 == u16); // expected-error{{invalid operands to binary expression}} - (void)(u64 == u32); // expected-error{{invalid operands to binary expression}} - (void)(u64 == f16); // expected-error{{invalid operands to binary expression}} - (void)(u64 == f32); // expected-error{{invalid operands to binary expression}} - (void)(u64 == f64); // expected-error{{invalid operands to binary expression}} - - (void)(f16 == b); // expected-error{{invalid operands to binary expression}} - (void)(f16 == i8); // expected-error{{invalid operands to binary expression}} - (void)(f16 == i16); // expected-error{{invalid operands to binary expression}} - (void)(f16 == i32); // expected-error{{invalid operands to binary expression}} - (void)(f16 == i64); // expected-error{{invalid operands to binary expression}} - (void)(f16 == u8); // expected-error{{invalid operands to binary expression}} - (void)(f16 == u32); // expected-error{{invalid operands to binary expression}} - (void)(f16 == u64); // expected-error{{invalid operands to binary expression}} - (void)(f16 == f32); // expected-error{{invalid operands to binary expression}} - (void)(f16 == f64); // expected-error{{invalid operands to binary expression}} - - (void)(f32 == b); // expected-error{{invalid operands to binary expression}} - (void)(f32 == i8); // expected-error{{invalid operands to binary expression}} - (void)(f32 == i16); // expected-error{{invalid operands to binary expression}} - (void)(f32 == i32); // expected-error{{invalid operands to binary expression}} - (void)(f32 == i64); // expected-error{{invalid operands to binary expression}} - (void)(f32 == u8); // expected-error{{invalid operands to binary expression}} - (void)(f32 == u16); // expected-error{{invalid operands to binary expression}} - (void)(f32 == u64); // expected-error{{invalid operands to binary expression}} - (void)(f32 == f16); // expected-error{{invalid operands to binary expression}} - (void)(f32 == f64); // expected-error{{invalid operands to binary expression}} - - (void)(f64 == b); // expected-error{{invalid operands to binary expression}} - (void)(f64 == i8); // expected-error{{invalid operands to binary expression}} - (void)(f64 == i16); // expected-error{{invalid operands to binary expression}} - (void)(f64 == i32); // expected-error{{invalid operands to binary expression}} - (void)(f64 == i64); // expected-error{{invalid operands to binary expression}} - (void)(f64 == u8); // expected-error{{invalid operands to binary expression}} - (void)(f64 == u16); // expected-error{{invalid operands to binary expression}} - (void)(f64 == u32); // expected-error{{invalid operands to binary expression}} - (void)(f64 == f16); // expected-error{{invalid operands to binary expression}} - (void)(f64 == f32); // expected-error{{invalid operands to binary expression}} + (void)(i8 == b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svint8_t' (aka '__SVInt8_t') as implicit conversion would cause truncation}} + (void)(i8 == i16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i8 == i32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i8 == i64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i8 == u16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i8 == u32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i8 == u64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i8 == f16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i8 == f32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i8 == f64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u8 == b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svuint8_t' (aka '__SVUint8_t') as implicit conversion would cause truncation}} + (void)(u8 == i16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u8 == i32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u8 == i64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u8 == u16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u8 == u32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u8 == u64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u8 == f16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u8 == f32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u8 == f64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i16 == b); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i16 == i8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i16 == i32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i16 == i64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i16 == u8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i16 == u32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i16 == u64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i16 == f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svint16_t' (aka '__SVInt16_t') as implicit conversion would cause truncation}} + (void)(i16 == f32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i16 == f64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u16 == b); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u16 == i8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u16 == i32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u16 == i64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u16 == u8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u16 == u32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u16 == u64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u16 == f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svuint16_t' (aka '__SVUint16_t') as implicit conversion would cause truncation}} + (void)(u16 == f32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u16 == f64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i32 == b); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i32 == i8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i32 == i16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i32 == i64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i32 == u8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i32 == u16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i32 == u64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i32 == f16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i32 == f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svint32_t' (aka '__SVInt32_t') as implicit conversion would cause truncation}} + (void)(i32 == f64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u32 == b); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u32 == i8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u32 == i16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u32 == i64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u32 == u8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u32 == u16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u32 == u64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u32 == f16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u32 == f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svuint32_t' (aka '__SVUint32_t') as implicit conversion would cause truncation}} + (void)(u32 == f64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i64 == b); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i64 == i8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i64 == i16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i64 == i32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i64 == u8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i64 == u16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i64 == u32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i64 == f16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i64 == f32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i64 == f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svint64_t' (aka '__SVInt64_t') as implicit conversion would cause truncation}} + + (void)(u64 == b); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u64 == i8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u64 == i16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u64 == i32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u64 == u8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u64 == u16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u64 == u32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u64 == f16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u64 == f32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u64 == f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svuint64_t' (aka '__SVUint64_t') as implicit conversion would cause truncation}} + + (void)(f16 == b); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f16 == i8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f16 == i16); // expected-error{{cannot convert between vector type 'svint16_t' (aka '__SVInt16_t') and vector type 'svfloat16_t' (aka '__SVFloat16_t') as implicit conversion would cause truncation}} + (void)(f16 == i32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f16 == i64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f16 == u8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f16 == u32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f16 == u64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f16 == f32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(f16 == f64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(f32 == b); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f32 == i8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f32 == i16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f32 == i32); // expected-error{{cannot convert between vector type 'svint32_t' (aka '__SVInt32_t') and vector type 'svfloat32_t' (aka '__SVFloat32_t') as implicit conversion would cause truncation}} + (void)(f32 == i64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f32 == u8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f32 == u16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f32 == u64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f32 == f16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f32 == f64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(f64 == b); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f64 == i8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f64 == i16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f64 == i32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f64 == i64); // expected-error{{cannot convert between vector type 'svint64_t' (aka '__SVInt64_t') and vector type 'svfloat64_t' (aka '__SVFloat64_t') as implicit conversion would cause truncation}} + (void)(f64 == u8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f64 == u16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f64 == u32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f64 == f16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f64 == f32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} } void neq(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, svbool_t b) { - (void)(i8 != b); // expected-error{{invalid operands to binary expression}} - (void)(i8 != i16); // expected-error{{invalid operands to binary expression}} - (void)(i8 != i32); // expected-error{{invalid operands to binary expression}} - (void)(i8 != i64); // expected-error{{invalid operands to binary expression}} - (void)(i8 != u16); // expected-error{{invalid operands to binary expression}} - (void)(i8 != u32); // expected-error{{invalid operands to binary expression}} - (void)(i8 != u64); // expected-error{{invalid operands to binary expression}} - (void)(i8 != f16); // expected-error{{invalid operands to binary expression}} - (void)(i8 != f32); // expected-error{{invalid operands to binary expression}} - (void)(i8 != f64); // expected-error{{invalid operands to binary expression}} - - (void)(u8 != b); // expected-error{{invalid operands to binary expression}} - (void)(u8 != i16); // expected-error{{invalid operands to binary expression}} - (void)(u8 != i32); // expected-error{{invalid operands to binary expression}} - (void)(u8 != i64); // expected-error{{invalid operands to binary expression}} - (void)(u8 != u16); // expected-error{{invalid operands to binary expression}} - (void)(u8 != u32); // expected-error{{invalid operands to binary expression}} - (void)(u8 != u64); // expected-error{{invalid operands to binary expression}} - (void)(u8 != f16); // expected-error{{invalid operands to binary expression}} - (void)(u8 != f32); // expected-error{{invalid operands to binary expression}} - (void)(u8 != f64); // expected-error{{invalid operands to binary expression}} - - (void)(i16 != b); // expected-error{{invalid operands to binary expression}} - (void)(i16 != i8); // expected-error{{invalid operands to binary expression}} - (void)(i16 != i32); // expected-error{{invalid operands to binary expression}} - (void)(i16 != i64); // expected-error{{invalid operands to binary expression}} - (void)(i16 != u8); // expected-error{{invalid operands to binary expression}} - (void)(i16 != u32); // expected-error{{invalid operands to binary expression}} - (void)(i16 != u64); // expected-error{{invalid operands to binary expression}} - (void)(i16 != f16); // expected-error{{invalid operands to binary expression}} - (void)(i16 != f32); // expected-error{{invalid operands to binary expression}} - (void)(i16 != f64); // expected-error{{invalid operands to binary expression}} - - (void)(u16 != b); // expected-error{{invalid operands to binary expression}} - (void)(u16 != i8); // expected-error{{invalid operands to binary expression}} - (void)(u16 != i32); // expected-error{{invalid operands to binary expression}} - (void)(u16 != i64); // expected-error{{invalid operands to binary expression}} - (void)(u16 != u8); // expected-error{{invalid operands to binary expression}} - (void)(u16 != u32); // expected-error{{invalid operands to binary expression}} - (void)(u16 != u64); // expected-error{{invalid operands to binary expression}} - (void)(u16 != f16); // expected-error{{invalid operands to binary expression}} - (void)(u16 != f32); // expected-error{{invalid operands to binary expression}} - (void)(u16 != f64); // expected-error{{invalid operands to binary expression}} - - (void)(i32 != b); // expected-error{{invalid operands to binary expression}} - (void)(i32 != i8); // expected-error{{invalid operands to binary expression}} - (void)(i32 != i16); // expected-error{{invalid operands to binary expression}} - (void)(i32 != i64); // expected-error{{invalid operands to binary expression}} - (void)(i32 != u8); // expected-error{{invalid operands to binary expression}} - (void)(i32 != u16); // expected-error{{invalid operands to binary expression}} - (void)(i32 != u64); // expected-error{{invalid operands to binary expression}} - (void)(i32 != f16); // expected-error{{invalid operands to binary expression}} - (void)(i32 != f32); // expected-error{{invalid operands to binary expression}} - (void)(i32 != f64); // expected-error{{invalid operands to binary expression}} - - (void)(u32 != b); // expected-error{{invalid operands to binary expression}} - (void)(u32 != i8); // expected-error{{invalid operands to binary expression}} - (void)(u32 != i16); // expected-error{{invalid operands to binary expression}} - (void)(u32 != i64); // expected-error{{invalid operands to binary expression}} - (void)(u32 != u8); // expected-error{{invalid operands to binary expression}} - (void)(u32 != u16); // expected-error{{invalid operands to binary expression}} - (void)(u32 != u64); // expected-error{{invalid operands to binary expression}} - (void)(u32 != f16); // expected-error{{invalid operands to binary expression}} - (void)(u32 != f32); // expected-error{{invalid operands to binary expression}} - (void)(u32 != f64); // expected-error{{invalid operands to binary expression}} - - (void)(i64 != b); // expected-error{{invalid operands to binary expression}} - (void)(i64 != i8); // expected-error{{invalid operands to binary expression}} - (void)(i64 != i16); // expected-error{{invalid operands to binary expression}} - (void)(i64 != i32); // expected-error{{invalid operands to binary expression}} - (void)(i64 != u8); // expected-error{{invalid operands to binary expression}} - (void)(i64 != u16); // expected-error{{invalid operands to binary expression}} - (void)(i64 != u32); // expected-error{{invalid operands to binary expression}} - (void)(i64 != f16); // expected-error{{invalid operands to binary expression}} - (void)(i64 != f32); // expected-error{{invalid operands to binary expression}} - (void)(i64 != f64); // expected-error{{invalid operands to binary expression}} - - (void)(u64 != b); // expected-error{{invalid operands to binary expression}} - (void)(u64 != i8); // expected-error{{invalid operands to binary expression}} - (void)(u64 != i16); // expected-error{{invalid operands to binary expression}} - (void)(u64 != i32); // expected-error{{invalid operands to binary expression}} - (void)(u64 != u8); // expected-error{{invalid operands to binary expression}} - (void)(u64 != u16); // expected-error{{invalid operands to binary expression}} - (void)(u64 != u32); // expected-error{{invalid operands to binary expression}} - (void)(u64 != f16); // expected-error{{invalid operands to binary expression}} - (void)(u64 != f32); // expected-error{{invalid operands to binary expression}} - (void)(u64 != f64); // expected-error{{invalid operands to binary expression}} - - (void)(f16 != b); // expected-error{{invalid operands to binary expression}} - (void)(f16 != i8); // expected-error{{invalid operands to binary expression}} - (void)(f16 != i16); // expected-error{{invalid operands to binary expression}} - (void)(f16 != i32); // expected-error{{invalid operands to binary expression}} - (void)(f16 != i64); // expected-error{{invalid operands to binary expression}} - (void)(f16 != u8); // expected-error{{invalid operands to binary expression}} - (void)(f16 != u32); // expected-error{{invalid operands to binary expression}} - (void)(f16 != u64); // expected-error{{invalid operands to binary expression}} - (void)(f16 != f32); // expected-error{{invalid operands to binary expression}} - (void)(f16 != f64); // expected-error{{invalid operands to binary expression}} - - (void)(f32 != b); // expected-error{{invalid operands to binary expression}} - (void)(f32 != i8); // expected-error{{invalid operands to binary expression}} - (void)(f32 != i16); // expected-error{{invalid operands to binary expression}} - (void)(f32 != i32); // expected-error{{invalid operands to binary expression}} - (void)(f32 != i64); // expected-error{{invalid operands to binary expression}} - (void)(f32 != u8); // expected-error{{invalid operands to binary expression}} - (void)(f32 != u16); // expected-error{{invalid operands to binary expression}} - (void)(f32 != u64); // expected-error{{invalid operands to binary expression}} - (void)(f32 != f16); // expected-error{{invalid operands to binary expression}} - (void)(f32 != f64); // expected-error{{invalid operands to binary expression}} - - (void)(f64 != b); // expected-error{{invalid operands to binary expression}} - (void)(f64 != i8); // expected-error{{invalid operands to binary expression}} - (void)(f64 != i16); // expected-error{{invalid operands to binary expression}} - (void)(f64 != i32); // expected-error{{invalid operands to binary expression}} - (void)(f64 != i64); // expected-error{{invalid operands to binary expression}} - (void)(f64 != u8); // expected-error{{invalid operands to binary expression}} - (void)(f64 != u16); // expected-error{{invalid operands to binary expression}} - (void)(f64 != u32); // expected-error{{invalid operands to binary expression}} - (void)(f64 != f16); // expected-error{{invalid operands to binary expression}} - (void)(f64 != f32); // expected-error{{invalid operands to binary expression}} + (void)(i8 != b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svint8_t' (aka '__SVInt8_t') as implicit conversion would cause truncation}} + (void)(i8 != i16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i8 != i32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i8 != i64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i8 != u16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i8 != u32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i8 != u64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i8 != f16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i8 != f32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i8 != f64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u8 != b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svuint8_t' (aka '__SVUint8_t') as implicit conversion would cause truncation}} + (void)(u8 != i16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u8 != i32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u8 != i64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u8 != u16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u8 != u32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u8 != u64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u8 != f16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u8 != f32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u8 != f64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i16 != b); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i16 != i8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i16 != i32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i16 != i64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i16 != u8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i16 != u32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i16 != u64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i16 != f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svint16_t' (aka '__SVInt16_t') as implicit conversion would cause truncation}} + (void)(i16 != f32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i16 != f64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u16 != b); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u16 != i8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u16 != i32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u16 != i64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u16 != u8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u16 != u32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u16 != u64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u16 != f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svuint16_t' (aka '__SVUint16_t') as implicit conversion would cause truncation}} + (void)(u16 != f32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u16 != f64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i32 != b); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i32 != i8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i32 != i16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i32 != i64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i32 != u8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i32 != u16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i32 != u64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i32 != f16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i32 != f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svint32_t' (aka '__SVInt32_t') as implicit conversion would cause truncation}} + (void)(i32 != f64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u32 != b); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u32 != i8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u32 != i16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u32 != i64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u32 != u8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u32 != u16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u32 != u64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u32 != f16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u32 != f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svuint32_t' (aka '__SVUint32_t') as implicit conversion would cause truncation}} + (void)(u32 != f64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i64 != b); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i64 != i8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i64 != i16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i64 != i32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i64 != u8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i64 != u16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i64 != u32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i64 != f16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i64 != f32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i64 != f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svint64_t' (aka '__SVInt64_t') as implicit conversion would cause truncation}} + + (void)(u64 != b); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u64 != i8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u64 != i16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u64 != i32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u64 != u8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u64 != u16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u64 != u32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u64 != f16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u64 != f32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u64 != f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svuint64_t' (aka '__SVUint64_t') as implicit conversion would cause truncation}} + + (void)(f16 != b); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f16 != i8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f16 != i16); // expected-error{{cannot convert between vector type 'svint16_t' (aka '__SVInt16_t') and vector type 'svfloat16_t' (aka '__SVFloat16_t') as implicit conversion would cause truncation}} + (void)(f16 != i32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f16 != i64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f16 != u8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f16 != u32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f16 != u64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f16 != f32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(f16 != f64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(f32 != b); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f32 != i8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f32 != i16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f32 != i32); // expected-error{{cannot convert between vector type 'svint32_t' (aka '__SVInt32_t') and vector type 'svfloat32_t' (aka '__SVFloat32_t') as implicit conversion would cause truncation}} + (void)(f32 != i64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f32 != u8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f32 != u16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f32 != u64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f32 != f16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f32 != f64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(f64 != b); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f64 != i8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f64 != i16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f64 != i32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f64 != i64); // expected-error{{cannot convert between vector type 'svint64_t' (aka '__SVInt64_t') and vector type 'svfloat64_t' (aka '__SVFloat64_t') as implicit conversion would cause truncation}} + (void)(f64 != u8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f64 != u16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f64 != u32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f64 != f16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f64 != f32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} } void lt(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, svbool_t b) { - (void)(i8 < b); // expected-error{{invalid operands to binary expression}} - (void)(i8 < i16); // expected-error{{invalid operands to binary expression}} - (void)(i8 < i32); // expected-error{{invalid operands to binary expression}} - (void)(i8 < i64); // expected-error{{invalid operands to binary expression}} - (void)(i8 < u16); // expected-error{{invalid operands to binary expression}} - (void)(i8 < u32); // expected-error{{invalid operands to binary expression}} - (void)(i8 < u64); // expected-error{{invalid operands to binary expression}} - (void)(i8 < f16); // expected-error{{invalid operands to binary expression}} - (void)(i8 < f32); // expected-error{{invalid operands to binary expression}} - (void)(i8 < f64); // expected-error{{invalid operands to binary expression}} - - (void)(u8 < b); // expected-error{{invalid operands to binary expression}} - (void)(u8 < i16); // expected-error{{invalid operands to binary expression}} - (void)(u8 < i32); // expected-error{{invalid operands to binary expression}} - (void)(u8 < i64); // expected-error{{invalid operands to binary expression}} - (void)(u8 < u16); // expected-error{{invalid operands to binary expression}} - (void)(u8 < u32); // expected-error{{invalid operands to binary expression}} - (void)(u8 < u64); // expected-error{{invalid operands to binary expression}} - (void)(u8 < f16); // expected-error{{invalid operands to binary expression}} - (void)(u8 < f32); // expected-error{{invalid operands to binary expression}} - (void)(u8 < f64); // expected-error{{invalid operands to binary expression}} - - (void)(i16 < b); // expected-error{{invalid operands to binary expression}} - (void)(i16 < i8); // expected-error{{invalid operands to binary expression}} - (void)(i16 < i32); // expected-error{{invalid operands to binary expression}} - (void)(i16 < i64); // expected-error{{invalid operands to binary expression}} - (void)(i16 < u8); // expected-error{{invalid operands to binary expression}} - (void)(i16 < u32); // expected-error{{invalid operands to binary expression}} - (void)(i16 < u64); // expected-error{{invalid operands to binary expression}} - (void)(i16 < f16); // expected-error{{invalid operands to binary expression}} - (void)(i16 < f32); // expected-error{{invalid operands to binary expression}} - (void)(i16 < f64); // expected-error{{invalid operands to binary expression}} - - (void)(u16 < b); // expected-error{{invalid operands to binary expression}} - (void)(u16 < i8); // expected-error{{invalid operands to binary expression}} - (void)(u16 < i32); // expected-error{{invalid operands to binary expression}} - (void)(u16 < i64); // expected-error{{invalid operands to binary expression}} - (void)(u16 < u8); // expected-error{{invalid operands to binary expression}} - (void)(u16 < u32); // expected-error{{invalid operands to binary expression}} - (void)(u16 < u64); // expected-error{{invalid operands to binary expression}} - (void)(u16 < f16); // expected-error{{invalid operands to binary expression}} - (void)(u16 < f32); // expected-error{{invalid operands to binary expression}} - (void)(u16 < f64); // expected-error{{invalid operands to binary expression}} - - (void)(i32 < b); // expected-error{{invalid operands to binary expression}} - (void)(i32 < i8); // expected-error{{invalid operands to binary expression}} - (void)(i32 < i16); // expected-error{{invalid operands to binary expression}} - (void)(i32 < i64); // expected-error{{invalid operands to binary expression}} - (void)(i32 < u8); // expected-error{{invalid operands to binary expression}} - (void)(i32 < u16); // expected-error{{invalid operands to binary expression}} - (void)(i32 < u64); // expected-error{{invalid operands to binary expression}} - (void)(i32 < f16); // expected-error{{invalid operands to binary expression}} - (void)(i32 < f32); // expected-error{{invalid operands to binary expression}} - (void)(i32 < f64); // expected-error{{invalid operands to binary expression}} - - (void)(u32 < b); // expected-error{{invalid operands to binary expression}} - (void)(u32 < i8); // expected-error{{invalid operands to binary expression}} - (void)(u32 < i16); // expected-error{{invalid operands to binary expression}} - (void)(u32 < i64); // expected-error{{invalid operands to binary expression}} - (void)(u32 < u8); // expected-error{{invalid operands to binary expression}} - (void)(u32 < u16); // expected-error{{invalid operands to binary expression}} - (void)(u32 < u64); // expected-error{{invalid operands to binary expression}} - (void)(u32 < f16); // expected-error{{invalid operands to binary expression}} - (void)(u32 < f32); // expected-error{{invalid operands to binary expression}} - (void)(u32 < f64); // expected-error{{invalid operands to binary expression}} - - (void)(i64 < b); // expected-error{{invalid operands to binary expression}} - (void)(i64 < i8); // expected-error{{invalid operands to binary expression}} - (void)(i64 < i16); // expected-error{{invalid operands to binary expression}} - (void)(i64 < i32); // expected-error{{invalid operands to binary expression}} - (void)(i64 < u8); // expected-error{{invalid operands to binary expression}} - (void)(i64 < u16); // expected-error{{invalid operands to binary expression}} - (void)(i64 < u32); // expected-error{{invalid operands to binary expression}} - (void)(i64 < f16); // expected-error{{invalid operands to binary expression}} - (void)(i64 < f32); // expected-error{{invalid operands to binary expression}} - (void)(i64 < f64); // expected-error{{invalid operands to binary expression}} - - (void)(u64 < b); // expected-error{{invalid operands to binary expression}} - (void)(u64 < i8); // expected-error{{invalid operands to binary expression}} - (void)(u64 < i16); // expected-error{{invalid operands to binary expression}} - (void)(u64 < i32); // expected-error{{invalid operands to binary expression}} - (void)(u64 < u8); // expected-error{{invalid operands to binary expression}} - (void)(u64 < u16); // expected-error{{invalid operands to binary expression}} - (void)(u64 < u32); // expected-error{{invalid operands to binary expression}} - (void)(u64 < f16); // expected-error{{invalid operands to binary expression}} - (void)(u64 < f32); // expected-error{{invalid operands to binary expression}} - (void)(u64 < f64); // expected-error{{invalid operands to binary expression}} - - (void)(f16 < b); // expected-error{{invalid operands to binary expression}} - (void)(f16 < i8); // expected-error{{invalid operands to binary expression}} - (void)(f16 < i16); // expected-error{{invalid operands to binary expression}} - (void)(f16 < i32); // expected-error{{invalid operands to binary expression}} - (void)(f16 < i64); // expected-error{{invalid operands to binary expression}} - (void)(f16 < u8); // expected-error{{invalid operands to binary expression}} - (void)(f16 < u32); // expected-error{{invalid operands to binary expression}} - (void)(f16 < u64); // expected-error{{invalid operands to binary expression}} - (void)(f16 < f32); // expected-error{{invalid operands to binary expression}} - (void)(f16 < f64); // expected-error{{invalid operands to binary expression}} - - (void)(f32 < b); // expected-error{{invalid operands to binary expression}} - (void)(f32 < i8); // expected-error{{invalid operands to binary expression}} - (void)(f32 < i16); // expected-error{{invalid operands to binary expression}} - (void)(f32 < i32); // expected-error{{invalid operands to binary expression}} - (void)(f32 < i64); // expected-error{{invalid operands to binary expression}} - (void)(f32 < u8); // expected-error{{invalid operands to binary expression}} - (void)(f32 < u16); // expected-error{{invalid operands to binary expression}} - (void)(f32 < u64); // expected-error{{invalid operands to binary expression}} - (void)(f32 < f16); // expected-error{{invalid operands to binary expression}} - (void)(f32 < f64); // expected-error{{invalid operands to binary expression}} - - (void)(f64 < b); // expected-error{{invalid operands to binary expression}} - (void)(f64 < i8); // expected-error{{invalid operands to binary expression}} - (void)(f64 < i16); // expected-error{{invalid operands to binary expression}} - (void)(f64 < i32); // expected-error{{invalid operands to binary expression}} - (void)(f64 < i64); // expected-error{{invalid operands to binary expression}} - (void)(f64 < u8); // expected-error{{invalid operands to binary expression}} - (void)(f64 < u16); // expected-error{{invalid operands to binary expression}} - (void)(f64 < u32); // expected-error{{invalid operands to binary expression}} - (void)(f64 < f16); // expected-error{{invalid operands to binary expression}} - (void)(f64 < f32); // expected-error{{invalid operands to binary expression}} + (void)(i8 < b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svint8_t' (aka '__SVInt8_t') as implicit conversion would cause truncation}} + (void)(i8 < i16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i8 < i32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i8 < i64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i8 < u16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i8 < u32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i8 < u64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i8 < f16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i8 < f32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i8 < f64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u8 < b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svuint8_t' (aka '__SVUint8_t') as implicit conversion would cause truncation}} + (void)(u8 < i16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u8 < i32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u8 < i64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u8 < u16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u8 < u32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u8 < u64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u8 < f16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u8 < f32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u8 < f64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i16 < b); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i16 < i8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i16 < i32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i16 < i64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i16 < u8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i16 < u32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i16 < u64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i16 < f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svint16_t' (aka '__SVInt16_t') as implicit conversion would cause truncation}} + (void)(i16 < f32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i16 < f64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u16 < b); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u16 < i8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u16 < i32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u16 < i64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u16 < u8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u16 < u32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u16 < u64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u16 < f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svuint16_t' (aka '__SVUint16_t') as implicit conversion would cause truncation}} + (void)(u16 < f32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u16 < f64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i32 < b); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i32 < i8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i32 < i16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i32 < i64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i32 < u8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i32 < u16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i32 < u64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i32 < f16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i32 < f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svint32_t' (aka '__SVInt32_t') as implicit conversion would cause truncation}} + (void)(i32 < f64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u32 < b); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u32 < i8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u32 < i16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u32 < i64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u32 < u8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u32 < u16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u32 < u64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u32 < f16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u32 < f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svuint32_t' (aka '__SVUint32_t') as implicit conversion would cause truncation}} + (void)(u32 < f64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i64 < b); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i64 < i8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i64 < i16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i64 < i32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i64 < u8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i64 < u16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i64 < u32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i64 < f16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i64 < f32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i64 < f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svint64_t' (aka '__SVInt64_t') as implicit conversion would cause truncation}} + + (void)(u64 < b); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u64 < i8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u64 < i16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u64 < i32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u64 < u8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u64 < u16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u64 < u32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u64 < f16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u64 < f32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u64 < f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svuint64_t' (aka '__SVUint64_t') as implicit conversion would cause truncation}} + + (void)(f16 < b); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f16 < i8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f16 < i16); // expected-error{{cannot convert between vector type 'svint16_t' (aka '__SVInt16_t') and vector type 'svfloat16_t' (aka '__SVFloat16_t') as implicit conversion would cause truncation}} + (void)(f16 < i32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f16 < i64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f16 < u8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f16 < u32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f16 < u64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f16 < f32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(f16 < f64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(f32 < b); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f32 < i8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f32 < i16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f32 < i32); // expected-error{{cannot convert between vector type 'svint32_t' (aka '__SVInt32_t') and vector type 'svfloat32_t' (aka '__SVFloat32_t') as implicit conversion would cause truncation}} + (void)(f32 < i64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f32 < u8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f32 < u16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f32 < u64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f32 < f16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f32 < f64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(f64 < b); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f64 < i8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f64 < i16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f64 < i32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f64 < i64); // expected-error{{cannot convert between vector type 'svint64_t' (aka '__SVInt64_t') and vector type 'svfloat64_t' (aka '__SVFloat64_t') as implicit conversion would cause truncation}} + (void)(f64 < u8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f64 < u16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f64 < u32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f64 < f16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f64 < f32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} } void leq(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, svbool_t b) { - (void)(i8 <= b); // expected-error{{invalid operands to binary expression}} - (void)(i8 <= i16); // expected-error{{invalid operands to binary expression}} - (void)(i8 <= i32); // expected-error{{invalid operands to binary expression}} - (void)(i8 <= i64); // expected-error{{invalid operands to binary expression}} - (void)(i8 <= u16); // expected-error{{invalid operands to binary expression}} - (void)(i8 <= u32); // expected-error{{invalid operands to binary expression}} - (void)(i8 <= u64); // expected-error{{invalid operands to binary expression}} - (void)(i8 <= f16); // expected-error{{invalid operands to binary expression}} - (void)(i8 <= f32); // expected-error{{invalid operands to binary expression}} - (void)(i8 <= f64); // expected-error{{invalid operands to binary expression}} - - (void)(u8 <= b); // expected-error{{invalid operands to binary expression}} - (void)(u8 <= i16); // expected-error{{invalid operands to binary expression}} - (void)(u8 <= i32); // expected-error{{invalid operands to binary expression}} - (void)(u8 <= i64); // expected-error{{invalid operands to binary expression}} - (void)(u8 <= u16); // expected-error{{invalid operands to binary expression}} - (void)(u8 <= u32); // expected-error{{invalid operands to binary expression}} - (void)(u8 <= u64); // expected-error{{invalid operands to binary expression}} - (void)(u8 <= f16); // expected-error{{invalid operands to binary expression}} - (void)(u8 <= f32); // expected-error{{invalid operands to binary expression}} - (void)(u8 <= f64); // expected-error{{invalid operands to binary expression}} - - (void)(i16 <= b); // expected-error{{invalid operands to binary expression}} - (void)(i16 <= i8); // expected-error{{invalid operands to binary expression}} - (void)(i16 <= i32); // expected-error{{invalid operands to binary expression}} - (void)(i16 <= i64); // expected-error{{invalid operands to binary expression}} - (void)(i16 <= u8); // expected-error{{invalid operands to binary expression}} - (void)(i16 <= u32); // expected-error{{invalid operands to binary expression}} - (void)(i16 <= u64); // expected-error{{invalid operands to binary expression}} - (void)(i16 <= f16); // expected-error{{invalid operands to binary expression}} - (void)(i16 <= f32); // expected-error{{invalid operands to binary expression}} - (void)(i16 <= f64); // expected-error{{invalid operands to binary expression}} - - (void)(u16 <= b); // expected-error{{invalid operands to binary expression}} - (void)(u16 <= i8); // expected-error{{invalid operands to binary expression}} - (void)(u16 <= i32); // expected-error{{invalid operands to binary expression}} - (void)(u16 <= i64); // expected-error{{invalid operands to binary expression}} - (void)(u16 <= u8); // expected-error{{invalid operands to binary expression}} - (void)(u16 <= u32); // expected-error{{invalid operands to binary expression}} - (void)(u16 <= u64); // expected-error{{invalid operands to binary expression}} - (void)(u16 <= f16); // expected-error{{invalid operands to binary expression}} - (void)(u16 <= f32); // expected-error{{invalid operands to binary expression}} - (void)(u16 <= f64); // expected-error{{invalid operands to binary expression}} - - (void)(i32 <= b); // expected-error{{invalid operands to binary expression}} - (void)(i32 <= i8); // expected-error{{invalid operands to binary expression}} - (void)(i32 <= i16); // expected-error{{invalid operands to binary expression}} - (void)(i32 <= i64); // expected-error{{invalid operands to binary expression}} - (void)(i32 <= u8); // expected-error{{invalid operands to binary expression}} - (void)(i32 <= u16); // expected-error{{invalid operands to binary expression}} - (void)(i32 <= u64); // expected-error{{invalid operands to binary expression}} - (void)(i32 <= f16); // expected-error{{invalid operands to binary expression}} - (void)(i32 <= f32); // expected-error{{invalid operands to binary expression}} - (void)(i32 <= f64); // expected-error{{invalid operands to binary expression}} - - (void)(u32 <= b); // expected-error{{invalid operands to binary expression}} - (void)(u32 <= i8); // expected-error{{invalid operands to binary expression}} - (void)(u32 <= i16); // expected-error{{invalid operands to binary expression}} - (void)(u32 <= i64); // expected-error{{invalid operands to binary expression}} - (void)(u32 <= u8); // expected-error{{invalid operands to binary expression}} - (void)(u32 <= u16); // expected-error{{invalid operands to binary expression}} - (void)(u32 <= u64); // expected-error{{invalid operands to binary expression}} - (void)(u32 <= f16); // expected-error{{invalid operands to binary expression}} - (void)(u32 <= f32); // expected-error{{invalid operands to binary expression}} - (void)(u32 <= f64); // expected-error{{invalid operands to binary expression}} - - (void)(i64 <= b); // expected-error{{invalid operands to binary expression}} - (void)(i64 <= i8); // expected-error{{invalid operands to binary expression}} - (void)(i64 <= i16); // expected-error{{invalid operands to binary expression}} - (void)(i64 <= i32); // expected-error{{invalid operands to binary expression}} - (void)(i64 <= u8); // expected-error{{invalid operands to binary expression}} - (void)(i64 <= u16); // expected-error{{invalid operands to binary expression}} - (void)(i64 <= u32); // expected-error{{invalid operands to binary expression}} - (void)(i64 <= f16); // expected-error{{invalid operands to binary expression}} - (void)(i64 <= f32); // expected-error{{invalid operands to binary expression}} - (void)(i64 <= f64); // expected-error{{invalid operands to binary expression}} - - (void)(u64 <= b); // expected-error{{invalid operands to binary expression}} - (void)(u64 <= i8); // expected-error{{invalid operands to binary expression}} - (void)(u64 <= i16); // expected-error{{invalid operands to binary expression}} - (void)(u64 <= i32); // expected-error{{invalid operands to binary expression}} - (void)(u64 <= u8); // expected-error{{invalid operands to binary expression}} - (void)(u64 <= u16); // expected-error{{invalid operands to binary expression}} - (void)(u64 <= u32); // expected-error{{invalid operands to binary expression}} - (void)(u64 <= f16); // expected-error{{invalid operands to binary expression}} - (void)(u64 <= f32); // expected-error{{invalid operands to binary expression}} - (void)(u64 <= f64); // expected-error{{invalid operands to binary expression}} - - (void)(f16 <= b); // expected-error{{invalid operands to binary expression}} - (void)(f16 <= i8); // expected-error{{invalid operands to binary expression}} - (void)(f16 <= i16); // expected-error{{invalid operands to binary expression}} - (void)(f16 <= i32); // expected-error{{invalid operands to binary expression}} - (void)(f16 <= i64); // expected-error{{invalid operands to binary expression}} - (void)(f16 <= u8); // expected-error{{invalid operands to binary expression}} - (void)(f16 <= u32); // expected-error{{invalid operands to binary expression}} - (void)(f16 <= u64); // expected-error{{invalid operands to binary expression}} - (void)(f16 <= f32); // expected-error{{invalid operands to binary expression}} - (void)(f16 <= f64); // expected-error{{invalid operands to binary expression}} - - (void)(f32 <= b); // expected-error{{invalid operands to binary expression}} - (void)(f32 <= i8); // expected-error{{invalid operands to binary expression}} - (void)(f32 <= i16); // expected-error{{invalid operands to binary expression}} - (void)(f32 <= i32); // expected-error{{invalid operands to binary expression}} - (void)(f32 <= i64); // expected-error{{invalid operands to binary expression}} - (void)(f32 <= u8); // expected-error{{invalid operands to binary expression}} - (void)(f32 <= u16); // expected-error{{invalid operands to binary expression}} - (void)(f32 <= u64); // expected-error{{invalid operands to binary expression}} - (void)(f32 <= f16); // expected-error{{invalid operands to binary expression}} - (void)(f32 <= f64); // expected-error{{invalid operands to binary expression}} - - (void)(f64 <= b); // expected-error{{invalid operands to binary expression}} - (void)(f64 <= i8); // expected-error{{invalid operands to binary expression}} - (void)(f64 <= i16); // expected-error{{invalid operands to binary expression}} - (void)(f64 <= i32); // expected-error{{invalid operands to binary expression}} - (void)(f64 <= i64); // expected-error{{invalid operands to binary expression}} - (void)(f64 <= u8); // expected-error{{invalid operands to binary expression}} - (void)(f64 <= u16); // expected-error{{invalid operands to binary expression}} - (void)(f64 <= u32); // expected-error{{invalid operands to binary expression}} - (void)(f64 <= f16); // expected-error{{invalid operands to binary expression}} - (void)(f64 <= f32); // expected-error{{invalid operands to binary expression}} + (void)(i8 <= b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svint8_t' (aka '__SVInt8_t') as implicit conversion would cause truncation}} + (void)(i8 <= i16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i8 <= i32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i8 <= i64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i8 <= u16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i8 <= u32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i8 <= u64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i8 <= f16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i8 <= f32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i8 <= f64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u8 <= b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svuint8_t' (aka '__SVUint8_t') as implicit conversion would cause truncation}} + (void)(u8 <= i16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u8 <= i32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u8 <= i64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u8 <= u16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u8 <= u32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u8 <= u64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u8 <= f16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u8 <= f32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u8 <= f64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i16 <= b); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i16 <= i8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i16 <= i32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i16 <= i64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i16 <= u8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i16 <= u32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i16 <= u64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i16 <= f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svint16_t' (aka '__SVInt16_t') as implicit conversion would cause truncation}} + (void)(i16 <= f32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i16 <= f64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u16 <= b); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u16 <= i8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u16 <= i32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u16 <= i64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u16 <= u8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u16 <= u32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u16 <= u64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u16 <= f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svuint16_t' (aka '__SVUint16_t') as implicit conversion would cause truncation}} + (void)(u16 <= f32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u16 <= f64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i32 <= b); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i32 <= i8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i32 <= i16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i32 <= i64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i32 <= u8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i32 <= u16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i32 <= u64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i32 <= f16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i32 <= f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svint32_t' (aka '__SVInt32_t') as implicit conversion would cause truncation}} + (void)(i32 <= f64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u32 <= b); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u32 <= i8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u32 <= i16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u32 <= i64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u32 <= u8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u32 <= u16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u32 <= u64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u32 <= f16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u32 <= f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svuint32_t' (aka '__SVUint32_t') as implicit conversion would cause truncation}} + (void)(u32 <= f64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i64 <= b); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i64 <= i8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i64 <= i16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i64 <= i32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i64 <= u8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i64 <= u16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i64 <= u32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i64 <= f16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i64 <= f32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i64 <= f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svint64_t' (aka '__SVInt64_t') as implicit conversion would cause truncation}} + + (void)(u64 <= b); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u64 <= i8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u64 <= i16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u64 <= i32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u64 <= u8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u64 <= u16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u64 <= u32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u64 <= f16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u64 <= f32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u64 <= f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svuint64_t' (aka '__SVUint64_t') as implicit conversion would cause truncation}} + + (void)(f16 <= b); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f16 <= i8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f16 <= i16); // expected-error{{cannot convert between vector type 'svint16_t' (aka '__SVInt16_t') and vector type 'svfloat16_t' (aka '__SVFloat16_t') as implicit conversion would cause truncation}} + (void)(f16 <= i32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f16 <= i64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f16 <= u8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f16 <= u32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f16 <= u64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f16 <= f32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(f16 <= f64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(f32 <= b); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f32 <= i8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f32 <= i16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f32 <= i32); // expected-error{{cannot convert between vector type 'svint32_t' (aka '__SVInt32_t') and vector type 'svfloat32_t' (aka '__SVFloat32_t') as implicit conversion would cause truncation}} + (void)(f32 <= i64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f32 <= u8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f32 <= u16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f32 <= u64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f32 <= f16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f32 <= f64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(f64 <= b); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f64 <= i8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f64 <= i16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f64 <= i32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f64 <= i64); // expected-error{{cannot convert between vector type 'svint64_t' (aka '__SVInt64_t') and vector type 'svfloat64_t' (aka '__SVFloat64_t') as implicit conversion would cause truncation}} + (void)(f64 <= u8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f64 <= u16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f64 <= u32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f64 <= f16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f64 <= f32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} } void gt(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, svbool_t b) { - (void)(i8 > b); // expected-error{{invalid operands to binary expression}} - (void)(i8 > i16); // expected-error{{invalid operands to binary expression}} - (void)(i8 > i32); // expected-error{{invalid operands to binary expression}} - (void)(i8 > i64); // expected-error{{invalid operands to binary expression}} - (void)(i8 > u16); // expected-error{{invalid operands to binary expression}} - (void)(i8 > u32); // expected-error{{invalid operands to binary expression}} - (void)(i8 > u64); // expected-error{{invalid operands to binary expression}} - (void)(i8 > f16); // expected-error{{invalid operands to binary expression}} - (void)(i8 > f32); // expected-error{{invalid operands to binary expression}} - (void)(i8 > f64); // expected-error{{invalid operands to binary expression}} - - (void)(u8 > b); // expected-error{{invalid operands to binary expression}} - (void)(u8 > i16); // expected-error{{invalid operands to binary expression}} - (void)(u8 > i32); // expected-error{{invalid operands to binary expression}} - (void)(u8 > i64); // expected-error{{invalid operands to binary expression}} - (void)(u8 > u16); // expected-error{{invalid operands to binary expression}} - (void)(u8 > u32); // expected-error{{invalid operands to binary expression}} - (void)(u8 > u64); // expected-error{{invalid operands to binary expression}} - (void)(u8 > f16); // expected-error{{invalid operands to binary expression}} - (void)(u8 > f32); // expected-error{{invalid operands to binary expression}} - (void)(u8 > f64); // expected-error{{invalid operands to binary expression}} - - (void)(i16 > b); // expected-error{{invalid operands to binary expression}} - (void)(i16 > i8); // expected-error{{invalid operands to binary expression}} - (void)(i16 > i32); // expected-error{{invalid operands to binary expression}} - (void)(i16 > i64); // expected-error{{invalid operands to binary expression}} - (void)(i16 > u8); // expected-error{{invalid operands to binary expression}} - (void)(i16 > u32); // expected-error{{invalid operands to binary expression}} - (void)(i16 > u64); // expected-error{{invalid operands to binary expression}} - (void)(i16 > f16); // expected-error{{invalid operands to binary expression}} - (void)(i16 > f32); // expected-error{{invalid operands to binary expression}} - (void)(i16 > f64); // expected-error{{invalid operands to binary expression}} - - (void)(u16 > b); // expected-error{{invalid operands to binary expression}} - (void)(u16 > i8); // expected-error{{invalid operands to binary expression}} - (void)(u16 > i32); // expected-error{{invalid operands to binary expression}} - (void)(u16 > i64); // expected-error{{invalid operands to binary expression}} - (void)(u16 > u8); // expected-error{{invalid operands to binary expression}} - (void)(u16 > u32); // expected-error{{invalid operands to binary expression}} - (void)(u16 > u64); // expected-error{{invalid operands to binary expression}} - (void)(u16 > f16); // expected-error{{invalid operands to binary expression}} - (void)(u16 > f32); // expected-error{{invalid operands to binary expression}} - (void)(u16 > f64); // expected-error{{invalid operands to binary expression}} - - (void)(i32 > b); // expected-error{{invalid operands to binary expression}} - (void)(i32 > i8); // expected-error{{invalid operands to binary expression}} - (void)(i32 > i16); // expected-error{{invalid operands to binary expression}} - (void)(i32 > i64); // expected-error{{invalid operands to binary expression}} - (void)(i32 > u8); // expected-error{{invalid operands to binary expression}} - (void)(i32 > u16); // expected-error{{invalid operands to binary expression}} - (void)(i32 > u64); // expected-error{{invalid operands to binary expression}} - (void)(i32 > f16); // expected-error{{invalid operands to binary expression}} - (void)(i32 > f32); // expected-error{{invalid operands to binary expression}} - (void)(i32 > f64); // expected-error{{invalid operands to binary expression}} - - (void)(u32 > b); // expected-error{{invalid operands to binary expression}} - (void)(u32 > i8); // expected-error{{invalid operands to binary expression}} - (void)(u32 > i16); // expected-error{{invalid operands to binary expression}} - (void)(u32 > i64); // expected-error{{invalid operands to binary expression}} - (void)(u32 > u8); // expected-error{{invalid operands to binary expression}} - (void)(u32 > u16); // expected-error{{invalid operands to binary expression}} - (void)(u32 > u64); // expected-error{{invalid operands to binary expression}} - (void)(u32 > f16); // expected-error{{invalid operands to binary expression}} - (void)(u32 > f32); // expected-error{{invalid operands to binary expression}} - (void)(u32 > f64); // expected-error{{invalid operands to binary expression}} - - (void)(i64 > b); // expected-error{{invalid operands to binary expression}} - (void)(i64 > i8); // expected-error{{invalid operands to binary expression}} - (void)(i64 > i16); // expected-error{{invalid operands to binary expression}} - (void)(i64 > i32); // expected-error{{invalid operands to binary expression}} - (void)(i64 > u8); // expected-error{{invalid operands to binary expression}} - (void)(i64 > u16); // expected-error{{invalid operands to binary expression}} - (void)(i64 > u32); // expected-error{{invalid operands to binary expression}} - (void)(i64 > f16); // expected-error{{invalid operands to binary expression}} - (void)(i64 > f32); // expected-error{{invalid operands to binary expression}} - (void)(i64 > f64); // expected-error{{invalid operands to binary expression}} - - (void)(u64 > b); // expected-error{{invalid operands to binary expression}} - (void)(u64 > i8); // expected-error{{invalid operands to binary expression}} - (void)(u64 > i16); // expected-error{{invalid operands to binary expression}} - (void)(u64 > i32); // expected-error{{invalid operands to binary expression}} - (void)(u64 > u8); // expected-error{{invalid operands to binary expression}} - (void)(u64 > u16); // expected-error{{invalid operands to binary expression}} - (void)(u64 > u32); // expected-error{{invalid operands to binary expression}} - (void)(u64 > f16); // expected-error{{invalid operands to binary expression}} - (void)(u64 > f32); // expected-error{{invalid operands to binary expression}} - (void)(u64 > f64); // expected-error{{invalid operands to binary expression}} - - (void)(f16 > b); // expected-error{{invalid operands to binary expression}} - (void)(f16 > i8); // expected-error{{invalid operands to binary expression}} - (void)(f16 > i16); // expected-error{{invalid operands to binary expression}} - (void)(f16 > i32); // expected-error{{invalid operands to binary expression}} - (void)(f16 > i64); // expected-error{{invalid operands to binary expression}} - (void)(f16 > u8); // expected-error{{invalid operands to binary expression}} - (void)(f16 > u32); // expected-error{{invalid operands to binary expression}} - (void)(f16 > u64); // expected-error{{invalid operands to binary expression}} - (void)(f16 > f32); // expected-error{{invalid operands to binary expression}} - (void)(f16 > f64); // expected-error{{invalid operands to binary expression}} - - (void)(f32 > b); // expected-error{{invalid operands to binary expression}} - (void)(f32 > i8); // expected-error{{invalid operands to binary expression}} - (void)(f32 > i16); // expected-error{{invalid operands to binary expression}} - (void)(f32 > i32); // expected-error{{invalid operands to binary expression}} - (void)(f32 > i64); // expected-error{{invalid operands to binary expression}} - (void)(f32 > u8); // expected-error{{invalid operands to binary expression}} - (void)(f32 > u16); // expected-error{{invalid operands to binary expression}} - (void)(f32 > u64); // expected-error{{invalid operands to binary expression}} - (void)(f32 > f16); // expected-error{{invalid operands to binary expression}} - (void)(f32 > f64); // expected-error{{invalid operands to binary expression}} - - (void)(f64 > b); // expected-error{{invalid operands to binary expression}} - (void)(f64 > i8); // expected-error{{invalid operands to binary expression}} - (void)(f64 > i16); // expected-error{{invalid operands to binary expression}} - (void)(f64 > i32); // expected-error{{invalid operands to binary expression}} - (void)(f64 > i64); // expected-error{{invalid operands to binary expression}} - (void)(f64 > u8); // expected-error{{invalid operands to binary expression}} - (void)(f64 > u16); // expected-error{{invalid operands to binary expression}} - (void)(f64 > u32); // expected-error{{invalid operands to binary expression}} - (void)(f64 > f16); // expected-error{{invalid operands to binary expression}} - (void)(f64 > f32); // expected-error{{invalid operands to binary expression}} + (void)(i8 > b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svint8_t' (aka '__SVInt8_t') as implicit conversion would cause truncation}} + (void)(i8 > i16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i8 > i32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i8 > i64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i8 > u16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i8 > u32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i8 > u64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i8 > f16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i8 > f32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i8 > f64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u8 > b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svuint8_t' (aka '__SVUint8_t') as implicit conversion would cause truncation}} + (void)(u8 > i16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u8 > i32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u8 > i64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u8 > u16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u8 > u32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u8 > u64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u8 > f16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u8 > f32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u8 > f64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i16 > b); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i16 > i8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i16 > i32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i16 > i64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i16 > u8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i16 > u32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i16 > u64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i16 > f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svint16_t' (aka '__SVInt16_t') as implicit conversion would cause truncation}} + (void)(i16 > f32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i16 > f64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u16 > b); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u16 > i8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u16 > i32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u16 > i64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u16 > u8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u16 > u32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u16 > u64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u16 > f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svuint16_t' (aka '__SVUint16_t') as implicit conversion would cause truncation}} + (void)(u16 > f32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u16 > f64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i32 > b); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i32 > i8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i32 > i16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i32 > i64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i32 > u8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i32 > u16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i32 > u64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i32 > f16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i32 > f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svint32_t' (aka '__SVInt32_t') as implicit conversion would cause truncation}} + (void)(i32 > f64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u32 > b); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u32 > i8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u32 > i16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u32 > i64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u32 > u8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u32 > u16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u32 > u64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u32 > f16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u32 > f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svuint32_t' (aka '__SVUint32_t') as implicit conversion would cause truncation}} + (void)(u32 > f64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i64 > b); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i64 > i8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i64 > i16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i64 > i32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i64 > u8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i64 > u16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i64 > u32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i64 > f16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i64 > f32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i64 > f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svint64_t' (aka '__SVInt64_t') as implicit conversion would cause truncation}} + + (void)(u64 > b); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u64 > i8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u64 > i16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u64 > i32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u64 > u8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u64 > u16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u64 > u32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u64 > f16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u64 > f32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u64 > f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svuint64_t' (aka '__SVUint64_t') as implicit conversion would cause truncation}} + + (void)(f16 > b); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f16 > i8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f16 > i16); // expected-error{{cannot convert between vector type 'svint16_t' (aka '__SVInt16_t') and vector type 'svfloat16_t' (aka '__SVFloat16_t') as implicit conversion would cause truncation}} + (void)(f16 > i32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f16 > i64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f16 > u8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f16 > u32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f16 > u64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f16 > f32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(f16 > f64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(f32 > b); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f32 > i8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f32 > i16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f32 > i32); // expected-error{{cannot convert between vector type 'svint32_t' (aka '__SVInt32_t') and vector type 'svfloat32_t' (aka '__SVFloat32_t') as implicit conversion would cause truncation}} + (void)(f32 > i64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f32 > u8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f32 > u16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f32 > u64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f32 > f16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f32 > f64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(f64 > b); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f64 > i8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f64 > i16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f64 > i32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f64 > i64); // expected-error{{cannot convert between vector type 'svint64_t' (aka '__SVInt64_t') and vector type 'svfloat64_t' (aka '__SVFloat64_t') as implicit conversion would cause truncation}} + (void)(f64 > u8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f64 > u16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f64 > u32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f64 > f16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f64 > f32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} } void geq(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, svbool_t b) { - (void)(i8 >= b); // expected-error{{invalid operands to binary expression}} - (void)(i8 >= i16); // expected-error{{invalid operands to binary expression}} - (void)(i8 >= i32); // expected-error{{invalid operands to binary expression}} - (void)(i8 >= i64); // expected-error{{invalid operands to binary expression}} - (void)(i8 >= u16); // expected-error{{invalid operands to binary expression}} - (void)(i8 >= u32); // expected-error{{invalid operands to binary expression}} - (void)(i8 >= u64); // expected-error{{invalid operands to binary expression}} - (void)(i8 >= f16); // expected-error{{invalid operands to binary expression}} - (void)(i8 >= f32); // expected-error{{invalid operands to binary expression}} - (void)(i8 >= f64); // expected-error{{invalid operands to binary expression}} - - (void)(u8 >= b); // expected-error{{invalid operands to binary expression}} - (void)(u8 >= i16); // expected-error{{invalid operands to binary expression}} - (void)(u8 >= i32); // expected-error{{invalid operands to binary expression}} - (void)(u8 >= i64); // expected-error{{invalid operands to binary expression}} - (void)(u8 >= u16); // expected-error{{invalid operands to binary expression}} - (void)(u8 >= u32); // expected-error{{invalid operands to binary expression}} - (void)(u8 >= u64); // expected-error{{invalid operands to binary expression}} - (void)(u8 >= f16); // expected-error{{invalid operands to binary expression}} - (void)(u8 >= f32); // expected-error{{invalid operands to binary expression}} - (void)(u8 >= f64); // expected-error{{invalid operands to binary expression}} - - (void)(i16 >= b); // expected-error{{invalid operands to binary expression}} - (void)(i16 >= i8); // expected-error{{invalid operands to binary expression}} - (void)(i16 >= i32); // expected-error{{invalid operands to binary expression}} - (void)(i16 >= i64); // expected-error{{invalid operands to binary expression}} - (void)(i16 >= u8); // expected-error{{invalid operands to binary expression}} - (void)(i16 >= u32); // expected-error{{invalid operands to binary expression}} - (void)(i16 >= u64); // expected-error{{invalid operands to binary expression}} - (void)(i16 >= f16); // expected-error{{invalid operands to binary expression}} - (void)(i16 >= f32); // expected-error{{invalid operands to binary expression}} - (void)(i16 >= f64); // expected-error{{invalid operands to binary expression}} - - (void)(u16 >= b); // expected-error{{invalid operands to binary expression}} - (void)(u16 >= i8); // expected-error{{invalid operands to binary expression}} - (void)(u16 >= i32); // expected-error{{invalid operands to binary expression}} - (void)(u16 >= i64); // expected-error{{invalid operands to binary expression}} - (void)(u16 >= u8); // expected-error{{invalid operands to binary expression}} - (void)(u16 >= u32); // expected-error{{invalid operands to binary expression}} - (void)(u16 >= u64); // expected-error{{invalid operands to binary expression}} - (void)(u16 >= f16); // expected-error{{invalid operands to binary expression}} - (void)(u16 >= f32); // expected-error{{invalid operands to binary expression}} - (void)(u16 >= f64); // expected-error{{invalid operands to binary expression}} - - (void)(i32 >= b); // expected-error{{invalid operands to binary expression}} - (void)(i32 >= i8); // expected-error{{invalid operands to binary expression}} - (void)(i32 >= i16); // expected-error{{invalid operands to binary expression}} - (void)(i32 >= i64); // expected-error{{invalid operands to binary expression}} - (void)(i32 >= u8); // expected-error{{invalid operands to binary expression}} - (void)(i32 >= u16); // expected-error{{invalid operands to binary expression}} - (void)(i32 >= u64); // expected-error{{invalid operands to binary expression}} - (void)(i32 >= f16); // expected-error{{invalid operands to binary expression}} - (void)(i32 >= f32); // expected-error{{invalid operands to binary expression}} - (void)(i32 >= f64); // expected-error{{invalid operands to binary expression}} - - (void)(u32 >= b); // expected-error{{invalid operands to binary expression}} - (void)(u32 >= i8); // expected-error{{invalid operands to binary expression}} - (void)(u32 >= i16); // expected-error{{invalid operands to binary expression}} - (void)(u32 >= i64); // expected-error{{invalid operands to binary expression}} - (void)(u32 >= u8); // expected-error{{invalid operands to binary expression}} - (void)(u32 >= u16); // expected-error{{invalid operands to binary expression}} - (void)(u32 >= u64); // expected-error{{invalid operands to binary expression}} - (void)(u32 >= f16); // expected-error{{invalid operands to binary expression}} - (void)(u32 >= f32); // expected-error{{invalid operands to binary expression}} - (void)(u32 >= f64); // expected-error{{invalid operands to binary expression}} - - (void)(i64 >= b); // expected-error{{invalid operands to binary expression}} - (void)(i64 >= i8); // expected-error{{invalid operands to binary expression}} - (void)(i64 >= i16); // expected-error{{invalid operands to binary expression}} - (void)(i64 >= i32); // expected-error{{invalid operands to binary expression}} - (void)(i64 >= u8); // expected-error{{invalid operands to binary expression}} - (void)(i64 >= u16); // expected-error{{invalid operands to binary expression}} - (void)(i64 >= u32); // expected-error{{invalid operands to binary expression}} - (void)(i64 >= f16); // expected-error{{invalid operands to binary expression}} - (void)(i64 >= f32); // expected-error{{invalid operands to binary expression}} - (void)(i64 >= f64); // expected-error{{invalid operands to binary expression}} - - (void)(u64 >= b); // expected-error{{invalid operands to binary expression}} - (void)(u64 >= i8); // expected-error{{invalid operands to binary expression}} - (void)(u64 >= i16); // expected-error{{invalid operands to binary expression}} - (void)(u64 >= i32); // expected-error{{invalid operands to binary expression}} - (void)(u64 >= u8); // expected-error{{invalid operands to binary expression}} - (void)(u64 >= u16); // expected-error{{invalid operands to binary expression}} - (void)(u64 >= u32); // expected-error{{invalid operands to binary expression}} - (void)(u64 >= f16); // expected-error{{invalid operands to binary expression}} - (void)(u64 >= f32); // expected-error{{invalid operands to binary expression}} - (void)(u64 >= f64); // expected-error{{invalid operands to binary expression}} - - (void)(f16 >= b); // expected-error{{invalid operands to binary expression}} - (void)(f16 >= i8); // expected-error{{invalid operands to binary expression}} - (void)(f16 >= i16); // expected-error{{invalid operands to binary expression}} - (void)(f16 >= i32); // expected-error{{invalid operands to binary expression}} - (void)(f16 >= i64); // expected-error{{invalid operands to binary expression}} - (void)(f16 >= u8); // expected-error{{invalid operands to binary expression}} - (void)(f16 >= u32); // expected-error{{invalid operands to binary expression}} - (void)(f16 >= u64); // expected-error{{invalid operands to binary expression}} - (void)(f16 >= f32); // expected-error{{invalid operands to binary expression}} - (void)(f16 >= f64); // expected-error{{invalid operands to binary expression}} - - (void)(f32 >= b); // expected-error{{invalid operands to binary expression}} - (void)(f32 >= i8); // expected-error{{invalid operands to binary expression}} - (void)(f32 >= i16); // expected-error{{invalid operands to binary expression}} - (void)(f32 >= i32); // expected-error{{invalid operands to binary expression}} - (void)(f32 >= i64); // expected-error{{invalid operands to binary expression}} - (void)(f32 >= u8); // expected-error{{invalid operands to binary expression}} - (void)(f32 >= u16); // expected-error{{invalid operands to binary expression}} - (void)(f32 >= u64); // expected-error{{invalid operands to binary expression}} - (void)(f32 >= f16); // expected-error{{invalid operands to binary expression}} - (void)(f32 >= f64); // expected-error{{invalid operands to binary expression}} - - (void)(f64 >= b); // expected-error{{invalid operands to binary expression}} - (void)(f64 >= i8); // expected-error{{invalid operands to binary expression}} - (void)(f64 >= i16); // expected-error{{invalid operands to binary expression}} - (void)(f64 >= i32); // expected-error{{invalid operands to binary expression}} - (void)(f64 >= i64); // expected-error{{invalid operands to binary expression}} - (void)(f64 >= u8); // expected-error{{invalid operands to binary expression}} - (void)(f64 >= u16); // expected-error{{invalid operands to binary expression}} - (void)(f64 >= u32); // expected-error{{invalid operands to binary expression}} - (void)(f64 >= f16); // expected-error{{invalid operands to binary expression}} - (void)(f64 >= f32); // expected-error{{invalid operands to binary expression}} + (void)(i8 >= b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svint8_t' (aka '__SVInt8_t') as implicit conversion would cause truncation}} + (void)(i8 >= i16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i8 >= i32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i8 >= i64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i8 >= u16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i8 >= u32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i8 >= u64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i8 >= f16); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i8 >= f32); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i8 >= f64); // expected-error{{vector operands do not have the same number of elements ('svint8_t' (aka '__SVInt8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u8 >= b); // expected-error{{cannot convert between vector type 'svbool_t' (aka '__SVBool_t') and vector type 'svuint8_t' (aka '__SVUint8_t') as implicit conversion would cause truncation}} + (void)(u8 >= i16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u8 >= i32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u8 >= i64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u8 >= u16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u8 >= u32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u8 >= u64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u8 >= f16); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u8 >= f32); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u8 >= f64); // expected-error{{vector operands do not have the same number of elements ('svuint8_t' (aka '__SVUint8_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i16 >= b); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i16 >= i8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i16 >= i32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i16 >= i64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i16 >= u8); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i16 >= u32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i16 >= u64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i16 >= f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svint16_t' (aka '__SVInt16_t') as implicit conversion would cause truncation}} + (void)(i16 >= f32); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i16 >= f64); // expected-error{{vector operands do not have the same number of elements ('svint16_t' (aka '__SVInt16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u16 >= b); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u16 >= i8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u16 >= i32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u16 >= i64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u16 >= u8); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u16 >= u32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u16 >= u64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u16 >= f16); // expected-error{{cannot convert between vector type 'svfloat16_t' (aka '__SVFloat16_t') and vector type 'svuint16_t' (aka '__SVUint16_t') as implicit conversion would cause truncation}} + (void)(u16 >= f32); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u16 >= f64); // expected-error{{vector operands do not have the same number of elements ('svuint16_t' (aka '__SVUint16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i32 >= b); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i32 >= i8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i32 >= i16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i32 >= i64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(i32 >= u8); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i32 >= u16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i32 >= u64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(i32 >= f16); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i32 >= f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svint32_t' (aka '__SVInt32_t') as implicit conversion would cause truncation}} + (void)(i32 >= f64); // expected-error{{vector operands do not have the same number of elements ('svint32_t' (aka '__SVInt32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(u32 >= b); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u32 >= i8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u32 >= i16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u32 >= i64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(u32 >= u8); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u32 >= u16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u32 >= u64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(u32 >= f16); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u32 >= f32); // expected-error{{cannot convert between vector type 'svfloat32_t' (aka '__SVFloat32_t') and vector type 'svuint32_t' (aka '__SVUint32_t') as implicit conversion would cause truncation}} + (void)(u32 >= f64); // expected-error{{vector operands do not have the same number of elements ('svuint32_t' (aka '__SVUint32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(i64 >= b); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(i64 >= i8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(i64 >= i16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(i64 >= i32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(i64 >= u8); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(i64 >= u16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(i64 >= u32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(i64 >= f16); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(i64 >= f32); // expected-error{{vector operands do not have the same number of elements ('svint64_t' (aka '__SVInt64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(i64 >= f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svint64_t' (aka '__SVInt64_t') as implicit conversion would cause truncation}} + + (void)(u64 >= b); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(u64 >= i8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(u64 >= i16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(u64 >= i32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(u64 >= u8); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(u64 >= u16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(u64 >= u32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(u64 >= f16); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(u64 >= f32); // expected-error{{vector operands do not have the same number of elements ('svuint64_t' (aka '__SVUint64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(u64 >= f64); // expected-error{{cannot convert between vector type 'svfloat64_t' (aka '__SVFloat64_t') and vector type 'svuint64_t' (aka '__SVUint64_t') as implicit conversion would cause truncation}} + + (void)(f16 >= b); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f16 >= i8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f16 >= i16); // expected-error{{cannot convert between vector type 'svint16_t' (aka '__SVInt16_t') and vector type 'svfloat16_t' (aka '__SVFloat16_t') as implicit conversion would cause truncation}} + (void)(f16 >= i32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f16 >= i64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f16 >= u8); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f16 >= u32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f16 >= u64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f16 >= f32); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} + (void)(f16 >= f64); // expected-error{{vector operands do not have the same number of elements ('svfloat16_t' (aka '__SVFloat16_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(f32 >= b); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f32 >= i8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f32 >= i16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f32 >= i32); // expected-error{{cannot convert between vector type 'svint32_t' (aka '__SVInt32_t') and vector type 'svfloat32_t' (aka '__SVFloat32_t') as implicit conversion would cause truncation}} + (void)(f32 >= i64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svint64_t' (aka '__SVInt64_t'))}} + (void)(f32 >= u8); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f32 >= u16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f32 >= u64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svuint64_t' (aka '__SVUint64_t'))}} + (void)(f32 >= f16); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f32 >= f64); // expected-error{{vector operands do not have the same number of elements ('svfloat32_t' (aka '__SVFloat32_t') and 'svfloat64_t' (aka '__SVFloat64_t'))}} + + (void)(f64 >= b); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svbool_t' (aka '__SVBool_t'))}} + (void)(f64 >= i8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint8_t' (aka '__SVInt8_t'))}} + (void)(f64 >= i16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint16_t' (aka '__SVInt16_t'))}} + (void)(f64 >= i32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svint32_t' (aka '__SVInt32_t'))}} + (void)(f64 >= i64); // expected-error{{cannot convert between vector type 'svint64_t' (aka '__SVInt64_t') and vector type 'svfloat64_t' (aka '__SVFloat64_t') as implicit conversion would cause truncation}} + (void)(f64 >= u8); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint8_t' (aka '__SVUint8_t'))}} + (void)(f64 >= u16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint16_t' (aka '__SVUint16_t'))}} + (void)(f64 >= u32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svuint32_t' (aka '__SVUint32_t'))}} + (void)(f64 >= f16); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat16_t' (aka '__SVFloat16_t'))}} + (void)(f64 >= f32); // expected-error{{vector operands do not have the same number of elements ('svfloat64_t' (aka '__SVFloat64_t') and 'svfloat32_t' (aka '__SVFloat32_t'))}} } diff --git a/clang/test/Sema/annotate-type.c b/clang/test/Sema/annotate-type.c new file mode 100644 index 0000000000000..266e13885389c --- /dev/null +++ b/clang/test/Sema/annotate-type.c @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 %s -fsyntax-only -fdouble-square-bracket-attributes -verify + +const char *some_function(); + +void foo(float *[[clang::annotate_type("foo")]] a) { + int [[clang::annotate_type("bar")]] x1; + int *[[clang::annotate_type("bar")]] x2; + int *[[clang::annotate_type("bar", 1)]] x3; + int *[[clang::annotate_type("bar", 1 + 2)]] x4; + struct {} [[clang::annotate_type("foo")]] x5; + int [[clang::annotate_type("int")]] *[[clang::annotate_type("ptr")]] array[10] [[clang::annotate_type("arr")]]; + + typedef int [[clang::annotate_type("bar")]] my_typedef; + + // GNU spelling is not supported + int __attribute__((annotate_type("bar"))) y1; // expected-warning {{unknown attribute 'annotate_type' ignored}} + int *__attribute__((annotate_type("bar"))) y2; // expected-warning {{unknown attribute 'annotate_type' ignored}} + + // Various error cases + [[clang::annotate_type("bar")]] int *z1; // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} + int *z2 [[clang::annotate_type("bar")]]; // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} + [[clang::annotate_type("bar")]]; // expected-error {{'annotate_type' attribute cannot be applied to a statement}} + int *[[clang::annotate_type(1)]] z3; // expected-error {{'annotate_type' attribute requires a string}} + int *[[clang::annotate_type()]] z4; // expected-error {{'annotate_type' attribute takes at least 1 argument}} + int *[[clang::annotate_type]] z5; // expected-error {{'annotate_type' attribute takes at least 1 argument}} + int *[[clang::annotate_type(some_function())]] z6; // expected-error {{'annotate_type' attribute requires a string}} + int *[[clang::annotate_type("bar", some_function())]] z7; // expected-error {{'annotate_type' attribute requires parameter 1 to be a constant expression}} expected-note{{subexpression not valid in a constant expression}} + int *[[clang::annotate_type("bar", z7)]] z8; // expected-error {{'annotate_type' attribute requires parameter 1 to be a constant expression}} expected-note{{subexpression not valid in a constant expression}} + int *[[clang::annotate_type("bar", int)]] z9; // expected-error {{expected expression}} +} +// More error cases: Prohibit adding the attribute to declarations. +// Different declarations hit different code paths, so they need separate tests. +[[clang::annotate_type("bar")]] int *global; // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} +[[clang::annotate_type("bar")]] void annotated_function(); // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} +void g([[clang::annotate_type("bar")]] int); // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} +struct [[clang::annotate_type("foo")]] S; // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} +struct [[clang::annotate_type("foo")]] S{ // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} + [[clang::annotate_type("foo")]] int member; // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} + [[clang::annotate_type("foo")]] union { // expected-error {{an attribute list cannot appear here}} + int i; + float f; + }; +}; diff --git a/clang/test/Sema/attr-declspec-ignored.c b/clang/test/Sema/attr-declspec-ignored.c index 6fd35c0bd7835..7e5cebf5f45c5 100644 --- a/clang/test/Sema/attr-declspec-ignored.c +++ b/clang/test/Sema/attr-declspec-ignored.c @@ -7,6 +7,16 @@ __attribute__((visibility("hidden"))) __attribute__((aligned)) union B; // expe __attribute__((visibility("hidden"))) __attribute__((aligned)) enum C {C}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum" to apply attribute to type declaration}} \ // expected-warning{{attribute 'aligned' is ignored, place it after "enum" to apply attribute to type declaration}} +// Make sure that we produce the same warnings on block declarations. +void func() { + __attribute__((visibility("hidden"))) __attribute__((aligned)) struct A; // expected-warning{{attribute 'visibility' is ignored, place it after "struct" to apply attribute to type declaration}} \ + // expected-warning{{attribute 'aligned' is ignored, place it after "struct" to apply attribute to type declaration}} + __attribute__((visibility("hidden"))) __attribute__((aligned)) union B; // expected-warning{{attribute 'visibility' is ignored, place it after "union" to apply attribute to type declaration}} \ + // expected-warning{{attribute 'aligned' is ignored, place it after "union" to apply attribute to type declaration}} + __attribute__((visibility("hidden"))) __attribute__((aligned)) enum C {C}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum" to apply attribute to type declaration}} \ + // expected-warning{{attribute 'aligned' is ignored, place it after "enum" to apply attribute to type declaration}} +} + __attribute__((visibility("hidden"))) __attribute__((aligned)) struct D {} d; __attribute__((visibility("hidden"))) __attribute__((aligned)) union E {} e; __attribute__((visibility("hidden"))) __attribute__((aligned)) enum F {F} f; diff --git a/clang/test/Sema/attr-regparm.c b/clang/test/Sema/attr-regparm.c index d50dd113f70f9..c18367993d65e 100644 --- a/clang/test/Sema/attr-regparm.c +++ b/clang/test/Sema/attr-regparm.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -fdouble-square-bracket-attributes -verify %s __attribute((regparm(2))) int x0(void); __attribute((regparm(1.0))) int x1(void); // expected-error{{'regparm' attribute requires an integer constant}} @@ -9,3 +9,9 @@ __attribute((regparm(5,3))) int x4(void); // expected-error{{'regparm' attribute void __attribute__((regparm(3))) x5(int); void x5(int); // expected-note{{previous declaration is here}} void __attribute__((regparm(2))) x5(int); // expected-error{{function declared with regparm(2) attribute was previously declared with the regparm(3) attribute}} + +[[gnu::regparm(3)]] void x6(int); // expected-note{{previous declaration is here}} +[[gnu::regparm(2)]] void x6(int); // expected-error{{function declared with regparm(2) attribute was previously declared with the regparm(3) attribute}} +void x6 [[gnu::regparm(3)]] (int); +void [[gnu::regparm(3)]] x6(int); // expected-warning{{'regparm' only applies to function types; type here is 'void'}} +void x6(int) [[gnu::regparm(3)]]; // expected-warning{{GCC does not allow the 'regparm' attribute to be written on a type}} diff --git a/clang/test/Sema/block-call.c b/clang/test/Sema/block-call.c index 81071121b6adf..0b96c3bee5e33 100644 --- a/clang/test/Sema/block-call.c +++ b/clang/test/Sema/block-call.c @@ -22,7 +22,7 @@ int main(void) { int * const (^IPCC1) () = IPCC; - int * (^IPCC2) () = IPCC; // OK per WG14 DR 423 because the 'const' was dropped from the declarator. + int * (^IPCC2) () = IPCC; // expected-error {{incompatible block pointer types initializing 'int *(^)()' with an expression of type 'int *const (^)()'}} int (^IPCC3) (const int) = PFR; @@ -33,7 +33,7 @@ int main(void) { int (^IPCC6) (int, char (^CArg) (float)) = IPCC4; // expected-error {{incompatible block pointer types initializing 'int (^)(int, char (^)(float))' with an expression of type 'int (^)(int, char (^)(double))'}} IPCC2 = 0; - IPCC1 = 1; // expected-error {{invalid block pointer conversion assigning to 'int *(^)()' from 'int'}} + IPCC1 = 1; // expected-error {{invalid block pointer conversion assigning to 'int *const (^)()' from 'int'}} int (^x)() = 0; int (^y)() = 3; // expected-error {{invalid block pointer conversion initializing 'int (^)()' with an expression of type 'int'}} int a = 1; diff --git a/clang/test/Sema/builtins-memcpy-inline.cpp b/clang/test/Sema/builtins-memcpy-inline.cpp index ab0a8700a6c98..9d905a9335c4e 100644 --- a/clang/test/Sema/builtins-memcpy-inline.cpp +++ b/clang/test/Sema/builtins-memcpy-inline.cpp @@ -7,6 +7,10 @@ // expected-warning@-1 {{defined as expected}} #endif +void test_memcpy_inline_invalid_arg_types() { + __builtin_memcpy_inline(1, 2, 3); // expected-error {{cannot initialize a parameter of type 'void *' with an rvalue of type 'int'}} +} + void test_memcpy_inline_null_src(void *ptr) { __builtin_memcpy_inline(ptr, NULL, 4); // expected-warning {{null passed to a callee that requires a non-null argument}} } diff --git a/clang/test/Sema/builtins-memset-inline.cpp b/clang/test/Sema/builtins-memset-inline.cpp new file mode 100644 index 0000000000000..e445b3bcb3c25 --- /dev/null +++ b/clang/test/Sema/builtins-memset-inline.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +#define NULL ((char *)0) + +#if __has_builtin(__builtin_memset_inline) +#warning defined as expected +// expected-warning@-1 {{defined as expected}} +#endif + +void test_memset_inline_invalid_arg_types() { + __builtin_memset_inline(1, 2, 3); // expected-error {{cannot initialize a parameter of type 'void *' with an rvalue of type 'int'}} +} + +void test_memset_inline_null_dst(void *ptr) { + __builtin_memset_inline(NULL, 1, 4); // expected-warning {{null passed to a callee that requires a non-null argument}} +} + +void test_memset_inline_null_buffer_is_ok_if_size_is_zero(void *ptr, char value) { + __builtin_memset_inline(NULL, value, /*size */ 0); +} + +void test_memset_inline_non_constant_size(void *dst, char value, unsigned size) { + __builtin_memset_inline(dst, value, size); // expected-error {{argument to '__builtin_memset_inline' must be a constant integer}} +} + +template +void test_memset_inline_template(void *dst, char value) { + // we do not try to evaluate size in non intantiated templates. + __builtin_memset_inline(dst, value, size); +} + +void test_memset_inline_implicit_conversion(void *ptr, char value) { + char a[5]; + __builtin_memset_inline(a, value, 5); +} + +void test_memset_inline_num_args(void *dst, char value) { + __builtin_memset_inline(); // expected-error {{too few arguments to function call}} + __builtin_memset_inline(dst, value, 4, NULL); // expected-error {{too many arguments to function call}} +} diff --git a/clang/test/Sema/c2x-nodiscard.c b/clang/test/Sema/c2x-nodiscard.c index fb38e20d8d7aa..77b81a523833c 100644 --- a/clang/test/Sema/c2x-nodiscard.c +++ b/clang/test/Sema/c2x-nodiscard.c @@ -15,7 +15,7 @@ struct S3 get_s3(void); [[nodiscard]] int f1(void); enum [[nodiscard]] E1 { One }; -[[nodiscard]] int i; // expected-warning {{'nodiscard' attribute only applies to Objective-C methods, enums, structs, unions, classes, functions, and function pointers}} +[[nodiscard]] int i; // expected-warning {{'nodiscard' attribute only applies to Objective-C methods, enums, structs, unions, classes, functions, function pointers, and typedefs}} struct [[nodiscard]] S4 { int i; diff --git a/clang/test/Sema/c89.c b/clang/test/Sema/c89.c index 67b05eab24e43..0bbd14eca6b41 100644 --- a/clang/test/Sema/c89.c +++ b/clang/test/Sema/c89.c @@ -107,7 +107,7 @@ const array_of_pointer_to_CI mine3; void main(void) {} /* expected-error {{'main' must return 'int'}} */ -const int main(void) {} /* OK per DR 423 */ +const int main(void) {} /* expected-error {{'main' must return 'int'}} */ long long ll1 = /* expected-warning {{'long long' is an extension when C99 mode is not enabled}} */ -42LL; /* expected-warning {{'long long' is an extension when C99 mode is not enabled}} */ diff --git a/clang/test/Sema/format-strings-freebsd.c b/clang/test/Sema/format-strings-freebsd.c index 965d7c287be65..64b526eb2f076 100644 --- a/clang/test/Sema/format-strings-freebsd.c +++ b/clang/test/Sema/format-strings-freebsd.c @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify -triple i386-unknown-freebsd %s // RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-unknown-freebsd %s // RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-scei-ps4 %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-sie-ps5 %s // Test FreeBSD kernel printf extensions. int freebsd_kernel_printf(const char *, ...) __attribute__((__format__(__freebsd_kprintf__, 1, 2))); diff --git a/clang/test/Sema/function.c b/clang/test/Sema/function.c index c41e3a69d9e0d..b4ecc54559c7c 100644 --- a/clang/test/Sema/function.c +++ b/clang/test/Sema/function.c @@ -117,6 +117,6 @@ void t22(int *ptr, int (*array)[3]) { void const Bar (void); // ok on decl // PR 20146 -void const Bar (void) // also okay on defn per DR 423 +void const Bar (void) // expected-warning {{function cannot return qualified void type 'const void'}} { } diff --git a/clang/test/Sema/generic-selection.c b/clang/test/Sema/generic-selection.c index 0bd537c79d316..1f17896ca4cda 100644 --- a/clang/test/Sema/generic-selection.c +++ b/clang/test/Sema/generic-selection.c @@ -78,3 +78,11 @@ void unreachable_associations(const int i, const struct Test t) { default : 3 ) == 1, "we had better pick struct Test, not const struct Test!"); // C-specific result } + +void GH55562(void) { + // Ensure that you can still define a type within a generic selection + // association (despite it not being particularly useful). + (void)_Generic(1, struct S { int a; } : 0, default : 0); // ext-warning {{'_Generic' is a C11 extension}} + struct S s = { 0 }; + int i = s.a; +} diff --git a/clang/test/Sema/gnu-flags.c b/clang/test/Sema/gnu-flags.c index b454549ba9455..8389cb6055bc4 100644 --- a/clang/test/Sema/gnu-flags.c +++ b/clang/test/Sema/gnu-flags.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -DNONE -Wno-gnu -// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu +// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu // RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wno-gnu \ // RUN: -Wgnu-alignof-expression -Wgnu-case-range -Wgnu-complex-integer -Wgnu-conditional-omitted-operand \ // RUN: -Wgnu-empty-initializer -Wgnu-label-as-value -Wgnu-statement-expression \ @@ -20,6 +20,7 @@ // %clang_cc1 -fsyntax-only -verify %s -DEMPTYINIT -Wno-gnu -Wgnu-empty-initializer // %clang_cc1 -fsyntax-only -verify %s -DLABELVALUE -Wno-gnu -Wgnu-label-as-value // %clang_cc1 -fsyntax-only -verify %s -DSTATEMENTEXP -Wno-gnu -Wgnu-statement-expression +// %clang_cc1 -fsyntax-only -verify %s -DSTATEMENTEXPMACRO -Wno-gnu -Wgnu-statement-expression-from-macro-expansion // %clang_cc1 -fsyntax-only -verify %s -DCOMPOUNDLITERALINITIALIZER -Wno-gnu -Wgnu-compound-literal-initializer // %clang_cc1 -fsyntax-only -verify %s -DFLEXIBLEARRAYINITIALIZER -Wno-gnu -Wgnu-flexible-array-initializer // %clang_cc1 -fsyntax-only -verify %s -DREDECLAREDENUM -Wno-gnu -Wgnu-redeclared-enum @@ -95,6 +96,14 @@ void statementexp(void) int a = ({ 1; }); } +#if ALL || STATEMENTEXP || STATEMENTEXPMACRO +// expected-warning@+5 {{use of GNU statement expression extension from macro expansion}} +#endif + +#define STMT_EXPR_MACRO(a) ({ (a); }) +void statementexprmacro(void) { + int a = STMT_EXPR_MACRO(1); +} #if ALL || COMPOUNDLITERALINITIALIZER // expected-warning@+4 {{initialization of an array of type 'int[5]' from a compound literal of type 'int[5]' is a GNU extension}} diff --git a/clang/test/Sema/large-bit-int.c b/clang/test/Sema/large-bit-int.c new file mode 100644 index 0000000000000..f88ba2e48c5c7 --- /dev/null +++ b/clang/test/Sema/large-bit-int.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fexperimental-max-bitint-width=1024 -fsyntax-only -verify %s + +void f() { + _Static_assert(__BITINT_MAXWIDTH__ == 1024, "Macro value is unexpected."); + + _BitInt(1024) a; + unsigned _BitInt(1024) b; + + _BitInt(8388609) c; // expected-error {{signed _BitInt of bit sizes greater than 1024 not supported}} + unsigned _BitInt(0xFFFFFFFFFF) d; // expected-error {{unsigned _BitInt of bit sizes greater than 1024 not supported}} +} diff --git a/clang/test/Sema/matrix-type-builtins.c b/clang/test/Sema/matrix-type-builtins.c index c58384613e79c..afe85d31a0980 100644 --- a/clang/test/Sema/matrix-type-builtins.c +++ b/clang/test/Sema/matrix-type-builtins.c @@ -1,10 +1,26 @@ -// RUN: %clang_cc1 %s -fenable-matrix -pedantic -verify -triple=x86_64-apple-darwin9 +// RUN: %clang_cc1 %s -fenable-matrix -fdouble-square-bracket-attributes -pedantic -verify -triple=x86_64-apple-darwin9 typedef float sx5x10_t __attribute__((matrix_type(5, 10))); typedef int ix3x2_t __attribute__((matrix_type(3, 2))); typedef double dx3x3 __attribute__((matrix_type(3, 3))); typedef unsigned ix3x3 __attribute__((matrix_type(3, 3))); +// Verify that we can use the [[]] spelling of the attribute. +// We intentionally use the same type alias name to check that both versions +// define the same type. +typedef float [[clang::matrix_type(5, 10)]] sx5x10_t; +typedef int [[clang::matrix_type(3, 2)]] ix3x2_t; +[[clang::matrix_type(5, 10)]] typedef float sx5x10_t; +// expected-warning@-1 {{applying attribute 'matrix_type' to a declaration is deprecated; apply it to the type instead}} +[[clang::matrix_type(3, 2)]] typedef int ix3x2_t; +// expected-warning@-1 {{applying attribute 'matrix_type' to a declaration is deprecated; apply it to the type instead}} + +// Attribute may not be used outside typedefs. +[[clang::matrix_type(3, 2)]] int ix3x2_var; +// expected-error@-1 {{'matrix_type' attribute only applies to typedefs}} +int [[clang::matrix_type(3, 2)]] ix3x2_var; +// expected-error@-1 {{'matrix_type' attribute only applies to typedefs}} + void transpose(sx5x10_t a, ix3x2_t b, dx3x3 c, int *d, int e) { a = __builtin_matrix_transpose(b); // expected-error@-1 {{assigning to 'sx5x10_t' (aka 'float __attribute__((matrix_type(5, 10)))') from incompatible type 'int __attribute__((matrix_type(2, 3)))'}} diff --git a/clang/test/Sema/neon-vector-types.c b/clang/test/Sema/neon-vector-types.c index 03f669eb8416c..c79c73919a927 100644 --- a/clang/test/Sema/neon-vector-types.c +++ b/clang/test/Sema/neon-vector-types.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -triple armv7 -target-feature +neon -fsyntax-only -verify -// RUN: %clang_cc1 %s -triple armv8 -target-feature +neon -fsyntax-only -verify +// RUN: %clang_cc1 %s -triple armv7 -target-feature +neon -fsyntax-only -fdouble-square-bracket-attributes -verify +// RUN: %clang_cc1 %s -triple armv8 -target-feature +neon -fsyntax-only -fdouble-square-bracket-attributes -verify typedef float float32_t; typedef signed char poly8_t; @@ -16,6 +16,16 @@ typedef __attribute__((neon_vector_type(4))) float32_t float32x4_t; typedef __attribute__((neon_polyvector_type(16))) poly8_t poly8x16_t; typedef __attribute__((neon_polyvector_type(8))) poly16_t poly16x8_t; +// Verify that we can use the [[]] spelling of the attributes. +// We intentionally use the same type alias names to check that both versions +// define the same type. +typedef int [[clang::neon_vector_type(2)]] int32x2_t; +typedef poly8_t [[clang::neon_polyvector_type(16)]] poly8x16_t; + +// Verify that we can use the attributes outside of a typedef. +int [[clang::neon_vector_type(2)]] int32x2_var; +poly8_t [[clang::neon_polyvector_type(16)]] poly8x16_var; + // The attributes must have a single argument. typedef __attribute__((neon_vector_type(2, 4))) int only_one_arg; // expected-error{{'neon_vector_type' attribute takes one argument}} diff --git a/clang/test/Sema/overload-arm-mve.c b/clang/test/Sema/overload-arm-mve.c index 3b1a4430747f1..9ad1bfcc882f7 100644 --- a/clang/test/Sema/overload-arm-mve.c +++ b/clang/test/Sema/overload-arm-mve.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple thumbv8.1m.main-none-none-eabi -target-feature +mve.fp -flax-vector-conversions=all -Werror -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple thumbv8.1m.main-none-none-eabi -target-feature +mve.fp -flax-vector-conversions=all -verify -fsyntax-only -DERROR_CHECK %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-none-none-eabi -target-feature +mve.fp -flax-vector-conversions=all -fdouble-square-bracket-attributes -Werror -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-none-none-eabi -target-feature +mve.fp -flax-vector-conversions=all -fdouble-square-bracket-attributes -verify -fsyntax-only -DERROR_CHECK %s typedef signed short int16_t; typedef signed int int32_t; @@ -15,6 +15,14 @@ typedef __attribute__((neon_vector_type(8), __clang_arm_mve_strict_polymorphism) typedef __attribute__((neon_vector_type(4), __clang_arm_mve_strict_polymorphism)) uint32_t uint32x4_t; typedef __attribute__((neon_vector_type(2), __clang_arm_mve_strict_polymorphism)) uint64_t uint64x2_t; +// Verify that we can use the [[]] spelling of the attribute. +// We intentionally use the same type alias name to check that both versions +// define the same type. +typedef int16_t [[clang::neon_vector_type(8), clang::__clang_arm_mve_strict_polymorphism]] int16x8_t; + +// Verify that we can use the attribute outside of a typedef. +void test_param(int16_t [[clang::neon_vector_type(8), clang::__clang_arm_mve_strict_polymorphism]] int16x8); + __attribute__((overloadable)) int overload(int16x8_t x, int16_t y); // expected-note {{candidate function}} __attribute__((overloadable)) diff --git a/clang/test/Sema/pointer-subtraction.c b/clang/test/Sema/pointer-subtraction.c index c3dbbd47459fa..79d18a0f0a306 100644 --- a/clang/test/Sema/pointer-subtraction.c +++ b/clang/test/Sema/pointer-subtraction.c @@ -11,6 +11,16 @@ void a(void) { f = (char *)(f - (char *)0); // expected-warning {{performing pointer subtraction with a null pointer has undefined behavior}} f = (char *)((char *)0 - (char *)0); // expected-warning {{performing pointer subtraction with a null pointer has undefined behavior}} expected-warning {{performing pointer subtraction with a null pointer has undefined behavior}} + if (1) + f = (char *)((char *)0 - f); // expected-warning {{performing pointer subtraction with a null pointer has undefined behavior}} + else + f = (char *)((char *)0 - f); + + if (0) + f = (char *)((char *)0 - f); + else + f = (char *)((char *)0 - f); // expected-warning {{performing pointer subtraction with a null pointer has undefined behavior}} + #ifndef SYSTEM_WARNINGS SYSTEM_MACRO(f); #else diff --git a/clang/test/Sema/pointer-subtraction.cpp b/clang/test/Sema/pointer-subtraction.cpp index efbb3255e5d31..28063a1fea6ef 100644 --- a/clang/test/Sema/pointer-subtraction.cpp +++ b/clang/test/Sema/pointer-subtraction.cpp @@ -11,6 +11,16 @@ void a() { f = (char *)(f - (char *)0); // expected-warning {{performing pointer subtraction with a null pointer may have undefined behavior}} f = (char *)((char *)0 - (char *)0); // valid in C++ + if (1) + f = (char *)((char *)0 - f); // expected-warning {{performing pointer subtraction with a null pointer may have undefined behavior}} + else + f = (char *)((char *)0 - f); + + if (0) + f = (char *)((char *)0 - f); + else + f = (char *)((char *)0 - f); // expected-warning {{performing pointer subtraction with a null pointer may have undefined behavior}} + #ifndef SYSTEM_WARNINGS SYSTEM_MACRO(f); #else diff --git a/clang/test/Sema/ppc-mma-builtins.c b/clang/test/Sema/ppc-mma-builtins.c index 66cb54266f6ca..20d779557d28a 100644 --- a/clang/test/Sema/ppc-mma-builtins.c +++ b/clang/test/Sema/ppc-mma-builtins.c @@ -11,7 +11,7 @@ void test2(unsigned char *vqp, unsigned char *vpp, vector unsigned char vc, unsi __builtin_vsx_disassemble_pair(resp, (__vector_pair*)vpp); } -void test3(const __vector_pair *vpp, signed long offset, const __vector_pair *vp2) { +void test3(const __vector_pair *vpp, signed long offset, __vector_pair *vp2) { __vector_pair vp = __builtin_vsx_lxvp(offset, vpp); __builtin_vsx_stxvp(vp, offset, vp2); } diff --git a/clang/test/Sema/ppc-pair-mma-types.c b/clang/test/Sema/ppc-pair-mma-types.c index 293688d49813c..6a7cfac031058 100644 --- a/clang/test/Sema/ppc-pair-mma-types.c +++ b/clang/test/Sema/ppc-pair-mma-types.c @@ -209,7 +209,7 @@ void testBuiltinTypes2(__vector_pair *vpp, const __vector_pair *vp2, unsigned ch void testBuiltinTypes3(vector int v, __vector_pair *vp2, signed long l, unsigned short s) { __vector_pair vp = __builtin_vsx_lxvp(l, v); // expected-error {{passing '__vector int' (vector of 4 'int' values) to parameter of incompatible type 'const __vector_pair *'}} - __builtin_vsx_stxvp(vp, l, s); // expected-error {{passing 'unsigned short' to parameter of incompatible type 'const __vector_pair *'}} + __builtin_vsx_stxvp(vp, l, s); // expected-error {{passing 'unsigned short' to parameter of incompatible type '__vector_pair *'}} } void testRestrictQualifiedPointer1(int *__restrict acc) { diff --git a/clang/test/Sema/pragma-ms-alloc-text.c b/clang/test/Sema/pragma-ms-alloc-text.c new file mode 100644 index 0000000000000..a5f2e9f11dce2 --- /dev/null +++ b/clang/test/Sema/pragma-ms-alloc-text.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s + +void foo(); +#pragma alloc_text("hello", foo) // expected-no-diagnostics +void foo() {} + +static void foo1(); +#pragma alloc_text("hello", foo1) // expected-no-diagnostics +void foo1() {} diff --git a/clang/test/Sema/pragma-ms-alloc-text.cpp b/clang/test/Sema/pragma-ms-alloc-text.cpp index e1fb0ab4b2538..931b152fe78cc 100644 --- a/clang/test/Sema/pragma-ms-alloc-text.cpp +++ b/clang/test/Sema/pragma-ms-alloc-text.cpp @@ -34,3 +34,9 @@ void foo4() {} void foo5(); // expected-note {{previous declaration is here}} #pragma alloc_text(c, foo5) // expected-error {{'#pragma alloc_text' is applicable only to functions with C linkage}} extern "C" void foo5() {} // expected-error {{declaration of 'foo5' has a different language linkage}} + +extern "C" { +static void foo6(); +#pragma alloc_text(c, foo6) // no-warning +void foo6() {} +} diff --git a/clang/test/Sema/sizeless-1.c b/clang/test/Sema/sizeless-1.c index 2ee1ca9e87165..d50d1c629d13d 100644 --- a/clang/test/Sema/sizeless-1.c +++ b/clang/test/Sema/sizeless-1.c @@ -201,23 +201,6 @@ void func(int sel) { local_int8 &&init_int8; // expected-error {{invalid operands to binary expression}} local_int8 || init_int8; // expected-error {{invalid operands to binary expression}} - local_int8 + 0; // expected-error {{invalid operands to binary expression}} - local_int8 - 0; // expected-error {{invalid operands to binary expression}} - local_int8 * 0; // expected-error {{invalid operands to binary expression}} - local_int8 / 0; // expected-error {{invalid operands to binary expression}} - local_int8 % 0; // expected-error {{invalid operands to binary expression}} - local_int8 & 0; // expected-error {{invalid operands to binary expression}} - local_int8 | 0; // expected-error {{invalid operands to binary expression}} - local_int8 ^ 0; // expected-error {{invalid operands to binary expression}} - local_int8 < 0; // expected-error {{invalid operands to binary expression}} - local_int8 <= 0; // expected-error {{invalid operands to binary expression}} - local_int8 == 0; // expected-error {{invalid operands to binary expression}} - local_int8 != 0; // expected-error {{invalid operands to binary expression}} - local_int8 >= 0; // expected-error {{invalid operands to binary expression}} - local_int8 > 0; // expected-error {{invalid operands to binary expression}} - local_int8 && 0; // expected-error {{invalid operands to binary expression}} - local_int8 || 0; // expected-error {{invalid operands to binary expression}} - if (local_int8) { // expected-error {{statement requires expression of scalar type}} } while (local_int8) { // expected-error {{statement requires expression of scalar type}} diff --git a/clang/test/Sema/stmtexpr-init.c b/clang/test/Sema/stmtexpr-init.c new file mode 100644 index 0000000000000..73c87e0d4b726 --- /dev/null +++ b/clang/test/Sema/stmtexpr-init.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -verify -fsyntax-only %s + +static int *z[1] = {({ static int _x = 70; &_x; })}; // expected-error {{statement expression not allowed at file scope}} + +void T1(void) { + int *x[1] = {({ static int _x = 10; &_x; })}; // expected-no-error + + /* Before commit + 683e83c5 [Clang][C++2b] P2242R3: Non-literal variables [...] in constexpr + (i.e in clang-14 and earlier) + this was silently accepted, but generated incorrect code. + */ + static int *y[1] = {({ static int _x = 20; &_x; })}; // expected-error {{initializer element is not a compile-time constant}} +} diff --git a/clang/test/Sema/struct-packed-align.c b/clang/test/Sema/struct-packed-align.c index 03b012e340287..2a60f368479a2 100644 --- a/clang/test/Sema/struct-packed-align.c +++ b/clang/test/Sema/struct-packed-align.c @@ -1,6 +1,7 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify // RUN: %clang_cc1 %s -fsyntax-only -triple=x86_64-windows-coff -verify // RUN: %clang_cc1 %s -fsyntax-only -triple=x86_64-scei-ps4 -verify +// RUN: %clang_cc1 %s -fsyntax-only -triple=x86_64-sie-ps5 -verify // Packed structs. struct s { @@ -147,9 +148,9 @@ extern int n2[__alignof(struct nS) == 1 ? 1 : -1]; // See the documentation of -Wpacked-bitfield-compat for more information. struct packed_chars { char a : 8, b : 8, c : 8, d : 4; -#ifdef __ORBIS__ - // Test for pre-r254596 clang behavior on the PS4 target. PS4 must maintain - // ABI backwards compatibility. +#ifdef __SCE__ + // Test for pre-r254596 clang behavior on the PS4/PS5 targets, which must + // maintain ABI backwards compatibility. char e : 8 __attribute__((packed)); // expected-warning@-1 {{'packed' attribute ignored for field of type 'char'}} #else @@ -159,11 +160,11 @@ struct packed_chars { char f : 4, g : 8, h : 8, i : 8; }; -#if (defined(_WIN32) || defined(__ORBIS__)) && !defined(__declspec) // _MSC_VER is unavailable in cc1. +#if (defined(_WIN32) || defined(__SCE__)) && !defined(__declspec) // _MSC_VER is unavailable in cc1. // On Windows clang uses MSVC compatible layout in this case. // -// Additionally, test for pre-r254596 clang behavior on the PS4 target. PS4 -// must maintain ABI backwards compatibility. +// Additionally, test for pre-r254596 clang behavior on the PS4/PS5 targets. +// They must maintain ABI backwards compatibility. extern int o1[sizeof(struct packed_chars) == 9 ? 1 : -1]; extern int o2[__alignof(struct packed_chars) == 1 ? 1 : -1]; #elif defined(_AIX) diff --git a/clang/test/Sema/unused-expr.c b/clang/test/Sema/unused-expr.c index af4f0f39b8e5f..91923af371653 100644 --- a/clang/test/Sema/unused-expr.c +++ b/clang/test/Sema/unused-expr.c @@ -96,7 +96,7 @@ int t6(void) { return 0; } -int t7 __attribute__ ((warn_unused_result)); // expected-warning {{'warn_unused_result' attribute only applies to Objective-C methods, enums, structs, unions, classes, functions, and function pointers}} +int t7 __attribute__ ((warn_unused_result)); // expected-warning {{'warn_unused_result' attribute only applies to Objective-C methods, enums, structs, unions, classes, functions, function pointers, and typedefs}} // PR4010 int (*fn4)(void) __attribute__ ((warn_unused_result)); diff --git a/clang/test/Sema/vector-gcc-compat.c b/clang/test/Sema/vector-gcc-compat.c index 78132f7f09635..36feb7fd1422c 100644 --- a/clang/test/Sema/vector-gcc-compat.c +++ b/clang/test/Sema/vector-gcc-compat.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -verify -fsyntax-only -Weverything -Wno-unused-but-set-variable -triple x86_64-apple-darwin10 +// RUN: %clang_cc1 %s -verify -fsyntax-only -fdouble-square-bracket-attributes -Weverything -Wno-unused-but-set-variable -triple x86_64-apple-darwin10 // Test the compatibility of clang's vector extensions with gcc's vector // extensions for C. Notably &&, ||, ?: and ! are not available. @@ -17,6 +17,32 @@ typedef double v2f64 __attribute__((vector_size(16))); typedef double v4f64 __attribute__((vector_size(32))); typedef int v4i32 __attribute((vector_size(16))); +// Verify that we can use the [[]] spelling of the attribute. +// We intentionally use the same type alias name to check that both versions +// define the same type. +// FIXME: Warnings are nuisance warnings due to the `-Weverything` flag, but +// we shouldn't really be emitting them in C mode with the +// `-fdouble-square-bracket-attributes` flag. +typedef long long v2i64 [[gnu::vector_size(16)]]; // expected-warning{{C++11 attribute syntax is incompatible with C++98}} +typedef int v2i32 [[gnu::vector_size(8)]]; // expected-warning{{C++11 attribute syntax is incompatible with C++98}} + +// Check various positions where the [[]] spelling can or cannot be used. +[[gnu::vector_size(16)]] typedef long long v2i64; // expected-warning{{C++11 attribute syntax is incompatible with C++98}} +typedef long long [[gnu::vector_size(16)]] v2i64_ignored; + // expected-warning@-1{{'vector_size' attribute ignored}} + // expected-warning@-2{{C++11 attribute syntax is incompatible with C++98}} +// FIXME: Contrary to the error message that we emit, GCC does actually allow +// the attribute in the following position. Somewhat surprisingly, the attribute +// is applied not to the pointer but to the base type, i.e. this declaration has +// the same effect in GCC as the other declarations for `v2i64`. +typedef long long *[[gnu::vector_size(16)]] v2i64_doesnt_work; + // expected-error@-1{{invalid vector element type 'long long *'}} + // expected-warning@-2{{GCC does not allow the 'vector_size' attribute to be written on a type}} + // expected-warning@-3{{C++11 attribute syntax is incompatible with C++98}} + +// Verify that we can use the attribute outside of a typedef. +static int v2i32_var [[gnu::vector_size(8)]]; // expected-warning{{C++11 attribute syntax is incompatible with C++98}} + void arithmeticTest(void); void logicTest(void); void comparisonTest(void); diff --git a/clang/test/Sema/warn-missing-prototypes.c b/clang/test/Sema/warn-missing-prototypes.c index debb7f8141707..37176c66de4b6 100644 --- a/clang/test/Sema/warn-missing-prototypes.c +++ b/clang/test/Sema/warn-missing-prototypes.c @@ -58,14 +58,9 @@ const int *get_const() { // expected-warning{{no previous prototype for function struct MyStruct {}; -// FIXME: because qualifiers are ignored in the return type when forming the -// type from the declarator, we get the position incorrect for the fix-it hint. -// It suggests 'const static struct' instead of 'static const struct'. However, -// thanks to the awful rules of parsing in C, the effect is the same and the -// code is valid, if a bit funny looking. const struct MyStruct get_struct() { // expected-warning{{no previous prototype for function 'get_struct'}} // expected-note@-1{{declare 'static' if the function is not intended to be used outside of this translation unit}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:7-[[@LINE-2]]:7}:"static " + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:1-[[@LINE-2]]:1}:"static " struct MyStruct ret; return ret; } @@ -75,7 +70,7 @@ const struct MyStruct get_struct() { // expected-warning{{no previous prototype // Two spaces between cost and struct const struct MyStruct get_struct_2() { // expected-warning{{no previous prototype for function 'get_struct_2'}} // expected-note@-1{{declare 'static' if the function is not intended to be used outside of this translation unit}} - // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:8-[[@LINE-2]]:8}:"static " + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:1-[[@LINE-2]]:1}:"static " struct MyStruct ret; return ret; } diff --git a/clang/test/Sema/wchar.c b/clang/test/Sema/wchar.c index 5566207e50d7f..fa32ae6512fce 100644 --- a/clang/test/Sema/wchar.c +++ b/clang/test/Sema/wchar.c @@ -4,8 +4,8 @@ typedef __WCHAR_TYPE__ wchar_t; #if defined(_WIN32) || defined(_M_IX86) || defined(__CYGWIN__) \ - || defined(_M_X64) || defined(__ORBIS__) || defined(SHORT_WCHAR) \ - || (defined(_AIX) && !defined(__64BIT__)) + || defined(_M_X64) || defined(__ORBIS__) || defined(__PROSPERO__) \ + || defined(SHORT_WCHAR) || (defined(_AIX) && !defined(__64BIT__)) #define WCHAR_T_TYPE unsigned short #elif defined(__aarch64__) // See AArch64TargetInfo constructor -- unsigned on non-darwin non-OpenBSD non-NetBSD. diff --git a/clang/test/Sema/wg14-dr423.c b/clang/test/Sema/wg14-dr423.c deleted file mode 100644 index 1ce44dcffad66..0000000000000 --- a/clang/test/Sema/wg14-dr423.c +++ /dev/null @@ -1,31 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// RUN: %clang_cc1 -ast-dump %s | FileCheck %s -// expected-no-diagnostics - -void GH39595(void) { - // Ensure that qualifiers on function return types are dropped as part of the - // declaration. - extern const int const_int(void); - // CHECK: FunctionDecl {{.*}} parent {{.*}} col:20 referenced const_int 'int (void)' extern - extern _Atomic int atomic(void); - // CHECK: FunctionDecl {{.*}} parent {{.*}} col:22 referenced atomic 'int (void)' extern - - (void)_Generic(const_int(), int : 1); - (void)_Generic(atomic(), int : 1); - - // Make sure they're dropped from function pointers as well. - _Atomic int (*fp)(void); - (void)_Generic(fp(), int : 1); -} - -void casting(void) { - // Ensure that qualifiers on cast operations are also dropped. - (void)_Generic((const int)12, int : 1); - - struct S { int i; } s; - (void)_Generic((const struct S)s, struct S : 1); - - int i; - __typeof__((const int)i) j; - j = 100; // If we didn't strip the qualifiers during the cast, this would err. -} diff --git a/clang/test/SemaCXX/aarch64-sve-vector-conditional-op.cpp b/clang/test/SemaCXX/aarch64-sve-vector-conditional-op.cpp index a8fbf9ea3860e..d075d7935ba03 100644 --- a/clang/test/SemaCXX/aarch64-sve-vector-conditional-op.cpp +++ b/clang/test/SemaCXX/aarch64-sve-vector-conditional-op.cpp @@ -8,15 +8,15 @@ void cond(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64, svuint8_t u8, svuint16_t u16, svuint32_t u32, svuint64_t u64, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, svbool_t b) { - (void) i8 < i8 ? i16 : i16; // expected-error{{invalid operands to binary expression}} - (void) i8 < i8 ? i32 : i32; // expected-error{{invalid operands to binary expression}} - (void) i8 < i8 ? i64 : i64; // expected-error{{invalid operands to binary expression}} + i8 ? i16 : i16; // expected-error{{vector condition type 'svint8_t' (aka '__SVInt8_t') and result type 'svint16_t' (aka '__SVInt16_t') do not have the same number of elements}} + i8 ? i32 : i32; // expected-error{{vector condition type 'svint8_t' (aka '__SVInt8_t') and result type 'svint32_t' (aka '__SVInt32_t') do not have the same number of elements}} + i8 ? i64 : i64; // expected-error{{vector condition type 'svint8_t' (aka '__SVInt8_t') and result type 'svint64_t' (aka '__SVInt64_t') do not have the same number of elements}} - (void) i16 < i16 ? i16 : i8; // expected-error{{invalid operands to binary expression}} - (void) i16 < i16 ? i16 : i32; // expected-error{{invalid operands to binary expression}} - (void) i16 < i16 ? i16 : i64; // expected-error{{invalid operands to binary expression}} + i16 ? i16 : i8; // expected-error{{vector operands to the vector conditional must be the same type ('svint16_t' (aka '__SVInt16_t') and 'svint8_t' (aka '__SVInt8_t'))}} + i16 ? i16 : i32; // expected-error{{vector operands to the vector conditional must be the same type ('svint16_t' (aka '__SVInt16_t') and 'svint32_t' (aka '__SVInt32_t'))}} + i16 ? i16 : i64; // expected-error{{vector operands to the vector conditional must be the same type ('svint16_t' (aka '__SVInt16_t') and 'svint64_t' (aka '__SVInt64_t'))}} - (void) i16 < i16 ? i8 : i16; // expected-error{{invalid operands to binary expression}} - (void) i16 < i16 ? i32 : i16; // expected-error{{invalid operands to binary expression}} - (void) i16 < i16 ? i64 : i16; // expected-error{{invalid operands to binary expression}} + i16 ? i8 : i16; // expected-error{{vector operands to the vector conditional must be the same type ('svint8_t' (aka '__SVInt8_t') and 'svint16_t' (aka '__SVInt16_t'))}} + i16 ? i32 : i16; // expected-error{{vector operands to the vector conditional must be the same type ('svint32_t' (aka '__SVInt32_t') and 'svint16_t' (aka '__SVInt16_t'))}} + i16 ? i64 : i16; // expected-error{{vector operands to the vector conditional must be the same type ('svint64_t' (aka '__SVInt64_t') and 'svint16_t' (aka '__SVInt16_t'))}} } \ No newline at end of file diff --git a/clang/test/SemaCXX/address-space-placement.cpp b/clang/test/SemaCXX/address-space-placement.cpp new file mode 100644 index 0000000000000..2d8b94041259c --- /dev/null +++ b/clang/test/SemaCXX/address-space-placement.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify %s + +// Check that we emit the correct warnings in various situations where the C++11 +// spelling of the `address_space` attribute is applied to a declaration instead +// of a type. Also check that the attribute can instead be applied to the type. + +void f([[clang::address_space(1)]] int* param) { // expected-warning {{applying attribute 'address_space' to a declaration is deprecated; apply it to the type instead}} + [[clang::address_space(1)]] int* local1; // expected-warning {{applying attribute 'address_space' to a declaration is deprecated; apply it to the type instead}} + int* local2 [[clang::address_space(1)]]; // expected-error {{automatic variable qualified with an address space}} expected-warning {{applying attribute 'address_space' to a declaration is deprecated; apply it to the type instead}} + int [[clang::address_space(1)]] * local3; + int* [[clang::address_space(1)]] local4; // expected-error {{automatic variable qualified with an address space}} + + for ([[clang::address_space(1)]] int* p = nullptr; p; ++p) {} // expected-warning {{applying attribute 'address_space' to a declaration is deprecated; apply it to the type instead}} + for (; [[clang::address_space(1)]] int* p = nullptr; ) {} // expected-warning {{applying attribute 'address_space' to a declaration is deprecated; apply it to the type instead}} + while([[clang::address_space(1)]] int* p = nullptr) {} // expected-warning {{applying attribute 'address_space' to a declaration is deprecated; apply it to the type instead}} + if ([[clang::address_space(1)]] int* p = nullptr) {} // expected-warning {{applying attribute 'address_space' to a declaration is deprecated; apply it to the type instead}} + try { + } catch([[clang::address_space(1)]] int& i) { // expected-warning {{applying attribute 'address_space' to a declaration is deprecated; apply it to the type instead}} + } + + for (int [[clang::address_space(1)]] * p = nullptr; p; ++p) {} + for (; int [[clang::address_space(1)]] * p = nullptr; ) {} + while(int [[clang::address_space(1)]] * p = nullptr) {} + if (int [[clang::address_space(1)]] * p = nullptr) {} + try { + } catch(int [[clang::address_space(1)]] & i) { + } +} + +[[clang::address_space(1)]] int* return_value(); // expected-warning {{applying attribute 'address_space' to a declaration is deprecated; apply it to the type instead}} +int [[clang::address_space(1)]] * return_value(); + +[[clang::address_space(1)]] int global1; // expected-warning {{applying attribute 'address_space' to a declaration is deprecated; apply it to the type instead}} +int global2 [[clang::address_space(1)]]; // expected-warning {{applying attribute 'address_space' to a declaration is deprecated; apply it to the type instead}} +int [[clang::address_space(1)]] global3; +int [[clang::address_space(1)]] global4; + +struct [[clang::address_space(1)]] S { // expected-error {{'address_space' attribute cannot be applied to a declaration}} + [[clang::address_space(1)]] int* member_function_1(); // expected-warning {{applying attribute 'address_space' to a declaration is deprecated; apply it to the type instead}} + int [[clang::address_space(1)]] * member_function_2(); +}; + +template +[[clang::address_space(1)]] T var_template_1; // expected-warning {{applying attribute 'address_space' to a declaration is deprecated; apply it to the type instead}} +template +T [[clang::address_space(1)]] var_template_2; + +using void_ptr [[clang::address_space(1)]] = void *; // expected-warning {{applying attribute 'address_space' to a declaration is deprecated; apply it to the type instead}} +// Intentionally using the same alias name to check that the aliases define the +// same type. +using void_ptr = void [[clang::address_space(1)]] *; + +namespace N {} +[[clang::address_space(1)]] using namespace N; // expected-error {{'address_space' attribute cannot be applied to a declaration}} diff --git a/clang/test/SemaCXX/alignment-of-derived-class.cpp b/clang/test/SemaCXX/alignment-of-derived-class.cpp index 28c1fa9144b78..ab28bc0a235f1 100644 --- a/clang/test/SemaCXX/alignment-of-derived-class.cpp +++ b/clang/test/SemaCXX/alignment-of-derived-class.cpp @@ -2,7 +2,7 @@ // expected-no-diagnostics // Test that the alignment of a empty direct base class is correctly -// inherited by the derived class. +// inherited by the derived class, and correctly not inherited on PS4/PS5. struct A { } __attribute__ ((aligned(16))); @@ -12,22 +12,38 @@ static_assert(__alignof(A) == 16, "A should be aligned to 16 bytes"); struct B1 : public A { }; +#if defined(__SCE__) +static_assert(__alignof(B1) == 1, "B1 should be aligned to 1 byte"); +#else static_assert(__alignof(B1) == 16, "B1 should be aligned to 16 bytes"); +#endif struct B2 : public A { } __attribute__ ((aligned(2))); +#if defined(__SCE__) +static_assert(__alignof(B2) == 2, "B2 should be aligned to 2 bytes"); +#else static_assert(__alignof(B2) == 16, "B2 should be aligned to 16 bytes"); +#endif struct B3 : public A { } __attribute__ ((aligned(4))); +#if defined(__SCE__) +static_assert(__alignof(B3) == 4, "B3 should be aligned to 4 bytes"); +#else static_assert(__alignof(B3) == 16, "B3 should be aligned to 16 bytes"); +#endif struct B4 : public A { } __attribute__ ((aligned(8))); +#if defined(__SCE__) +static_assert(__alignof(B4) == 8, "B4 should be aligned to 8 bytes"); +#else static_assert(__alignof(B4) == 16, "B4 should be aligned to 16 bytes"); +#endif struct B5 : public A { } __attribute__ ((aligned(16))); diff --git a/clang/test/SemaCXX/annotate-type.cpp b/clang/test/SemaCXX/annotate-type.cpp new file mode 100644 index 0000000000000..545b3ccfdef8e --- /dev/null +++ b/clang/test/SemaCXX/annotate-type.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 %s -std=c++17 -fsyntax-only -fcxx-exceptions -verify + +struct S1 { + void f() [[clang::annotate_type("foo")]]; + [[clang::annotate_type("foo")]] void g(); // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} +}; + +template struct is_same { + static constexpr bool value = false; +}; + +template struct is_same { + static constexpr bool value = true; +}; + +static_assert(is_same::value); +static_assert(is_same::value); +static_assert(is_same::value); + +// Cannot overload on types that only differ by `annotate_type` attribute. +void f(int) {} // expected-note {{previous definition is here}} +void f(int [[clang::annotate_type("foo")]]) {} // expected-error {{redefinition of 'f'}} + +// Cannot specialize on types that only differ by `annotate_type` attribute. +template struct S2 {}; + +template <> struct S2 {}; // expected-note {{previous definition is here}} + +template <> +struct S2 {}; // expected-error {{redefinition of 'S2'}} + +// Test that the attribute supports parameter pack expansion. +template void variadic_func_template() { + int [[clang::annotate_type("foo", Is...)]] val; +} +int f2() { variadic_func_template<1, 2, 3>(); } + +// Make sure we correctly diagnose wrong number of arguments for +// [[clang::annotate_type]] inside a template argument. +template void func_template(); +void f3() { + func_template(); // expected-error {{'annotate_type' attribute takes at least 1 argument}} +} + +// More error cases: Prohibit adding the attribute to declarations. +// Different declarations hit different code paths, so they need separate tests. +namespace [[clang::annotate_type("foo")]] my_namespace {} // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} +struct [[clang::annotate_type("foo")]] S3; // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} +struct [[clang::annotate_type("foo")]] S3{ // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} + [[clang::annotate_type("foo")]] int member; // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} +}; +void f4() { + for ([[clang::annotate_type("foo")]] int i = 0; i < 42; ++i) {} // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} + for (; [[clang::annotate_type("foo")]] bool b = false;) {} // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} + while ([[clang::annotate_type("foo")]] bool b = false) {} // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} + if ([[clang::annotate_type("foo")]] bool b = false) {} // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} + try { + } catch ([[clang::annotate_type("foo")]] int i) { // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} + } +} +template +[[clang::annotate_type("foo")]] T var_template; // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} +[[clang::annotate_type("foo")]] extern "C" int extern_c_func(); // expected-error {{an attribute list cannot appear here}} +extern "C" [[clang::annotate_type("foo")]] int extern_c_func(); // expected-error {{'annotate_type' attribute cannot be applied to a declaration}} diff --git a/clang/test/SemaCXX/class-layout.cpp b/clang/test/SemaCXX/class-layout.cpp index 940966950d8be..f81e526d0e2ad 100644 --- a/clang/test/SemaCXX/class-layout.cpp +++ b/clang/test/SemaCXX/class-layout.cpp @@ -2,6 +2,7 @@ // RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base // RUN: %clang_cc1 -triple x86_64-apple-darwin %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=14 // RUN: %clang_cc1 -triple x86_64-scei-ps4 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6 +// RUN: %clang_cc1 -triple x86_64-sie-ps5 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6 // RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=6 -DCLANG_ABI_COMPAT=6 // RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14 // expected-no-diagnostics diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp index 4aaf6328aaf63..760821eb88373 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -530,8 +530,8 @@ namespace TwosComplementShifts { using int32 = __INT32_TYPE__; static_assert(uint32(int32(0x1234) << 16) == 0x12340000); static_assert(uint32(int32(0x1234) << 19) == 0x91a00000); - static_assert(uint32(int32(0x1234) << 20) == 0x23400000); // expected-warning {{requires 34 bits}} - static_assert(uint32(int32(0x1234) << 24) == 0x34000000); // expected-warning {{requires 38 bits}} + static_assert(uint32(int32(0x1234) << 20) == 0x23400000); + static_assert(uint32(int32(0x1234) << 24) == 0x34000000); static_assert(uint32(int32(-1) << 31) == 0x80000000); static_assert(-1 >> 1 == -1); diff --git a/clang/test/SemaCXX/coroutine-allocs.cpp b/clang/test/SemaCXX/coroutine-allocs.cpp index 4ffb080c9828f..c9797208e2dc5 100644 --- a/clang/test/SemaCXX/coroutine-allocs.cpp +++ b/clang/test/SemaCXX/coroutine-allocs.cpp @@ -19,7 +19,7 @@ struct resumable { }; }; -resumable f1() { // expected-error {{'operator new' provided by 'std::coroutine_traits::promise_type' (aka 'resumable::promise_type') is not usable}} +resumable f1() { // expected-error {{'operator new' provided by 'std::coroutine_traits::promise_type' (aka 'resumable::promise_type') is not usable with the function signature of 'f1'}} co_return; } @@ -37,7 +37,7 @@ resumable f1() { // expected-error {{'operator new' provided by 'std::coroutine_ // The first argument is the amount of space requested, and has type std::size_­t. // The lvalues p1…pn are the succeeding arguments. // -// So the acctual type passed to resumable::promise_type::operator new is lvalue +// So the actual type passed to resumable::promise_type::operator new is lvalue // Allocator. It is allowed to convert a lvalue to a lvalue reference. So the // following one is valid. resumable f2(Allocator &&) { @@ -59,3 +59,25 @@ resumable f5(const Allocator) { // expected-error {{operator new' provided by 's resumable f6(const Allocator &) { // expected-error {{operator new' provided by 'std::coroutine_traits::promise_type' (aka 'resumable::promise_type') is not usable}} co_return; } + +struct promise_base1 { + void *operator new(std::size_t sz); // expected-note {{member found by ambiguous name lookup}} +}; + +struct promise_base2 { + void *operator new(std::size_t sz); // expected-note {{member found by ambiguous name lookup}} +}; + +struct resumable2 { + struct promise_type : public promise_base1, public promise_base2 { + resumable2 get_return_object() { return {}; } + auto initial_suspend() { return std::suspend_always(); } + auto final_suspend() noexcept { return std::suspend_always(); } + void unhandled_exception() {} + void return_void(){}; + }; +}; + +resumable2 f7() { // expected-error {{member 'operator new' found in multiple base classes of different types}} + co_return; +} diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp index 6b6f8d22cdb89..df2a9925c0154 100644 --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -651,6 +651,27 @@ static_assert(baz() == sizeof(int)); } // namespace value_dependent +namespace default_argument { + +// Previously calls of consteval functions in default arguments were rejected. +// Now we show that we don't reject such calls. +consteval int foo() { return 1; } +consteval int bar(int i = foo()) { return i * i; } + +struct Test1 { + Test1(int i = bar(13)) {} + void v(int i = bar(13) * 2 + bar(15)) {} +}; +Test1 t1; + +struct Test2 { + constexpr Test2(int i = bar()) {} + constexpr void v(int i = bar(bar(bar(foo())))) {} +}; +Test2 t2; + +} // namespace default_argument + namespace PR50779 { struct derp { int b = 0; diff --git a/clang/test/SemaCXX/enum-scoped.cpp b/clang/test/SemaCXX/enum-scoped.cpp index ae2fe37153e86..4a9eb9cef892d 100644 --- a/clang/test/SemaCXX/enum-scoped.cpp +++ b/clang/test/SemaCXX/enum-scoped.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++11 -verify -triple x86_64-apple-darwin %s +// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++17 -verify -triple x86_64-apple-darwin %s enum class E1 { Val1 = 1L @@ -31,10 +32,22 @@ static_assert(sizeof(E3) == 1, "bad size"); int x2 = Val2; int a1[Val2]; -int a2[E1::Val1]; // expected-error{{size of array has non-integer type}} +int a2[E1::Val1]; + +#if __cplusplus >= 201703L +// expected-error@-3 {{type 'E1' is not implicitly convertible to 'unsigned long'}} +#else +// expected-error@-5 {{size of array has non-integer type}} +#endif int* p1 = new int[Val2]; -int* p2 = new int[E1::Val1]; // expected-error{{array size expression must have integral or unscoped enumeration type, not 'E1'}} +int* p2 = new int[E1::Val1]; + +#if __cplusplus >= 201703L +// expected-error@-3 {{converting 'E1' to incompatible type 'unsigned long'}} +#else +// expected-error@-5 {{array size expression must have integral or unscoped enumeration type, not 'E1'}} +#endif enum class E4 { e1 = -2147483648, // ok @@ -317,3 +330,11 @@ namespace PR35586 { enum C { R, G, B }; enum B { F = (enum C) -1, T}; // this should compile cleanly, it used to assert. }; + +namespace test12 { +// Check that clang rejects this code without crashing in c++17. +enum class A; +enum class B; +A a; +B b{a}; // expected-error {{cannot initialize}} +} diff --git a/clang/test/SemaCXX/generic-selection.cpp b/clang/test/SemaCXX/generic-selection.cpp index 79e0776cfa395..7b4fad65a1811 100644 --- a/clang/test/SemaCXX/generic-selection.cpp +++ b/clang/test/SemaCXX/generic-selection.cpp @@ -69,3 +69,24 @@ void unreachable_associations(const int i, const Test t) { default : 3 ) == 2, "we had better pick const Test, not Test!"); // C++-specific result } + +namespace GH55562 { +struct S { // expected-note {{declared here}} + int i; +}; + +void func(struct S s) { + // We would previously reject this because the parser thought 'struct S :' + // was the start of a definition (with a base class specifier); it's not, it + // is an elaborated type specifier followed by the association's value and + // it should work the same as in C. + (void)_Generic(s, struct S : 1); + + // The rest of these cases test that we still produce a reasonable diagnostic + // when referencing an unknown type or trying to define a type in other ways. + (void)_Generic(s, struct T : 1); // expected-error {{type 'struct T' in generic association incomplete}} + (void)_Generic(s, struct U { int a; } : 1); // expected-error {{'U' cannot be defined in a type specifier}} + (void)_Generic(s, struct V : S); // expected-error {{'S' does not refer to a value}} + (void)_Generic(s, struct W : S { int b; } : 1); // expected-error {{expected '(' for function-style cast or type construction}} +} +} // namespace GH55562 diff --git a/clang/test/SemaCXX/has_unique_object_reps_bitint.cpp b/clang/test/SemaCXX/has_unique_object_reps_bitint.cpp new file mode 100644 index 0000000000000..83190d006030e --- /dev/null +++ b/clang/test/SemaCXX/has_unique_object_reps_bitint.cpp @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify -std=c++17 -Wno-bitfield-width %s +// expected-no-diagnostics + +static_assert(__has_unique_object_representations(_BitInt(8))); +static_assert(__has_unique_object_representations(unsigned _BitInt(8))); +static_assert(__has_unique_object_representations(_BitInt(sizeof(int) * 8u))); +// sizeof(_BitInt(24)) may be 4 to align it to the next greater integer type, in which case it would have 8 padding bits. +static_assert(__has_unique_object_representations(_BitInt(24)) == (sizeof(_BitInt(24)) == 3)); + +static_assert(!__has_unique_object_representations(_BitInt(7))); +static_assert(!__has_unique_object_representations(unsigned _BitInt(7))); +static_assert(!__has_unique_object_representations(_BitInt(2))); +static_assert(!__has_unique_object_representations(unsigned _BitInt(1))); + +template +constexpr bool check() { + if constexpr (N <= __BITINT_MAXWIDTH__) { + static_assert(__has_unique_object_representations(_BitInt(N)) == (sizeof(_BitInt(N)) * 8u == N)); + static_assert(__has_unique_object_representations(unsigned _BitInt(N)) == (sizeof(unsigned _BitInt(N)) * 8u == N)); + } + return true; +} + +template +constexpr bool do_check = (check() && ...); + +static_assert(do_check<2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18>); +static_assert(do_check<15, 16, 17, 23, 24, 25, 31, 32, 33>); +static_assert(do_check<39, 40, 41, 47, 48, 49>); +static_assert(do_check<127, 128, 129, 255, 256, 257, 383, 384, 385>); + +template +struct in_struct { + _BitInt(N) x; + static constexpr bool check() { + return __has_unique_object_representations(in_struct) == __has_unique_object_representations(_BitInt(N)); + } +}; + +static_assert(in_struct<8>::check()); +static_assert(in_struct<7>::check()); + +struct bit_fields_1 { + _BitInt(7) x : 7; + unsigned _BitInt(1) y : 1; +}; + +static_assert(__has_unique_object_representations(bit_fields_1) == (sizeof(bit_fields_1) == 1)); + +struct bit_fields_2 { + _BitInt(8) x : 7; +}; + +static_assert(!__has_unique_object_representations(bit_fields_2)); + +struct bit_fields_3 { + _BitInt(15) x : 8; +}; + +static_assert(__has_unique_object_representations(bit_fields_3) == (sizeof(bit_fields_3) == 1)); + +#if __BITINT_MAXWIDTH__ >= 129 +struct bit_fields_4 { + _BitInt(129) x : 128; +}; + +static_assert(__has_unique_object_representations(bit_fields_4) == (sizeof(bit_fields_4) == 128 / 8)); +#endif + +struct bit_fields_5 { + _BitInt(2) x : 8; +}; + +static_assert(!__has_unique_object_representations(bit_fields_5)); + +template +struct ref_member { + _BitInt(N) & x; +}; + +struct int_ref_member { + int &x; +}; + +static_assert(__has_unique_object_representations(ref_member<7>) == __has_unique_object_representations(ref_member<8>)); +static_assert(__has_unique_object_representations(ref_member<8>) == __has_unique_object_representations(int_ref_member)); diff --git a/clang/test/SemaCXX/nested-name-spec.cpp b/clang/test/SemaCXX/nested-name-spec.cpp index 403bf1c0d4aa8..081ee25e7cdba 100644 --- a/clang/test/SemaCXX/nested-name-spec.cpp +++ b/clang/test/SemaCXX/nested-name-spec.cpp @@ -473,3 +473,10 @@ namespace DependentTemplateInTrivialNNSLoc { x: goto x; } } + +template +struct x; // expected-note {{template is declared here}} + +template +int issue55962 = x::a; // expected-error {{use of class template 'x' requires template arguments}} \ + // expected-warning {{variable templates are a C++14 extension}} diff --git a/clang/test/SemaCXX/shift.cpp b/clang/test/SemaCXX/shift.cpp index 144c18849050c..89a98791d3eba 100644 --- a/clang/test/SemaCXX/shift.cpp +++ b/clang/test/SemaCXX/shift.cpp @@ -41,8 +41,8 @@ void test() { int i; i = 1 << (WORD_BIT - 2); - i = 2 << (WORD_BIT - 1); // expected-warning {{bits to represent, but 'int' only has}} - i = 1 << (WORD_BIT - 1); // expected-warning {{sets the sign bit of the shift expression}} + i = 2 << (WORD_BIT - 1); // cxx17-warning {{bits to represent, but 'int' only has}} + i = 1 << (WORD_BIT - 1); // cxx17-warning {{sets the sign bit of the shift expression}} i = -1 << (WORD_BIT - 1); // cxx17-warning {{shifting a negative signed value is undefined}} i = -1 << 0; // cxx17-warning {{shifting a negative signed value is undefined}} i = 0 << (WORD_BIT - 1); @@ -53,7 +53,7 @@ void test() { u = 5U << (WORD_BIT - 1); long long int lli; - lli = INT_MIN << 2; // cxx17-warning {{shifting a negative signed value is undefined}} cxx2a-warning {{requires 34 bits to represent}} + lli = INT_MIN << 2; // cxx17-warning {{shifting a negative signed value is undefined}} lli = 1LL << (sizeof(long long) * CHAR_BIT - 2); } diff --git a/clang/test/SemaCXX/sizeless-1.cpp b/clang/test/SemaCXX/sizeless-1.cpp index 1e6987955cc7a..e0ca847bcdb29 100644 --- a/clang/test/SemaCXX/sizeless-1.cpp +++ b/clang/test/SemaCXX/sizeless-1.cpp @@ -213,23 +213,6 @@ void func(int sel) { local_int8 &&init_int8; // expected-error {{invalid operands to binary expression}} expected-error {{not contextually convertible}} local_int8 || init_int8; // expected-error {{invalid operands to binary expression}} expected-error {{not contextually convertible}} - local_int8 + 0; // expected-error {{invalid operands to binary expression}} - local_int8 - 0; // expected-error {{invalid operands to binary expression}} - local_int8 * 0; // expected-error {{invalid operands to binary expression}} - local_int8 / 0; // expected-error {{invalid operands to binary expression}} - local_int8 % 0; // expected-error {{invalid operands to binary expression}} - local_int8 & 0; // expected-error {{invalid operands to binary expression}} - local_int8 | 0; // expected-error {{invalid operands to binary expression}} - local_int8 ^ 0; // expected-error {{invalid operands to binary expression}} - local_int8 < 0; // expected-error {{invalid operands to binary expression}} - local_int8 <= 0; // expected-error {{invalid operands to binary expression}} - local_int8 == 0; // expected-error {{invalid operands to binary expression}} - local_int8 != 0; // expected-error {{invalid operands to binary expression}} - local_int8 >= 0; // expected-error {{invalid operands to binary expression}} - local_int8 > 0; // expected-error {{invalid operands to binary expression}} - local_int8 && 0; // expected-error {{invalid operands to binary expression}} expected-error {{not contextually convertible}} - local_int8 || 0; // expected-error {{invalid operands to binary expression}} expected-error {{not contextually convertible}} - if (local_int8) { // expected-error {{not contextually convertible to 'bool'}} } while (local_int8) { // expected-error {{not contextually convertible to 'bool'}} diff --git a/clang/test/SemaCXX/thread-safety-coro.cpp b/clang/test/SemaCXX/thread-safety-coro.cpp index a500ad5435e4a..9d40c3bf492a5 100644 --- a/clang/test/SemaCXX/thread-safety-coro.cpp +++ b/clang/test/SemaCXX/thread-safety-coro.cpp @@ -38,10 +38,14 @@ class Task { Task get_return_object() noexcept; void unhandled_exception() noexcept; void return_value(int value) noexcept; + + std::suspend_always yield_value(int value) noexcept; }; }; Task Foo() noexcept { // ICE'd + co_yield({ int frame = 0; 0; }); + co_await({ int frame = 0; std::suspend_always(); }); co_return({ int frame = 0; 0; }); } diff --git a/clang/test/SemaCXX/warn-unused-result.cpp b/clang/test/SemaCXX/warn-unused-result.cpp index d0bb4c9317dd2..4b7a2503ecc0d 100644 --- a/clang/test/SemaCXX/warn-unused-result.cpp +++ b/clang/test/SemaCXX/warn-unused-result.cpp @@ -254,3 +254,35 @@ __attribute__((warn_unused_result)) bool (*h)(); void i([[nodiscard]] bool (*fp)()); // expected-warning {{'nodiscard' attribute only applies to functions, classes, or enumerations}} } + +namespace unused_typedef_result { +[[clang::warn_unused_result]] typedef void *a; +typedef a indirect; +a af1(); +indirect indirectf1(); +void af2() { + af1(); // expected-warning {{ignoring return value}} + void *(*a1)(); + a1(); // no warning + a (*a2)(); + a2(); // expected-warning {{ignoring return value}} + indirectf1(); // expected-warning {{ignoring return value}} +} +[[nodiscard]] typedef void *b1; // expected-warning {{'[[nodiscard]]' attribute ignored when applied to a typedef; consider using '__attribute__((warn_unused_result))' or '[[clang::warn_unused_result]]' instead}} +[[gnu::warn_unused_result]] typedef void *b2; // expected-warning {{'[[gnu::warn_unused_result]]' attribute ignored when applied to a typedef; consider using '__attribute__((warn_unused_result))' or '[[clang::warn_unused_result]]' instead}} +b1 b1f1(); +b2 b2f1(); +void bf2() { + b1f1(); // no warning + b2f1(); // no warning +} +__attribute__((warn_unused_result)) typedef void *c; +c cf1(); +void cf2() { + cf1(); // expected-warning {{ignoring return value}} + void *(*c1)(); + c1(); + c (*c2)(); + c2(); // expected-warning {{ignoring return value}} +} +} diff --git a/clang/test/SemaCXX/weak-init.cpp b/clang/test/SemaCXX/weak-init.cpp new file mode 100644 index 0000000000000..c040330bb274a --- /dev/null +++ b/clang/test/SemaCXX/weak-init.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + +extern const int W1 __attribute__((weak)) = 10; // expected-note {{declared here}} + +static_assert(W1 == 10, ""); // expected-error {{static_assert expression is not an integral constant expression}} + // expected-note@-1 {{initializer of weak variable 'W1' is not considered constant because it may be different at runtime}} + +extern const int W2 __attribute__((weak)) = 20; + +int S2[W2]; // expected-error {{variable length array declaration not allowed at file scope}} + +extern const int W3 __attribute__((weak)) = 30; // expected-note {{declared here}} + +constexpr int S3 = W3; // expected-error {{constexpr variable 'S3' must be initialized by a constant expression}} + // expected-note@-1 {{initializer of weak variable 'W3' is not considered constant because it may be different at runtime}} diff --git a/clang/test/SemaHLSL/Wave.hlsl b/clang/test/SemaHLSL/Wave.hlsl new file mode 100644 index 0000000000000..ed64d1a5a55ba --- /dev/null +++ b/clang/test/SemaHLSL/Wave.hlsl @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -x hlsl -triple dxil--shadermodel6.7-library %s -verify + +// Make sure WaveActiveCountBits is accepted. + +// expected-no-diagnostics +unsigned foo(bool b) { + return WaveActiveCountBits(b); +} diff --git a/clang/test/SemaObjC/attr-objc-gc.m b/clang/test/SemaObjC/attr-objc-gc.m index 303dce0d8752b..e9dcbd993cb36 100644 --- a/clang/test/SemaObjC/attr-objc-gc.m +++ b/clang/test/SemaObjC/attr-objc-gc.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -fdouble-square-bracket-attributes -verify %s static id __attribute((objc_gc(weak))) a; static id __attribute((objc_gc(strong))) b; @@ -18,6 +18,10 @@ /* expected-warning {{'__weak' only applies to Objective-C object or block pointer types; type here is 'int'}}*/ static __we\ ak int i; +static id [[clang::objc_gc(weak)]] j; +[[clang::objc_gc(weak)]] static id k; // expected-warning {{applying attribute 'objc_gc' to a declaration is deprecated; apply it to the type instead}} +static id l [[clang::objc_gc(weak)]]; // expected-warning {{applying attribute 'objc_gc' to a declaration is deprecated; apply it to the type instead}} + // rdar://problem/9126213 void test2(id __attribute((objc_gc(strong))) *strong, id __attribute((objc_gc(weak))) *weak) { diff --git a/clang/test/SemaObjC/block-omitted-return-type.m b/clang/test/SemaObjC/block-omitted-return-type.m index 0504b1feabcab..f4ab4628013f0 100644 --- a/clang/test/SemaObjC/block-omitted-return-type.m +++ b/clang/test/SemaObjC/block-omitted-return-type.m @@ -23,8 +23,8 @@ - (void)test void (^simpleBlock4)(void) = ^ const { //expected-warning {{'const' qualifier on omitted return type '' has no effect}} return; }; - void (^simpleBlock5)(void) = ^ const void { // OK after DR 423. - return; + void (^simpleBlock5)(void) = ^ const void { //expected-error {{incompatible block pointer types initializing 'void (^)(void)' with an expression of type 'const void (^)(void)'}} + return; // expected-warning@-1 {{function cannot return qualified void type 'const void'}} }; void (^simpleBlock6)(void) = ^ const (void) { //expected-warning {{'const' qualifier on omitted return type '' has no effect}} return; diff --git a/clang/test/SemaOpenCL/address-spaces.cl b/clang/test/SemaOpenCL/address-spaces.cl index 41f5a33653254..70b6d0753528e 100644 --- a/clang/test/SemaOpenCL/address-spaces.cl +++ b/clang/test/SemaOpenCL/address-spaces.cl @@ -266,9 +266,9 @@ void func_multiple_addr2(void) { __attribute__((opencl_private)) private_int_t var5; // expected-warning {{multiple identical address spaces specified for type}} __attribute__((opencl_private)) private_int_t *var6; // expected-warning {{multiple identical address spaces specified for type}} #if __OPENCL_CPP_VERSION__ - [[clang::opencl_private]] __global int var7; // expected-error {{multiple address spaces specified for type}} - [[clang::opencl_private]] __global int *var8; // expected-error {{multiple address spaces specified for type}} - [[clang::opencl_private]] private_int_t var9; // expected-warning {{multiple identical address spaces specified for type}} - [[clang::opencl_private]] private_int_t *var10; // expected-warning {{multiple identical address spaces specified for type}} + __global int [[clang::opencl_private]] var7; // expected-error {{multiple address spaces specified for type}} + __global int [[clang::opencl_private]] *var8; // expected-error {{multiple address spaces specified for type}} + private_int_t [[clang::opencl_private]] var9; // expected-warning {{multiple identical address spaces specified for type}} + private_int_t [[clang::opencl_private]] *var10; // expected-warning {{multiple identical address spaces specified for type}} #endif // !__OPENCL_CPP_VERSION__ } diff --git a/clang/test/SemaOpenCL/extension-begin.cl b/clang/test/SemaOpenCL/extension-begin.cl index 9124ceba4e2a2..dc8bd769e2bde 100644 --- a/clang/test/SemaOpenCL/extension-begin.cl +++ b/clang/test/SemaOpenCL/extension-begin.cl @@ -18,8 +18,8 @@ #pragma OPENCL EXTENSION my_ext : enable #ifndef IMPLICIT_INCLUDE -// expected-warning@-2 {{unknown OpenCL extension 'my_ext' - ignoring}} -// expected-warning@+2 {{unknown OpenCL extension 'my_ext' - ignoring}} +// expected-warning@-2 {{OpenCL extension 'my_ext' unknown or does not require pragma - ignoring}} +// expected-warning@+2 {{OpenCL extension 'my_ext' unknown or does not require pragma - ignoring}} #endif // IMPLICIT_INCLUDE #pragma OPENCL EXTENSION my_ext : disable diff --git a/clang/test/SemaOpenCL/extension-version.cl b/clang/test/SemaOpenCL/extension-version.cl index d135970b8b02e..4d92eff6ae3ac 100644 --- a/clang/test/SemaOpenCL/extension-version.cl +++ b/clang/test/SemaOpenCL/extension-version.cl @@ -217,51 +217,51 @@ // Check that pragmas for the OpenCL 3.0 features are rejected. #pragma OPENCL EXTENSION __opencl_c_int64 : disable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_int64' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_int64' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_3d_image_writes : disable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_3d_image_writes' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_3d_image_writes' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_atomic_order_acq_rel : disable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_atomic_order_acq_rel' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_atomic_order_acq_rel' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_atomic_order_seq_cst : disable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_atomic_order_seq_cst' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_atomic_order_seq_cst' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_device_enqueue : disable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_device_enqueue' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_device_enqueue' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_fp64 : disable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_fp64' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_fp64' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_generic_address_space : disable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_generic_address_space' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_generic_address_space' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_images : disable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_images' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_images' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_pipes : disable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_pipes' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_pipes' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_program_scope_global_variables : disable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_program_scope_global_variables' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_program_scope_global_variables' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_read_write_images : disable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_read_write_images' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_read_write_images' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_subgroups : disable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_subgroups' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_subgroups' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_int64 : enable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_int64' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_int64' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_3d_image_writes : enable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_3d_image_writes' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_3d_image_writes' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_atomic_order_acq_rel : enable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_atomic_order_acq_rel' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_atomic_order_acq_rel' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_atomic_order_seq_cst : enable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_atomic_order_seq_cst' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_atomic_order_seq_cst' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_device_enqueue : enable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_device_enqueue' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_device_enqueue' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_fp64 : enable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_fp64' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_fp64' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_generic_address_space : enable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_generic_address_space' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_generic_address_space' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_images : enable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_images' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_images' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_pipes : enable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_pipes' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_pipes' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_program_scope_global_variables : enable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_program_scope_global_variables' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_program_scope_global_variables' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_read_write_images : enable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_read_write_images' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_read_write_images' unknown or does not require pragma - ignoring}} #pragma OPENCL EXTENSION __opencl_c_subgroups : enable -//expected-warning@-1{{unknown OpenCL extension '__opencl_c_subgroups' - ignoring}} +//expected-warning@-1{{OpenCL extension '__opencl_c_subgroups' unknown or does not require pragma - ignoring}} diff --git a/clang/tools/clang-import-test/clang-import-test.cpp b/clang/tools/clang-import-test/clang-import-test.cpp index a5206319bbb6e..a2ec0514af447 100644 --- a/clang/tools/clang-import-test/clang-import-test.cpp +++ b/clang/tools/clang-import-test/clang-import-test.cpp @@ -43,7 +43,7 @@ static llvm::cl::opt Expression( llvm::cl::desc("Path to a file containing the expression to parse")); static llvm::cl::list - Imports("import", llvm::cl::ZeroOrMore, + Imports("import", llvm::cl::desc("Path to a file containing declarations to import")); static llvm::cl::opt @@ -56,7 +56,7 @@ static llvm::cl::opt UseOrigins( "Use DeclContext origin information for more accurate lookups")); static llvm::cl::list - ClangArgs("Xcc", llvm::cl::ZeroOrMore, + ClangArgs("Xcc", llvm::cl::desc("Argument to pass to the CompilerInvocation"), llvm::cl::CommaSeparated); diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 74c03a26b884f..4e0b5ab2024cc 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -68,55 +68,55 @@ static cl::opt LinkerUserPath("linker-path", cl::Required, cl::cat(ClangLinkerWrapperCategory)); static cl::opt - TargetFeatures("target-feature", cl::ZeroOrMore, + TargetFeatures("target-feature", cl::desc("Target features for triple"), cl::cat(ClangLinkerWrapperCategory)); -static cl::opt OptLevel("opt-level", cl::ZeroOrMore, +static cl::opt OptLevel("opt-level", cl::desc("Optimization level for LTO"), cl::init("O2"), cl::cat(ClangLinkerWrapperCategory)); static cl::list - BitcodeLibraries("target-library", cl::ZeroOrMore, + BitcodeLibraries("target-library", cl::desc("Path for the target bitcode library"), cl::cat(ClangLinkerWrapperCategory)); static cl::opt EmbedBitcode( - "target-embed-bc", cl::ZeroOrMore, + "target-embed-bc", cl::desc("Embed linked bitcode instead of an executable device image"), - cl::init(false), cl::cat(ClangLinkerWrapperCategory)); + cl::cat(ClangLinkerWrapperCategory)); static cl::opt DryRun( - "dry-run", cl::ZeroOrMore, + "dry-run", cl::desc("List the linker commands to be run without executing them"), - cl::init(false), cl::cat(ClangLinkerWrapperCategory)); + cl::cat(ClangLinkerWrapperCategory)); static cl::opt - PrintWrappedModule("print-wrapped-module", cl::ZeroOrMore, + PrintWrappedModule("print-wrapped-module", cl::desc("Print the wrapped module's IR for testing"), - cl::init(false), cl::cat(ClangLinkerWrapperCategory)); + cl::cat(ClangLinkerWrapperCategory)); static cl::opt - HostTriple("host-triple", cl::ZeroOrMore, + HostTriple("host-triple", cl::desc("Triple to use for the host compilation"), cl::init(sys::getDefaultTargetTriple()), cl::cat(ClangLinkerWrapperCategory)); static cl::list - PtxasArgs("ptxas-args", cl::ZeroOrMore, + PtxasArgs("ptxas-args", cl::desc("Argument to pass to the ptxas invocation"), cl::cat(ClangLinkerWrapperCategory)); static cl::list - LinkerArgs("device-linker", cl::ZeroOrMore, + LinkerArgs("device-linker", cl::desc("Arguments to pass to the device linker invocation"), cl::value_desc(" or ="), cl::cat(ClangLinkerWrapperCategory)); -static cl::opt Verbose("v", cl::ZeroOrMore, +static cl::opt Verbose("v", cl::desc("Verbose output from tools"), - cl::init(false), + cl::cat(ClangLinkerWrapperCategory)); static cl::opt DebugInfo( @@ -126,11 +126,11 @@ static cl::opt DebugInfo( "Direction information"), clEnumValN(FullDebugInfo, "g", "Full debugging support"))); -static cl::opt SaveTemps("save-temps", cl::ZeroOrMore, +static cl::opt SaveTemps("save-temps", cl::desc("Save intermediary results."), cl::cat(ClangLinkerWrapperCategory)); -static cl::opt CudaPath("cuda-path", cl::ZeroOrMore, +static cl::opt CudaPath("cuda-path", cl::desc("Save intermediary results."), cl::cat(ClangLinkerWrapperCategory)); diff --git a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp index 1792923dd0159..8d9d2791f6d0e 100644 --- a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp +++ b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp @@ -63,23 +63,23 @@ static cl::opt Help("h", cl::desc("Alias for -help"), cl::Hidden); static cl::OptionCategory ClangOffloadBundlerCategory("clang-offload-bundler options"); static cl::list - InputFileNames("input", cl::ZeroOrMore, + InputFileNames("input", cl::desc("Input file." " Can be specified multiple times " "for multiple input files."), cl::cat(ClangOffloadBundlerCategory)); static cl::list - InputFileNamesDeprecatedOpt("inputs", cl::CommaSeparated, cl::ZeroOrMore, + InputFileNamesDeprecatedOpt("inputs", cl::CommaSeparated, cl::desc("[,...] (deprecated)"), cl::cat(ClangOffloadBundlerCategory)); static cl::list - OutputFileNames("output", cl::ZeroOrMore, + OutputFileNames("output", cl::desc("Output file." " Can be specified multiple times " "for multiple output files."), cl::cat(ClangOffloadBundlerCategory)); static cl::list - OutputFileNamesDeprecatedOpt("outputs", cl::CommaSeparated, cl::ZeroOrMore, + OutputFileNamesDeprecatedOpt("outputs", cl::CommaSeparated, cl::desc("[,...] (deprecated)"), cl::cat(ClangOffloadBundlerCategory)); static cl::list diff --git a/clang/tools/clang-offload-packager/CMakeLists.txt b/clang/tools/clang-offload-packager/CMakeLists.txt index bf95f5d5f8dd9..a781825895a52 100644 --- a/clang/tools/clang-offload-packager/CMakeLists.txt +++ b/clang/tools/clang-offload-packager/CMakeLists.txt @@ -3,26 +3,16 @@ set(LLVM_LINK_COMPONENTS Object Support) -if(NOT CLANG_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - -add_clang_executable(clang-offload-packager +add_clang_tool(clang-offload-packager ClangOffloadPackager.cpp DEPENDS ${tablegen_deps} ) -set(CLANG_LINKER_WRAPPER_LIB_DEPS - clangBasic - ) - add_dependencies(clang clang-offload-packager) -target_link_libraries(clang-offload-packager +clang_target_link_libraries(clang-offload-packager PRIVATE - ${CLANG_LINKER_WRAPPER_LIB_DEPS} + clangBasic ) - -install(TARGETS clang-offload-packager RUNTIME DESTINATION bin) diff --git a/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp b/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp index f05697539675d..7ef258396e989 100644 --- a/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp +++ b/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp @@ -38,7 +38,7 @@ static cl::opt OutputFile("o", cl::Required, cl::cat(ClangOffloadPackagerCategory)); static cl::list - DeviceImages("image", cl::ZeroOrMore, + DeviceImages("image", cl::desc("List of key and value arguments. Required keywords " "are 'file' and 'triple'."), cl::value_desc("=,..."), @@ -89,8 +89,7 @@ int main(int argc, const char **argv) { llvm::MemoryBuffer::getFileOrSTDIN(KeyAndValue.getValue()); if (std::error_code EC = ObjectOrErr.getError()) return reportError(errorCodeToError(EC)); - DeviceImage = std::move(*ObjectOrErr); - ImageBinary.Image = *DeviceImage; + ImageBinary.Image = std::move(*ObjectOrErr); ImageBinary.TheImageKind = getImageKind( sys::path::extension(KeyAndValue.getValue()).drop_front()); } else if (Key == "kind") { diff --git a/clang/tools/clang-rename/ClangRename.cpp b/clang/tools/clang-rename/ClangRename.cpp index 141ba379ed053..e7ceac7dbf303 100644 --- a/clang/tools/clang-rename/ClangRename.cpp +++ b/clang/tools/clang-rename/ClangRename.cpp @@ -68,17 +68,17 @@ static cl::OptionCategory ClangRenameOptions("clang-rename common options"); static cl::list SymbolOffsets( "offset", cl::desc("Locates the symbol by offset as opposed to :."), - cl::ZeroOrMore, cl::cat(ClangRenameOptions)); + cl::cat(ClangRenameOptions)); static cl::opt Inplace("i", cl::desc("Overwrite edited s."), cl::cat(ClangRenameOptions)); static cl::list QualifiedNames("qualified-name", cl::desc("The fully qualified name of the symbol."), - cl::ZeroOrMore, cl::cat(ClangRenameOptions)); + cl::cat(ClangRenameOptions)); static cl::list NewNames("new-name", cl::desc("The new name to change the symbol to."), - cl::ZeroOrMore, cl::cat(ClangRenameOptions)); + cl::cat(ClangRenameOptions)); static cl::opt PrintName( "pn", cl::desc("Print the found symbol's name prior to renaming to stderr."), diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp index 4240b9d425df1..088615e30a2d6 100644 --- a/clang/tools/clang-repl/ClangRepl.cpp +++ b/clang/tools/clang-repl/ClangRepl.cpp @@ -23,13 +23,12 @@ #include "llvm/Support/TargetSelect.h" // llvm::Initialize* static llvm::cl::list - ClangArgs("Xcc", llvm::cl::ZeroOrMore, + ClangArgs("Xcc", llvm::cl::desc("Argument to pass to the CompilerInvocation"), llvm::cl::CommaSeparated); static llvm::cl::opt OptHostSupportsJit("host-supports-jit", llvm::cl::Hidden); static llvm::cl::list OptInputs(llvm::cl::Positional, - llvm::cl::ZeroOrMore, llvm::cl::desc("[code to run]")); static void LLVMErrorHandler(void *UserData, const char *Message, diff --git a/clang/tools/diagtool/DiagnosticNames.cpp b/clang/tools/diagtool/DiagnosticNames.cpp index b0ea68e032e75..a3f49783c1c41 100644 --- a/clang/tools/diagtool/DiagnosticNames.cpp +++ b/clang/tools/diagtool/DiagnosticNames.cpp @@ -66,7 +66,7 @@ const DiagnosticRecord &diagtool::getDiagnosticForID(short DiagID) { // Second the table of options, sorted by name for fast binary lookup. static const GroupRecord OptionTable[] = { -#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups) \ +#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \ {FlagNameOffset, Members, SubGroups}, #include "clang/Basic/DiagnosticGroups.inc" #undef DIAG_ENTRY diff --git a/clang/tools/driver/CMakeLists.txt b/clang/tools/driver/CMakeLists.txt index 6b3e159d1b648..d05b71db13f21 100644 --- a/clang/tools/driver/CMakeLists.txt +++ b/clang/tools/driver/CMakeLists.txt @@ -31,6 +31,7 @@ add_clang_tool(clang DEPENDS intrinsics_gen ${support_plugins} + GENERATE_DRIVER ) clang_target_link_libraries(clang diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index f1531669709aa..5498810d835cd 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -137,6 +137,9 @@ struct AssemblerInvocation { unsigned IncrementalLinkerCompatible : 1; unsigned EmbedBitcode : 1; + /// Whether to emit DWARF unwind info. + EmitDwarfUnwindType EmitDwarfUnwind; + /// The name of the relocation model to use. std::string RelocationModel; @@ -167,6 +170,7 @@ struct AssemblerInvocation { Dwarf64 = 0; DwarfVersion = 0; EmbedBitcode = 0; + EmitDwarfUnwind = EmitDwarfUnwindType::Default; } static bool CreateFromArgs(AssemblerInvocation &Res, @@ -317,6 +321,14 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, .Default(0); } + if (auto *A = Args.getLastArg(OPT_femit_dwarf_unwind_EQ)) { + Opts.EmitDwarfUnwind = + llvm::StringSwitch(A->getValue()) + .Case("always", EmitDwarfUnwindType::Always) + .Case("no-compact-unwind", EmitDwarfUnwindType::NoCompactUnwind) + .Case("default", EmitDwarfUnwindType::Default); + } + return Success; } @@ -367,6 +379,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, assert(MRI && "Unable to create target register info!"); MCTargetOptions MCOptions; + MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind; + std::unique_ptr MAI( TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions)); assert(MAI && "Unable to create target asm info!"); @@ -505,7 +519,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, if (Opts.EmbedBitcode && Ctx.getObjectFileType() == MCContext::IsMachO) { MCSection *AsmLabel = Ctx.getMachOSection( "__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly()); - Str.get()->SwitchSection(AsmLabel); + Str.get()->switchSection(AsmLabel); Str.get()->emitZeros(1); } diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index a7bfb07e002bf..fa1f09b44f4da 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -327,7 +327,7 @@ static int ExecuteCC1Tool(SmallVectorImpl &ArgV) { return 1; } -int main(int Argc, const char **Argv) { +int clang_main(int Argc, char **Argv) { noteBottomOfStack(); llvm::InitLLVM X(Argc, Argv); llvm::setBugReportMsg("PLEASE submit a bug report to " BUG_REPORT_URL @@ -482,32 +482,39 @@ int main(int Argc, const char **Argv) { } std::unique_ptr C(TheDriver.BuildCompilation(Args)); + + Driver::ReproLevel ReproLevel = Driver::ReproLevel::OnCrash; + if (Arg *A = C->getArgs().getLastArg(options::OPT_gen_reproducer_eq)) { + auto Level = llvm::StringSwitch>(A->getValue()) + .Case("off", Driver::ReproLevel::Off) + .Case("crash", Driver::ReproLevel::OnCrash) + .Case("error", Driver::ReproLevel::OnError) + .Case("always", Driver::ReproLevel::Always) + .Default(None); + if (!Level) { + llvm::errs() << "Unknown value for " << A->getSpelling() << ": '" + << A->getValue() << "'\n"; + return 1; + } + ReproLevel = *Level; + } + if (!!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) + ReproLevel = Driver::ReproLevel::Always; + int Res = 1; bool IsCrash = false; + Driver::CommandStatus CommandStatus = Driver::CommandStatus::Ok; + // Pretend the first command failed if ReproStatus is Always. + const Command *FailingCommand = nullptr; + if (!C->getJobs().empty()) + FailingCommand = &*C->getJobs().begin(); if (C && !C->containsError()) { SmallVector, 4> FailingCommands; Res = TheDriver.ExecuteCompilation(*C, FailingCommands); - // Force a crash to test the diagnostics. - if (TheDriver.GenReproducer) { - Diags.Report(diag::err_drv_force_crash) - << !::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"); - - // Pretend that every command failed. - FailingCommands.clear(); - for (const auto &J : C->getJobs()) - if (const Command *C = dyn_cast(&J)) - FailingCommands.push_back(std::make_pair(-1, C)); - - // Print the bug report message that would be printed if we did actually - // crash, but only if we're crashing due to FORCE_CLANG_DIAGNOSTICS_CRASH. - if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) - llvm::dbgs() << llvm::getBugReportMsg(); - } - for (const auto &P : FailingCommands) { int CommandRes = P.first; - const Command *FailingCommand = P.second; + FailingCommand = P.second; if (!Res) Res = CommandRes; @@ -526,13 +533,22 @@ int main(int Argc, const char **Argv) { // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html IsCrash |= CommandRes > 128; #endif - if (IsCrash) { - TheDriver.generateCompilationDiagnostics(*C, *FailingCommand); + CommandStatus = + IsCrash ? Driver::CommandStatus::Crash : Driver::CommandStatus::Error; + if (IsCrash) break; - } } } + // Print the bug report message that would be printed if we did actually + // crash, but only if we're crashing due to FORCE_CLANG_DIAGNOSTICS_CRASH. + if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) + llvm::dbgs() << llvm::getBugReportMsg(); + if (FailingCommand != nullptr && + TheDriver.maybeGenerateCompilationDiagnostics(CommandStatus, ReproLevel, + *C, *FailingCommand)) + Res = 1; + Diags.getClient()->finish(); if (!UseNewCC1Process && IsCrash) { diff --git a/clang/tools/libclang/CIndexer.cpp b/clang/tools/libclang/CIndexer.cpp index dab3fc4e201d0..77da2e4fa5ead 100644 --- a/clang/tools/libclang/CIndexer.cpp +++ b/clang/tools/libclang/CIndexer.cpp @@ -176,7 +176,7 @@ LibclangInvocationReporter::LibclangInvocationReporter( if (llvm::sys::fs::createUniqueFile(TempPath, FD, TempPath, llvm::sys::fs::OF_Text)) return; - File = std::string(TempPath.begin(), TempPath.end()); + File = static_cast(TempPath); llvm::raw_fd_ostream OS(FD, /*ShouldClose=*/true); // Write out the information about the invocation to it. diff --git a/clang/tools/scan-build-py/bin/analyze-build b/clang/tools/scan-build-py/bin/analyze-build index b3f61429906c4..636b5aa4dd36d 100755 --- a/clang/tools/scan-build-py/bin/analyze-build +++ b/clang/tools/scan-build-py/bin/analyze-build @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/tools/scan-build-py/bin/intercept-build b/clang/tools/scan-build-py/bin/intercept-build index 9ecde39984434..dcd0473ef5489 100755 --- a/clang/tools/scan-build-py/bin/intercept-build +++ b/clang/tools/scan-build-py/bin/intercept-build @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/tools/scan-build-py/bin/scan-build b/clang/tools/scan-build-py/bin/scan-build index a341751d993a2..3e5a5ade304c2 100755 --- a/clang/tools/scan-build-py/bin/scan-build +++ b/clang/tools/scan-build-py/bin/scan-build @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/tools/scan-build-py/lib/libscanbuild/analyze.py b/clang/tools/scan-build-py/lib/libscanbuild/analyze.py index 08802de81cc57..2633139fd523e 100644 --- a/clang/tools/scan-build-py/lib/libscanbuild/analyze.py +++ b/clang/tools/scan-build-py/lib/libscanbuild/analyze.py @@ -357,6 +357,7 @@ def report_directory(hint, keep, output_format): try: yield name finally: + args = (name,) if os.listdir(name): if output_format not in ['sarif', 'sarif-html']: # FIXME: # 'scan-view' currently does not support sarif format. @@ -364,6 +365,7 @@ def report_directory(hint, keep, output_format): elif output_format == 'sarif-html': msg = "Run 'scan-view %s' to examine bug reports or see " \ "merged sarif results at %s/results-merged.sarif." + args = (name, name) else: msg = "View merged sarif results at %s/results-merged.sarif." keep = True @@ -372,7 +374,7 @@ def report_directory(hint, keep, output_format): msg = "Report directory '%s' contains no report, but kept." else: msg = "Removing directory '%s' because it contains no report." - logging.warning(msg, name) + logging.warning(msg, *args) if not keep: os.rmdir(name) diff --git a/clang/tools/scan-build-py/libexec/analyze-c++ b/clang/tools/scan-build-py/libexec/analyze-c++ index a280b2fb4ddaf..5c72dfff4a896 100755 --- a/clang/tools/scan-build-py/libexec/analyze-c++ +++ b/clang/tools/scan-build-py/libexec/analyze-c++ @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/tools/scan-build-py/libexec/analyze-cc b/clang/tools/scan-build-py/libexec/analyze-cc index 36bbcd93f9871..fbdbde8f5b2e6 100755 --- a/clang/tools/scan-build-py/libexec/analyze-cc +++ b/clang/tools/scan-build-py/libexec/analyze-cc @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/tools/scan-build-py/libexec/intercept-c++ b/clang/tools/scan-build-py/libexec/intercept-c++ index 9e541a180d6b4..b8c8e923ec76e 100755 --- a/clang/tools/scan-build-py/libexec/intercept-c++ +++ b/clang/tools/scan-build-py/libexec/intercept-c++ @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/tools/scan-build-py/libexec/intercept-cc b/clang/tools/scan-build-py/libexec/intercept-cc index 9e541a180d6b4..b8c8e923ec76e 100755 --- a/clang/tools/scan-build-py/libexec/intercept-cc +++ b/clang/tools/scan-build-py/libexec/intercept-cc @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/unittests/AST/ASTImporterFixtures.h b/clang/unittests/AST/ASTImporterFixtures.h index f309a5090ad2a..ed561f4b5eaf2 100644 --- a/clang/unittests/AST/ASTImporterFixtures.h +++ b/clang/unittests/AST/ASTImporterFixtures.h @@ -276,9 +276,10 @@ class TestImportBase auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport); if (!Imported) { std::string ErrorText; - handleAllErrors( - Imported.takeError(), - [&ErrorText](const ImportError &Err) { ErrorText = Err.message(); }); + handleAllErrors(Imported.takeError(), + [&ErrorText](const ASTImportError &Err) { + ErrorText = Err.message(); + }); return testing::AssertionFailure() << "Import failed, error: \"" << ErrorText << "\"!"; } @@ -437,7 +438,7 @@ ::testing::AssertionResult isSuccess(llvm::Expected &ValOrErr) { template ::testing::AssertionResult isImportError(llvm::Expected &ValOrErr, - ImportError::ErrorKind Kind) { + ASTImportError::ErrorKind Kind) { if (ValOrErr) { return ::testing::AssertionFailure() << "Expected<> is expected to contain " "error but does contain value \"" @@ -446,7 +447,7 @@ ::testing::AssertionResult isImportError(llvm::Expected &ValOrErr, std::ostringstream OS; bool Result = false; auto Err = llvm::handleErrors( - ValOrErr.takeError(), [&OS, &Result, Kind](clang::ImportError &IE) { + ValOrErr.takeError(), [&OS, &Result, Kind](clang::ASTImportError &IE) { if (IE.Error == Kind) { Result = true; OS << "Expected<> contains an ImportError " << IE.toString(); diff --git a/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp b/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp index eabdfeb03ede2..e743bb7a5f62c 100644 --- a/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp +++ b/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp @@ -290,7 +290,7 @@ struct ODRViolation : ASTImporterOptionSpecificTestBase { // Check that a Decl was not imported because of NameConflict. static void CheckImportNameConflict(llvm::Expected &Result, Decl *ToTU, Decl *ToD) { - EXPECT_TRUE(isImportError(Result, ImportError::NameConflict)); + EXPECT_TRUE(isImportError(Result, ASTImportError::NameConflict)); EXPECT_EQ(DeclCounter().match(ToTU, getPattern()), 1u); } diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index f1965235c9a6d..d0edbcb40ab8e 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -910,6 +910,20 @@ TEST_P(ImportDecl, ImportUsingEnumDecl) { functionDecl(hasDescendant(usingEnumDecl(hasName("bar"))))); } +const internal::VariadicDynCastAllOfMatcher usingPackDecl; + +TEST_P(ImportDecl, ImportUsingPackDecl) { + MatchVerifier Verifier; + testImport( + "struct A { int operator()() { return 1; } };" + "struct B { int operator()() { return 2; } };" + "template struct C : T... { using T::operator()...; };" + "C declToImport;", + Lang_CXX20, "", Lang_CXX20, Verifier, + varDecl(hasType(templateSpecializationType(hasDeclaration( + classTemplateSpecializationDecl(hasDescendant(usingPackDecl()))))))); +} + /// \brief Matches shadow declarations introduced into a scope by a /// (resolved) using declaration. /// @@ -1022,6 +1036,31 @@ TEST_P(ImportExpr, DependentSizedArrayType) { has(fieldDecl(hasType(dependentSizedArrayType()))))))); } +TEST_P(ASTImporterOptionSpecificTestBase, ImportUsingPackDecl) { + Decl *FromTU = getTuDecl( + "struct A { int operator()() { return 1; } };" + "struct B { int operator()() { return 2; } };" + "template struct C : T... { using T::operator()...; };" + "C Var;", + Lang_CXX20); + + auto From = FirstDeclMatcher().match(FromTU, usingPackDecl()); + ASSERT_TRUE(From); + auto To = cast(Import(From, Lang_CXX20)); + ASSERT_TRUE(To); + + ArrayRef FromExpansions = From->expansions(); + ArrayRef ToExpansions = To->expansions(); + ASSERT_EQ(FromExpansions.size(), ToExpansions.size()); + for (unsigned int I = 0; I < FromExpansions.size(); ++I) { + auto ImportedExpansion = Import(FromExpansions[I], Lang_CXX20); + EXPECT_EQ(ImportedExpansion, ToExpansions[I]); + } + + auto ImportedDC = cast(Import(From->getDeclContext(), Lang_CXX20)); + EXPECT_EQ(ImportedDC, cast(To->getDeclContext())); +} + TEST_P(ASTImporterOptionSpecificTestBase, TemplateTypeParmDeclNoDefaultArg) { Decl *FromTU = getTuDecl("template struct X {};", Lang_CXX03); auto From = FirstDeclMatcher().match( @@ -3169,8 +3208,8 @@ TEST_P(ImportBlock, ImportBlocksAreUnsupported) { auto ToBlockOrError = importOrError(FromBlock, Lang_CXX03); - const auto ExpectUnsupportedConstructError = [](const ImportError &Error) { - EXPECT_EQ(ImportError::UnsupportedConstruct, Error.Error); + const auto ExpectUnsupportedConstructError = [](const ASTImportError &Error) { + EXPECT_EQ(ASTImportError::UnsupportedConstruct, Error.Error); }; llvm::handleAllErrors(ToBlockOrError.takeError(), ExpectUnsupportedConstructError); @@ -5430,9 +5469,9 @@ TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) { // But an error is set to the counterpart in the "from" context. ASTImporter *Importer = findFromTU(FromSpec)->Importer.get(); - Optional OptErr = Importer->getImportDeclErrorIfAny(FromSpec); + Optional OptErr = Importer->getImportDeclErrorIfAny(FromSpec); ASSERT_TRUE(OptErr); - EXPECT_EQ(OptErr->Error, ImportError::NameConflict); + EXPECT_EQ(OptErr->Error, ASTImportError::NameConflict); } // Check a case when a new AST node is created but not linked to the AST before @@ -5454,9 +5493,9 @@ TEST_P(ErrorHandlingTest, 0u); ASTImporter *Importer = findFromTU(FromFoo)->Importer.get(); - Optional OptErr = Importer->getImportDeclErrorIfAny(FromFoo); + Optional OptErr = Importer->getImportDeclErrorIfAny(FromFoo); ASSERT_TRUE(OptErr); - EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); + EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct); } // Check a case when a new AST node is created and linked to the AST before @@ -5487,12 +5526,13 @@ TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) { // An error is set to the counterpart in the "from" context both for the fwd // decl and the definition. ASTImporter *Importer = findFromTU(FromProto)->Importer.get(); - Optional OptErr = Importer->getImportDeclErrorIfAny(FromProto); + Optional OptErr = + Importer->getImportDeclErrorIfAny(FromProto); ASSERT_TRUE(OptErr); - EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); + EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct); OptErr = Importer->getImportDeclErrorIfAny(FromDef); ASSERT_TRUE(OptErr); - EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); + EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct); } // An error should be set for a class if we cannot import one member. @@ -5512,16 +5552,16 @@ TEST_P(ErrorHandlingTest, ErrorIsPropagatedFromMemberToClass) { // An error is set for X. EXPECT_FALSE(ImportedX); ASTImporter *Importer = findFromTU(FromX)->Importer.get(); - Optional OptErr = Importer->getImportDeclErrorIfAny(FromX); + Optional OptErr = Importer->getImportDeclErrorIfAny(FromX); ASSERT_TRUE(OptErr); - EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); + EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct); // An error is set for f(). auto *FromF = FirstDeclMatcher().match( FromTU, cxxMethodDecl(hasName("f"))); OptErr = Importer->getImportDeclErrorIfAny(FromF); ASSERT_TRUE(OptErr); - EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); + EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct); // And any subsequent import should fail. CXXMethodDecl *ImportedF = Import(FromF, Lang_CXX03); EXPECT_FALSE(ImportedF); @@ -5579,7 +5619,7 @@ TEST_P(ErrorHandlingTest, ErrorPropagatesThroughImportCycles) { // An error is set to the templated CXXRecordDecl of F. ASTImporter *Importer = findFromTU(FromFRD)->Importer.get(); - Optional OptErr = Importer->getImportDeclErrorIfAny(FromFRD); + Optional OptErr = Importer->getImportDeclErrorIfAny(FromFRD); EXPECT_TRUE(OptErr); // An error is set to A. @@ -5637,7 +5677,7 @@ TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) { // There is no error set for X. EXPECT_TRUE(ImportedX); ASTImporter *Importer = findFromTU(FromX)->Importer.get(); - Optional OptErr = Importer->getImportDeclErrorIfAny(FromX); + Optional OptErr = Importer->getImportDeclErrorIfAny(FromX); ASSERT_FALSE(OptErr); // An error is set for f(). @@ -5645,7 +5685,7 @@ TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) { FromTU, functionDecl(hasName("f"))); OptErr = Importer->getImportDeclErrorIfAny(FromF); ASSERT_TRUE(OptErr); - EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); + EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct); // And any subsequent import should fail. FunctionDecl *ImportedF = Import(FromF, Lang_CXX03); EXPECT_FALSE(ImportedF); @@ -5716,18 +5756,18 @@ TEST_P(ErrorHandlingTest, // An error is set for X ... EXPECT_FALSE(ImportedX); ASTImporter *Importer = findFromTU(FromX)->Importer.get(); - Optional OptErr = Importer->getImportDeclErrorIfAny(FromX); + Optional OptErr = Importer->getImportDeclErrorIfAny(FromX); ASSERT_TRUE(OptErr); - EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); + EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct); } // ... but the node had been created. auto *ToXDef = FirstDeclMatcher().match( ToTU, cxxRecordDecl(hasName("X"), isDefinition())); // An error is set for "ToXDef" in the shared state. - Optional OptErr = + Optional OptErr = SharedStatePtr->getImportDeclErrorIfAny(ToXDef); ASSERT_TRUE(OptErr); - EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); + EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct); auto *ToXFwd = FirstDeclMatcher().match( ToTU, cxxRecordDecl(hasName("X"), unless(isDefinition()))); @@ -5759,10 +5799,10 @@ TEST_P(ErrorHandlingTest, // The import should fail. EXPECT_FALSE(ImportedX); ASTImporter *Importer = findFromTU(FromX)->Importer.get(); - Optional OptErr = Importer->getImportDeclErrorIfAny(FromX); + Optional OptErr = Importer->getImportDeclErrorIfAny(FromX); // And an error is set for this new X in the "from" ctx. ASSERT_TRUE(OptErr); - EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); + EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct); } } @@ -5799,9 +5839,9 @@ TEST_P(ErrorHandlingTest, ImportOfOverriddenMethods) { EXPECT_FALSE(Import(FromFooA, Lang_CXX11)); ASTImporter *Importer = findFromTU(FromFooA)->Importer.get(); auto CheckError = [&Importer](Decl *FromD) { - Optional OptErr = Importer->getImportDeclErrorIfAny(FromD); + Optional OptErr = Importer->getImportDeclErrorIfAny(FromD); ASSERT_TRUE(OptErr); - EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); + EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct); }; CheckError(FromFooA); EXPECT_FALSE(Import(FromFooB, Lang_CXX11)); @@ -6280,6 +6320,61 @@ TEST_P(ASTImporterOptionSpecificTestBase, struct ImportAutoFunctions : ASTImporterOptionSpecificTestBase {}; +TEST_P(ImportAutoFunctions, ReturnWithTemplateWithStructDeclaredInside1) { + Decl *FromTU = getTuDecl( + R"( + template struct Tmpl {}; + auto foo() { + struct X {}; + return Tmpl(); + } + )", + Lang_CXX14, "input0.cc"); + FunctionDecl *From = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("foo"))); + + FunctionDecl *To = Import(From, Lang_CXX14); + EXPECT_TRUE(To); + EXPECT_TRUE(isa(To->getReturnType())); +} + +TEST_P(ImportAutoFunctions, ReturnWithTemplateWithStructDeclaredInside2) { + Decl *FromTU = getTuDecl( + R"( + template struct Tmpl {}; + auto foo() { + struct X {}; + return Tmpl>(); + } + )", + Lang_CXX14, "input0.cc"); + FunctionDecl *From = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("foo"))); + + FunctionDecl *To = Import(From, Lang_CXX14); + EXPECT_TRUE(To); + EXPECT_TRUE(isa(To->getReturnType())); +} + +TEST_P(ImportAutoFunctions, ReturnWithTemplateWithTypedefDeclaredInside) { + Decl *FromTU = getTuDecl( + R"( + template struct Tmpl {}; + auto foo() { + struct X {}; + using x_type = X; + return Tmpl(); + } + )", + Lang_CXX14, "input0.cc"); + FunctionDecl *From = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("foo"))); + + FunctionDecl *To = Import(From, Lang_CXX14); + EXPECT_TRUE(To); + EXPECT_TRUE(isa(To->getReturnType())); +} + TEST_P(ImportAutoFunctions, ReturnWithTypedefDeclaredInside) { Decl *FromTU = getTuDecl( R"( diff --git a/clang/unittests/AST/ASTTraverserTest.cpp b/clang/unittests/AST/ASTTraverserTest.cpp index 9d32a3d4116d1..3553c3012cd4e 100644 --- a/clang/unittests/AST/ASTTraverserTest.cpp +++ b/clang/unittests/AST/ASTTraverserTest.cpp @@ -1157,6 +1157,46 @@ void decomposition() f = 42; } +typedef __typeof(sizeof(int)) size_t; + +struct Pair +{ + int x, y; +}; + +// Note: these utilities are required to force binding to tuple like structure +namespace std +{ + template + struct tuple_size + { + }; + + template <> + struct tuple_size + { + static constexpr size_t value = 2; + }; + + template + struct tuple_element + { + using type = int; + }; + +}; + +template +int &&get(Pair &&p); + +void decompTuple() +{ + Pair p{1, 2}; + auto [a, b] = p; + + a = 3; +} + )cpp", {"-std=c++20"}); @@ -1492,6 +1532,48 @@ DecompositionDecl '' |-BindingDecl 'f' |-BindingDecl 's' `-BindingDecl 't' +)cpp"); + } + + { + auto FN = ast_matchers::match( + functionDecl(hasName("decompTuple"), + hasDescendant(decompositionDecl().bind("decomp"))), + AST2->getASTContext()); + EXPECT_EQ(FN.size(), 1u); + + EXPECT_EQ( + dumpASTString(TK_AsIs, FN[0].getNodeAs("decomp")), + R"cpp( +DecompositionDecl '' +|-CXXConstructExpr +| `-ImplicitCastExpr +| `-DeclRefExpr 'p' +|-BindingDecl 'a' +| |-VarDecl 'a' +| | `-CallExpr +| | |-ImplicitCastExpr +| | | `-DeclRefExpr 'get' +| | `-ImplicitCastExpr +| | `-DeclRefExpr '' +| `-DeclRefExpr 'a' +`-BindingDecl 'b' + |-VarDecl 'b' + | `-CallExpr + | |-ImplicitCastExpr + | | `-DeclRefExpr 'get' + | `-ImplicitCastExpr + | `-DeclRefExpr '' + `-DeclRefExpr 'b' +)cpp"); + + EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, + FN[0].getNodeAs("decomp")), + R"cpp( +DecompositionDecl '' +|-DeclRefExpr 'p' +|-BindingDecl 'a' +`-BindingDecl 'b' )cpp"); } } diff --git a/clang/unittests/AST/AttrTest.cpp b/clang/unittests/AST/AttrTest.cpp index 38e723f3ee090..500e9cfa528b7 100644 --- a/clang/unittests/AST/AttrTest.cpp +++ b/clang/unittests/AST/AttrTest.cpp @@ -7,7 +7,10 @@ //===----------------------------------------------------------------------===// #include "clang/AST/Attr.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Basic/AttrKinds.h" +#include "clang/Tooling/Tooling.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -15,10 +18,154 @@ using namespace clang; namespace { +using clang::ast_matchers::constantExpr; +using clang::ast_matchers::equals; +using clang::ast_matchers::functionDecl; +using clang::ast_matchers::has; +using clang::ast_matchers::hasDescendant; +using clang::ast_matchers::hasName; +using clang::ast_matchers::integerLiteral; +using clang::ast_matchers::match; +using clang::ast_matchers::selectFirst; +using clang::ast_matchers::stringLiteral; +using clang::ast_matchers::varDecl; +using clang::tooling::buildASTFromCode; +using clang::tooling::buildASTFromCodeWithArgs; + TEST(Attr, Doc) { EXPECT_THAT(Attr::getDocumentation(attr::Used).str(), testing::HasSubstr("The compiler must emit the definition even " "if it appears to be unused")); } +const FunctionDecl *getFunctionNode(ASTUnit *AST, const std::string &Name) { + auto Result = + match(functionDecl(hasName(Name)).bind("fn"), AST->getASTContext()); + EXPECT_EQ(Result.size(), 1u); + return Result[0].getNodeAs("fn"); +} + +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"); +} + +template +void AssertAnnotatedAs(TypeLoc TL, llvm::StringRef annotation, + ModifiedTypeLoc &ModifiedTL, + const AnnotateTypeAttr **AnnotateOut = nullptr) { + const auto AttributedTL = TL.getAs(); + ASSERT_FALSE(AttributedTL.isNull()); + ModifiedTL = AttributedTL.getModifiedLoc().getAs(); + ASSERT_TRUE(ModifiedTL); + + ASSERT_NE(AttributedTL.getAttr(), nullptr); + const auto *Annotate = dyn_cast(AttributedTL.getAttr()); + ASSERT_NE(Annotate, nullptr); + EXPECT_EQ(Annotate->getAnnotation(), annotation); + if (AnnotateOut) { + *AnnotateOut = Annotate; + } +} + +TEST(Attr, AnnotateType) { + + // Test that the AnnotateType attribute shows up in the right places and that + // it stores its arguments correctly. + + auto AST = buildASTFromCode(R"cpp( + void f(int* [[clang::annotate_type("foo", "arg1", 2)]] *, + int [[clang::annotate_type("bar")]]); + + int [[clang::annotate_type("int")]] * [[clang::annotate_type("ptr")]] + array[10] [[clang::annotate_type("arr")]]; + + void (* [[clang::annotate_type("funcptr")]] fp)(void); + + struct S { int mem; }; + int [[clang::annotate_type("int")]] + S::* [[clang::annotate_type("ptr_to_mem")]] ptr_to_member = &S::mem; + )cpp"); + + { + const FunctionDecl *Func = getFunctionNode(AST.get(), "f"); + + // First parameter. + const auto PointerTL = Func->getParamDecl(0) + ->getTypeSourceInfo() + ->getTypeLoc() + .getAs(); + ASSERT_FALSE(PointerTL.isNull()); + PointerTypeLoc PointerPointerTL; + const AnnotateTypeAttr *Annotate; + AssertAnnotatedAs(PointerTL.getPointeeLoc(), "foo", PointerPointerTL, + &Annotate); + + EXPECT_EQ(Annotate->args_size(), 2u); + const auto *StringLit = selectFirst( + "str", match(constantExpr(hasDescendant(stringLiteral().bind("str"))), + *Annotate->args_begin()[0], AST->getASTContext())); + ASSERT_NE(StringLit, nullptr); + EXPECT_EQ(StringLit->getString(), "arg1"); + EXPECT_EQ(match(constantExpr(has(integerLiteral(equals(2u)).bind("int"))), + *Annotate->args_begin()[1], AST->getASTContext()) + .size(), + 1u); + + // Second parameter. + BuiltinTypeLoc IntTL; + AssertAnnotatedAs(Func->getParamDecl(1)->getTypeSourceInfo()->getTypeLoc(), + "bar", IntTL); + EXPECT_EQ(IntTL.getType(), AST->getASTContext().IntTy); + } + + { + const VarDecl *Var = getVariableNode(AST.get(), "array"); + + ArrayTypeLoc ArrayTL; + AssertAnnotatedAs(Var->getTypeSourceInfo()->getTypeLoc(), "arr", ArrayTL); + PointerTypeLoc PointerTL; + AssertAnnotatedAs(ArrayTL.getElementLoc(), "ptr", PointerTL); + BuiltinTypeLoc IntTL; + AssertAnnotatedAs(PointerTL.getPointeeLoc(), "int", IntTL); + EXPECT_EQ(IntTL.getType(), AST->getASTContext().IntTy); + } + + { + const VarDecl *Var = getVariableNode(AST.get(), "fp"); + + PointerTypeLoc PointerTL; + AssertAnnotatedAs(Var->getTypeSourceInfo()->getTypeLoc(), "funcptr", + PointerTL); + ASSERT_TRUE( + PointerTL.getPointeeLoc().IgnoreParens().getAs()); + } + + { + const VarDecl *Var = getVariableNode(AST.get(), "ptr_to_member"); + + MemberPointerTypeLoc MemberPointerTL; + AssertAnnotatedAs(Var->getTypeSourceInfo()->getTypeLoc(), "ptr_to_mem", + MemberPointerTL); + BuiltinTypeLoc IntTL; + AssertAnnotatedAs(MemberPointerTL.getPointeeLoc(), "int", IntTL); + EXPECT_EQ(IntTL.getType(), AST->getASTContext().IntTy); + } + + // Test type annotation on an `__auto_type` type in C mode. + AST = buildASTFromCodeWithArgs(R"c( + __auto_type [[clang::annotate_type("auto")]] auto_var = 1; + )c", + {"-fdouble-square-bracket-attributes"}, + "input.c"); + + { + const VarDecl *Var = getVariableNode(AST.get(), "auto_var"); + + AutoTypeLoc AutoTL; + AssertAnnotatedAs(Var->getTypeSourceInfo()->getTypeLoc(), "auto", AutoTL); + } +} + } // namespace diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index 3901a48245eb7..6723e1657c1ab 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -2095,18 +2095,8 @@ TEST_P(ASTMatchersTest, QualifiedTypeLocTest_BindsToConstIntVarDecl) { } TEST_P(ASTMatchersTest, QualifiedTypeLocTest_BindsToConstIntFunctionDecl) { - StringRef Code = R"( - const int f() { return 5; } - )"; - // In C++, the qualified return type is retained. - EXPECT_TRUE(matchesConditionally( - Code, qualifiedTypeLoc(loc(asString("const int"))), true, langAnyCxx())); - // In C, the qualifications on the return type are dropped, so we expect it - // to match 'int' rather than 'const int'. - EXPECT_TRUE(matchesConditionally( - Code, qualifiedTypeLoc(loc(asString("const int"))), false, langAnyC())); - EXPECT_TRUE( - matchesConditionally(Code, loc(asString("int")), true, langAnyC())); + EXPECT_TRUE(matches("const int f() { return 5; }", + qualifiedTypeLoc(loc(asString("const int"))))); } TEST_P(ASTMatchersTest, QualifiedTypeLocTest_DoesNotBindToUnqualifiedVarDecl) { diff --git a/clang/unittests/ASTMatchers/ASTMatchersTest.h b/clang/unittests/ASTMatchers/ASTMatchersTest.h index 657ed46b082cc..79c6186054839 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTest.h +++ b/clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -60,17 +60,6 @@ class VerifyMatch : public MatchFinder::MatchCallback { const std::unique_ptr FindResultReviewer; }; -inline ArrayRef langAnyC() { - static const TestLanguage Result[] = {Lang_C89, Lang_C99}; - return ArrayRef(Result); -} - -inline ArrayRef langAnyCxx() { - static const TestLanguage Result[] = {Lang_CXX03, Lang_CXX11, Lang_CXX14, - Lang_CXX17, Lang_CXX20}; - return ArrayRef(Result); -} - inline ArrayRef langCxx11OrLater() { static const TestLanguage Result[] = {Lang_CXX11, Lang_CXX14, Lang_CXX17, Lang_CXX20}; diff --git a/clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp b/clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp index 9535f99c5aea4..797b2849acedf 100644 --- a/clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp @@ -1,4 +1,4 @@ -//===- unittests/Analysis/FlowSensitive/SingelVarConstantPropagation.cpp --===// +//===- unittests/Analysis/FlowSensitive/MultiVarConstantPropagation.cpp --===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp b/clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp index e14724931a7c0..842e3502efaaf 100644 --- a/clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp @@ -1,4 +1,4 @@ -//===- unittests/Analysis/FlowSensitive/SingelVarConstantPropagation.cpp --===// +//===- unittests/Analysis/FlowSensitive/SingleVarConstantPropagation.cpp --===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index efea7797b45fb..e3c97367b17ca 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -122,24 +122,24 @@ TEST_F(TransferTest, IntVarDecl) { // [[p]] } )"; - runDataflow( - Code, [](llvm::ArrayRef< - std::pair>> - Results, - ASTContext &ASTCtx) { - ASSERT_THAT(Results, ElementsAre(Pair("p", _))); - const Environment &Env = Results[0].second.Env; + runDataflow(Code, + [](llvm::ArrayRef< + std::pair>> + Results, + ASTContext &ASTCtx) { + ASSERT_THAT(Results, ElementsAre(Pair("p", _))); + const Environment &Env = Results[0].second.Env; - const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); - ASSERT_THAT(FooDecl, NotNull()); + const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); + ASSERT_THAT(FooDecl, NotNull()); - const StorageLocation *FooLoc = - Env.getStorageLocation(*FooDecl, SkipPast::None); - ASSERT_TRUE(isa_and_nonnull(FooLoc)); + const StorageLocation *FooLoc = + Env.getStorageLocation(*FooDecl, SkipPast::None); + ASSERT_TRUE(isa_and_nonnull(FooLoc)); - const Value *FooVal = Env.getValue(*FooLoc); - EXPECT_TRUE(isa_and_nonnull(FooVal)); - }); + const Value *FooVal = Env.getValue(*FooLoc); + EXPECT_TRUE(isa_and_nonnull(FooVal)); + }); } TEST_F(TransferTest, StructVarDecl) { @@ -310,11 +310,11 @@ TEST_F(TransferTest, ReferenceVarDecl) { const ReferenceValue *FooVal = cast(Env.getValue(*FooLoc)); - const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); - EXPECT_TRUE(isa(&FooPointeeLoc)); + const StorageLocation &FooReferentLoc = FooVal->getReferentLoc(); + EXPECT_TRUE(isa(&FooReferentLoc)); - const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); - EXPECT_TRUE(isa_and_nonnull(FooPointeeVal)); + const Value *FooReferentVal = Env.getValue(FooReferentLoc); + EXPECT_TRUE(isa_and_nonnull(FooReferentVal)); }); } @@ -397,31 +397,31 @@ TEST_F(TransferTest, SelfReferentialReferenceVarDecl) { const auto *FooLoc = cast( Env.getStorageLocation(*FooDecl, SkipPast::None)); const auto *FooVal = cast(Env.getValue(*FooLoc)); - const auto *FooPointeeVal = - cast(Env.getValue(FooVal->getPointeeLoc())); + const auto *FooReferentVal = + cast(Env.getValue(FooVal->getReferentLoc())); const auto *BarVal = - cast(FooPointeeVal->getChild(*BarDecl)); - const auto *BarPointeeVal = - cast(Env.getValue(BarVal->getPointeeLoc())); + cast(FooReferentVal->getChild(*BarDecl)); + const auto *BarReferentVal = + cast(Env.getValue(BarVal->getReferentLoc())); const auto *FooRefVal = - cast(BarPointeeVal->getChild(*FooRefDecl)); - const StorageLocation &FooRefPointeeLoc = FooRefVal->getPointeeLoc(); - EXPECT_THAT(Env.getValue(FooRefPointeeLoc), IsNull()); + cast(BarReferentVal->getChild(*FooRefDecl)); + const StorageLocation &FooReferentLoc = FooRefVal->getReferentLoc(); + EXPECT_THAT(Env.getValue(FooReferentLoc), IsNull()); const auto *FooPtrVal = - cast(BarPointeeVal->getChild(*FooPtrDecl)); + cast(BarReferentVal->getChild(*FooPtrDecl)); const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc(); EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull()); const auto *BazRefVal = - cast(BarPointeeVal->getChild(*BazRefDecl)); - const StorageLocation &BazRefPointeeLoc = BazRefVal->getPointeeLoc(); - EXPECT_THAT(Env.getValue(BazRefPointeeLoc), NotNull()); + cast(BarReferentVal->getChild(*BazRefDecl)); + const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc(); + EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull()); const auto *BazPtrVal = - cast(BarPointeeVal->getChild(*BazPtrDecl)); + cast(BarReferentVal->getChild(*BazPtrDecl)); const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc(); EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); }); @@ -564,8 +564,8 @@ TEST_F(TransferTest, SelfReferentialPointerVarDecl) { const auto *FooRefVal = cast(BarPointeeVal->getChild(*FooRefDecl)); - const StorageLocation &FooRefPointeeLoc = FooRefVal->getPointeeLoc(); - EXPECT_THAT(Env.getValue(FooRefPointeeLoc), IsNull()); + const StorageLocation &FooReferentLoc = FooRefVal->getReferentLoc(); + EXPECT_THAT(Env.getValue(FooReferentLoc), IsNull()); const auto *FooPtrVal = cast(BarPointeeVal->getChild(*FooPtrDecl)); @@ -574,8 +574,8 @@ TEST_F(TransferTest, SelfReferentialPointerVarDecl) { const auto *BazRefVal = cast(BarPointeeVal->getChild(*BazRefDecl)); - const StorageLocation &BazRefPointeeLoc = BazRefVal->getPointeeLoc(); - EXPECT_THAT(Env.getValue(BazRefPointeeLoc), NotNull()); + const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc(); + EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull()); const auto *BazPtrVal = cast(BarPointeeVal->getChild(*BazPtrDecl)); @@ -952,31 +952,31 @@ TEST_F(TransferTest, ReferenceParamDecl) { // [[p]] } )"; - runDataflow(Code, - [](llvm::ArrayRef< - std::pair>> - Results, - ASTContext &ASTCtx) { - ASSERT_THAT(Results, ElementsAre(Pair("p", _))); - const Environment &Env = Results[0].second.Env; + runDataflow( + Code, [](llvm::ArrayRef< + std::pair>> + Results, + ASTContext &ASTCtx) { + ASSERT_THAT(Results, ElementsAre(Pair("p", _))); + const Environment &Env = Results[0].second.Env; - const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); - ASSERT_THAT(FooDecl, NotNull()); + const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); + ASSERT_THAT(FooDecl, NotNull()); - const StorageLocation *FooLoc = - Env.getStorageLocation(*FooDecl, SkipPast::None); - ASSERT_TRUE(isa_and_nonnull(FooLoc)); + const StorageLocation *FooLoc = + Env.getStorageLocation(*FooDecl, SkipPast::None); + ASSERT_TRUE(isa_and_nonnull(FooLoc)); - const ReferenceValue *FooVal = - dyn_cast(Env.getValue(*FooLoc)); - ASSERT_THAT(FooVal, NotNull()); + const ReferenceValue *FooVal = + dyn_cast(Env.getValue(*FooLoc)); + ASSERT_THAT(FooVal, NotNull()); - const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); - EXPECT_TRUE(isa(&FooPointeeLoc)); + const StorageLocation &FooReferentLoc = FooVal->getReferentLoc(); + EXPECT_TRUE(isa(&FooReferentLoc)); - const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); - EXPECT_TRUE(isa_and_nonnull(FooPointeeVal)); - }); + const Value *FooReferentVal = Env.getValue(FooReferentLoc); + EXPECT_TRUE(isa_and_nonnull(FooReferentVal)); + }); } TEST_F(TransferTest, PointerParamDecl) { @@ -1378,13 +1378,13 @@ TEST_F(TransferTest, ReferenceMember) { Env.getStorageLocation(*FooDecl, SkipPast::None)); const auto *FooVal = cast(Env.getValue(*FooLoc)); const auto *BarVal = cast(FooVal->getChild(*BarDecl)); - const auto *BarPointeeVal = - cast(Env.getValue(BarVal->getPointeeLoc())); + const auto *BarReferentVal = + cast(Env.getValue(BarVal->getReferentLoc())); const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); ASSERT_THAT(BazDecl, NotNull()); - EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarPointeeVal); + EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarReferentVal); }); } @@ -1752,7 +1752,7 @@ TEST_F(TransferTest, DefaultInitializerReference) { const auto *QuxVal = cast(Env.getValue(*QuxDecl, SkipPast::None)); - EXPECT_EQ(&QuxVal->getPointeeLoc(), &FooVal->getPointeeLoc()); + EXPECT_EQ(&QuxVal->getReferentLoc(), &FooVal->getReferentLoc()); }); } @@ -2299,7 +2299,7 @@ TEST_F(TransferTest, DerefDependentPtr) { cast(Env.getValue(*FooDecl, SkipPast::None)); const auto *BarVal = cast(Env.getValue(*BarDecl, SkipPast::None)); - EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); + EXPECT_EQ(&BarVal->getReferentLoc(), &FooVal->getPointeeLoc()); }); } @@ -3327,23 +3327,23 @@ TEST_F(TransferTest, LoopWithStructReferenceAssignmentConverges) { ASSERT_THAT(LDecl, NotNull()); // Inner. - auto *LVal = dyn_cast( - InnerEnv.getValue(*LDecl, SkipPast::None)); + auto *LVal = + dyn_cast(InnerEnv.getValue(*LDecl, SkipPast::None)); ASSERT_THAT(LVal, NotNull()); EXPECT_EQ(&LVal->getPointeeLoc(), InnerEnv.getStorageLocation(*ValDecl, SkipPast::Reference)); // Outer. - LVal = dyn_cast( - OuterEnv.getValue(*LDecl, SkipPast::None)); + LVal = + dyn_cast(OuterEnv.getValue(*LDecl, SkipPast::None)); ASSERT_THAT(LVal, NotNull()); // The loop body may not have been executed, so we should not conclude // that `l` points to `val`. EXPECT_NE(&LVal->getPointeeLoc(), OuterEnv.getStorageLocation(*ValDecl, SkipPast::Reference)); -}); + }); } TEST_F(TransferTest, DoesNotCrashOnUnionThisExpr) { @@ -3369,4 +3369,192 @@ TEST_F(TransferTest, DoesNotCrashOnUnionThisExpr) { LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator="); } +TEST_F(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) { + std::string Code = R"( + struct A { + int Foo; + int Bar; + }; + + void target() { + int Qux; + A Baz; + Baz.Foo = Qux; + auto &FooRef = Baz.Foo; + auto &BarRef = Baz.Bar; + auto &[BoundFooRef, BoundBarRef] = Baz; + // [[p]] + } + )"; + runDataflow( + Code, [](llvm::ArrayRef< + std::pair>> + Results, + ASTContext &ASTCtx) { + ASSERT_THAT(Results, ElementsAre(Pair("p", _))); + const Environment &Env = Results[0].second.Env; + + const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); + ASSERT_THAT(FooRefDecl, NotNull()); + + const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); + ASSERT_THAT(BarRefDecl, NotNull()); + + const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); + ASSERT_THAT(QuxDecl, NotNull()); + + const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); + ASSERT_THAT(BoundFooRefDecl, NotNull()); + + const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); + ASSERT_THAT(BoundBarRefDecl, NotNull()); + + const StorageLocation *FooRefLoc = + Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); + ASSERT_THAT(FooRefLoc, NotNull()); + + const StorageLocation *BarRefLoc = + Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); + ASSERT_THAT(BarRefLoc, NotNull()); + + const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); + ASSERT_THAT(QuxVal, NotNull()); + + const StorageLocation *BoundFooRefLoc = + Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference); + EXPECT_EQ(BoundFooRefLoc, FooRefLoc); + + const StorageLocation *BoundBarRefLoc = + Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference); + EXPECT_EQ(BoundBarRefLoc, BarRefLoc); + + EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal); + }); +} + +TEST_F(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) { + std::string Code = R"( + struct A { + int &Foo; + int &Bar; + }; + + void target(A Baz) { + int Qux; + Baz.Foo = Qux; + auto &FooRef = Baz.Foo; + auto &BarRef = Baz.Bar; + auto &[BoundFooRef, BoundBarRef] = Baz; + // [[p]] + } + )"; + runDataflow( + Code, [](llvm::ArrayRef< + std::pair>> + Results, + ASTContext &ASTCtx) { + ASSERT_THAT(Results, ElementsAre(Pair("p", _))); + const Environment &Env = Results[0].second.Env; + + const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); + ASSERT_THAT(FooRefDecl, NotNull()); + + const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); + ASSERT_THAT(BarRefDecl, NotNull()); + + const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); + ASSERT_THAT(QuxDecl, NotNull()); + + const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); + ASSERT_THAT(BoundFooRefDecl, NotNull()); + + const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); + ASSERT_THAT(BoundBarRefDecl, NotNull()); + + const StorageLocation *FooRefLoc = + Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); + ASSERT_THAT(FooRefLoc, NotNull()); + + const StorageLocation *BarRefLoc = + Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); + ASSERT_THAT(BarRefLoc, NotNull()); + + const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); + ASSERT_THAT(QuxVal, NotNull()); + + const StorageLocation *BoundFooRefLoc = + Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference); + EXPECT_EQ(BoundFooRefLoc, FooRefLoc); + + const StorageLocation *BoundBarRefLoc = + Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference); + EXPECT_EQ(BoundBarRefLoc, BarRefLoc); + + EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal); + }); +} + +TEST_F(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) { + std::string Code = R"( + struct A { + int Foo; + int Bar; + }; + + void target() { + int Qux; + A Baz; + Baz.Foo = Qux; + auto &FooRef = Baz.Foo; + auto &BarRef = Baz.Bar; + auto [BoundFoo, BoundBar] = Baz; + // [[p]] + } + )"; + runDataflow( + Code, [](llvm::ArrayRef< + std::pair>> + Results, + ASTContext &ASTCtx) { + ASSERT_THAT(Results, ElementsAre(Pair("p", _))); + const Environment &Env = Results[0].second.Env; + + const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); + ASSERT_THAT(FooRefDecl, NotNull()); + + const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); + ASSERT_THAT(BarRefDecl, NotNull()); + + const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); + ASSERT_THAT(BoundFooDecl, NotNull()); + + const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); + ASSERT_THAT(BoundBarDecl, NotNull()); + + const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); + ASSERT_THAT(QuxDecl, NotNull()); + + const StorageLocation *FooRefLoc = + Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); + ASSERT_THAT(FooRefLoc, NotNull()); + + const StorageLocation *BarRefLoc = + Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); + ASSERT_THAT(BarRefLoc, NotNull()); + + const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); + ASSERT_THAT(QuxVal, NotNull()); + + const StorageLocation *BoundFooLoc = + Env.getStorageLocation(*BoundFooDecl, SkipPast::Reference); + EXPECT_NE(BoundFooLoc, FooRefLoc); + + const StorageLocation *BoundBarLoc = + Env.getStorageLocation(*BoundBarDecl, SkipPast::Reference); + EXPECT_NE(BoundBarLoc, BarRefLoc); + + EXPECT_EQ(Env.getValue(*BoundFooDecl, SkipPast::Reference), QuxVal); + }); +} + } // namespace diff --git a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp index 2509aa3b9d8dd..594764b4e71bd 100644 --- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp @@ -312,7 +312,7 @@ class SpecialBoolAnalysis if (const auto *E = selectFirst( "call", match(cxxConstructExpr(HasSpecialBoolType).bind("call"), *S, getASTContext()))) { - auto &ConstructorVal = *cast(Env.createValue(E->getType())); + auto &ConstructorVal = *Env.createValue(E->getType()); ConstructorVal.setProperty("is_set", Env.getBoolLiteralValue(false)); Env.setValue(*Env.getStorageLocation(*E, SkipPast::None), ConstructorVal); } else if (const auto *E = selectFirst( @@ -327,8 +327,7 @@ class SpecialBoolAnalysis Env.getStorageLocation(*Object, SkipPast::ReferenceThenPointer); assert(ObjectLoc != nullptr); - auto &ConstructorVal = - *cast(Env.createValue(Object->getType())); + auto &ConstructorVal = *Env.createValue(Object->getType()); ConstructorVal.setProperty("is_set", Env.getBoolLiteralValue(true)); Env.setValue(*ObjectLoc, ConstructorVal); } @@ -342,13 +341,11 @@ class SpecialBoolAnalysis Decl->getName() != "SpecialBool") return false; - auto *IsSet1 = cast_or_null( - cast(&Val1)->getProperty("is_set")); + auto *IsSet1 = cast_or_null(Val1.getProperty("is_set")); if (IsSet1 == nullptr) return true; - auto *IsSet2 = cast_or_null( - cast(&Val2)->getProperty("is_set")); + auto *IsSet2 = cast_or_null(Val2.getProperty("is_set")); if (IsSet2 == nullptr) return false; @@ -365,18 +362,16 @@ class SpecialBoolAnalysis Decl->getName() != "SpecialBool") return true; - auto *IsSet1 = cast_or_null( - cast(&Val1)->getProperty("is_set")); + auto *IsSet1 = cast_or_null(Val1.getProperty("is_set")); if (IsSet1 == nullptr) return true; - auto *IsSet2 = cast_or_null( - cast(&Val2)->getProperty("is_set")); + auto *IsSet2 = cast_or_null(Val2.getProperty("is_set")); if (IsSet2 == nullptr) return true; auto &IsSet = MergedEnv.makeAtomicBoolValue(); - cast(&MergedVal)->setProperty("is_set", IsSet); + MergedVal.setProperty("is_set", IsSet); if (Env1.flowConditionImplies(*IsSet1) && Env2.flowConditionImplies(*IsSet2)) MergedEnv.addToFlowCondition(IsSet); @@ -426,32 +421,31 @@ TEST_F(JoinFlowConditionsTest, JoinDistinctButProvablyEquivalentValues) { /*[[p4]]*/ } )"; - runDataflow(Code, - [](llvm::ArrayRef< - std::pair>> - Results, - ASTContext &ASTCtx) { - ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _), - Pair("p2", _), Pair("p1", _))); - const Environment &Env1 = Results[3].second.Env; - const Environment &Env2 = Results[2].second.Env; - const Environment &Env3 = Results[1].second.Env; - const Environment &Env4 = Results[0].second.Env; + runDataflow( + Code, [](llvm::ArrayRef< + std::pair>> + Results, + ASTContext &ASTCtx) { + ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _), + Pair("p2", _), Pair("p1", _))); + const Environment &Env1 = Results[3].second.Env; + const Environment &Env2 = Results[2].second.Env; + const Environment &Env3 = Results[1].second.Env; + const Environment &Env4 = Results[0].second.Env; - const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); - ASSERT_THAT(FooDecl, NotNull()); + const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); + ASSERT_THAT(FooDecl, NotNull()); - auto GetFooValue = [FooDecl](const Environment &Env) { - return cast( - cast(Env.getValue(*FooDecl, SkipPast::None)) - ->getProperty("is_set")); - }; + auto GetFooValue = [FooDecl](const Environment &Env) { + return cast( + Env.getValue(*FooDecl, SkipPast::None)->getProperty("is_set")); + }; - EXPECT_FALSE(Env1.flowConditionImplies(*GetFooValue(Env1))); - EXPECT_TRUE(Env2.flowConditionImplies(*GetFooValue(Env2))); - EXPECT_TRUE(Env3.flowConditionImplies(*GetFooValue(Env3))); - EXPECT_TRUE(Env4.flowConditionImplies(*GetFooValue(Env3))); - }); + EXPECT_FALSE(Env1.flowConditionImplies(*GetFooValue(Env1))); + EXPECT_TRUE(Env2.flowConditionImplies(*GetFooValue(Env2))); + EXPECT_TRUE(Env3.flowConditionImplies(*GetFooValue(Env3))); + EXPECT_TRUE(Env4.flowConditionImplies(*GetFooValue(Env3))); + }); } class OptionalIntAnalysis @@ -470,7 +464,7 @@ class OptionalIntAnalysis if (const auto *E = selectFirst( "call", match(cxxConstructExpr(HasOptionalIntType).bind("call"), *S, getASTContext()))) { - auto &ConstructorVal = *cast(Env.createValue(E->getType())); + auto &ConstructorVal = *Env.createValue(E->getType()); ConstructorVal.setProperty("has_value", Env.getBoolLiteralValue(false)); Env.setValue(*Env.getStorageLocation(*E, SkipPast::None), ConstructorVal); } else if (const auto *E = selectFirst( @@ -487,8 +481,7 @@ class OptionalIntAnalysis Env.getStorageLocation(*Object, SkipPast::ReferenceThenPointer); assert(ObjectLoc != nullptr); - auto &ConstructorVal = - *cast(Env.createValue(Object->getType())); + auto &ConstructorVal = *Env.createValue(Object->getType()); ConstructorVal.setProperty("has_value", Env.getBoolLiteralValue(true)); Env.setValue(*ObjectLoc, ConstructorVal); } @@ -502,8 +495,7 @@ class OptionalIntAnalysis Type->getAsCXXRecordDecl()->getQualifiedNameAsString() != "OptionalInt") return false; - return cast(&Val1)->getProperty("has_value") == - cast(&Val2)->getProperty("has_value"); + return Val1.getProperty("has_value") == Val2.getProperty("has_value"); } bool merge(QualType Type, const Value &Val1, const Environment &Env1, @@ -514,20 +506,18 @@ class OptionalIntAnalysis Type->getAsCXXRecordDecl()->getQualifiedNameAsString() != "OptionalInt") return false; - auto *HasValue1 = cast_or_null( - cast(&Val1)->getProperty("has_value")); + auto *HasValue1 = cast_or_null(Val1.getProperty("has_value")); if (HasValue1 == nullptr) return false; - auto *HasValue2 = cast_or_null( - cast(&Val2)->getProperty("has_value")); + auto *HasValue2 = cast_or_null(Val2.getProperty("has_value")); if (HasValue2 == nullptr) return false; if (HasValue1 == HasValue2) - cast(&MergedVal)->setProperty("has_value", *HasValue1); + MergedVal.setProperty("has_value", *HasValue1); else - cast(&MergedVal)->setProperty("has_value", HasValueTop); + MergedVal.setProperty("has_value", HasValueTop); return true; } @@ -598,7 +588,7 @@ TEST_F(WideningTest, JoinDistinctValuesWithDistinctProperties) { ASSERT_THAT(FooDecl, NotNull()); auto GetFooValue = [FooDecl](const Environment &Env) { - return cast(Env.getValue(*FooDecl, SkipPast::None)); + return Env.getValue(*FooDecl, SkipPast::None); }; EXPECT_EQ(GetFooValue(Env1)->getProperty("has_value"), @@ -627,34 +617,34 @@ TEST_F(WideningTest, JoinDistinctValuesWithSameProperties) { /*[[p4]]*/ } )"; - runDataflow( - Code, [](llvm::ArrayRef< - std::pair>> - Results, - ASTContext &ASTCtx) { - ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _), - Pair("p2", _), Pair("p1", _))); - const Environment &Env1 = Results[3].second.Env; - const Environment &Env2 = Results[2].second.Env; - const Environment &Env3 = Results[1].second.Env; - const Environment &Env4 = Results[0].second.Env; + runDataflow(Code, + [](llvm::ArrayRef< + std::pair>> + Results, + ASTContext &ASTCtx) { + ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _), + Pair("p2", _), Pair("p1", _))); + const Environment &Env1 = Results[3].second.Env; + const Environment &Env2 = Results[2].second.Env; + const Environment &Env3 = Results[1].second.Env; + const Environment &Env4 = Results[0].second.Env; - const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); - ASSERT_THAT(FooDecl, NotNull()); + const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); + ASSERT_THAT(FooDecl, NotNull()); - auto GetFooValue = [FooDecl](const Environment &Env) { - return cast(Env.getValue(*FooDecl, SkipPast::None)); - }; + auto GetFooValue = [FooDecl](const Environment &Env) { + return Env.getValue(*FooDecl, SkipPast::None); + }; - EXPECT_EQ(GetFooValue(Env1)->getProperty("has_value"), - &Env1.getBoolLiteralValue(false)); - EXPECT_EQ(GetFooValue(Env2)->getProperty("has_value"), - &Env2.getBoolLiteralValue(true)); - EXPECT_EQ(GetFooValue(Env3)->getProperty("has_value"), - &Env3.getBoolLiteralValue(true)); - EXPECT_EQ(GetFooValue(Env4)->getProperty("has_value"), - &Env4.getBoolLiteralValue(true)); - }); + EXPECT_EQ(GetFooValue(Env1)->getProperty("has_value"), + &Env1.getBoolLiteralValue(false)); + EXPECT_EQ(GetFooValue(Env2)->getProperty("has_value"), + &Env2.getBoolLiteralValue(true)); + EXPECT_EQ(GetFooValue(Env3)->getProperty("has_value"), + &Env3.getBoolLiteralValue(true)); + EXPECT_EQ(GetFooValue(Env4)->getProperty("has_value"), + &Env4.getBoolLiteralValue(true)); + }); } TEST_F(WideningTest, DistinctPointersToTheSameLocationAreEquivalent) { @@ -715,8 +705,7 @@ TEST_F(WideningTest, DistinctValuesWithSamePropertiesAreEquivalent) { const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); ASSERT_THAT(FooDecl, NotNull()); - const auto *FooVal = - cast(Env.getValue(*FooDecl, SkipPast::None)); + const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); EXPECT_EQ(FooVal->getProperty("has_value"), &Env.getBoolLiteralValue(true)); }); diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp index a501f549851f9..912754ebe8b6e 100644 --- a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp @@ -179,6 +179,11 @@ struct is_void : is_same::type> {}; namespace detail { +template +auto try_add_lvalue_reference(int) -> type_identity; +template +auto try_add_lvalue_reference(...) -> type_identity; + template auto try_add_rvalue_reference(int) -> type_identity; template @@ -186,6 +191,10 @@ auto try_add_rvalue_reference(...) -> type_identity; } // namespace detail +template +struct add_lvalue_reference : decltype(detail::try_add_lvalue_reference(0)) { +}; + template struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference(0)) { }; @@ -1852,7 +1861,26 @@ TEST_P(UncheckedOptionalAccessTest, Emplace) { )", UnorderedElementsAre(Pair("check", "safe"))); - // FIXME: Add tests that call `emplace` in conditional branches. + // FIXME: Add tests that call `emplace` in conditional branches: + // ExpectLatticeChecksFor( + // R"( + // #include "unchecked_optional_access_test.h" + // + // void target($ns::$optional opt, bool b) { + // if (b) { + // opt.emplace(0); + // } + // if (b) { + // opt.value(); + // /*[[check-1]]*/ + // } else { + // opt.value(); + // /*[[check-2]]*/ + // } + // } + // )", + // UnorderedElementsAre(Pair("check-1", "safe"), + // Pair("check-2", "unsafe: input.cc:12:9"))); } TEST_P(UncheckedOptionalAccessTest, Reset) { @@ -1883,7 +1911,27 @@ TEST_P(UncheckedOptionalAccessTest, Reset) { )", UnorderedElementsAre(Pair("check", "unsafe: input.cc:7:9"))); - // FIXME: Add tests that call `reset` in conditional branches. + // FIXME: Add tests that call `reset` in conditional branches: + // ExpectLatticeChecksFor( + // R"( + // #include "unchecked_optional_access_test.h" + // + // void target(bool b) { + // $ns::$optional opt = $ns::make_optional(0); + // if (b) { + // opt.reset(); + // } + // if (b) { + // opt.value(); + // /*[[check-1]]*/ + // } else { + // opt.value(); + // /*[[check-2]]*/ + // } + // } + // )", + // UnorderedElementsAre(Pair("check-1", "unsafe: input.cc:10:9"), + // Pair("check-2", "safe"))); } TEST_P(UncheckedOptionalAccessTest, ValueAssignment) { @@ -2150,8 +2198,473 @@ TEST_P(UncheckedOptionalAccessTest, UniquePtrToStructWithOptionalField) { UnorderedElementsAre(Pair("check-1", "safe"), Pair("check-2", "safe"))); } +TEST_P(UncheckedOptionalAccessTest, CallReturningOptional) { + ExpectLatticeChecksFor( + R"( + #include "unchecked_optional_access_test.h" + + $ns::$optional MakeOpt(); + + void target() { + $ns::$optional opt = 0; + opt = MakeOpt(); + opt.value(); + /*[[check-1]]*/ + } + )", + UnorderedElementsAre(Pair("check-1", "unsafe: input.cc:9:7"))); + ExpectLatticeChecksFor( + R"( + #include "unchecked_optional_access_test.h" + + const $ns::$optional& MakeOpt(); + + void target() { + $ns::$optional opt = 0; + opt = MakeOpt(); + opt.value(); + /*[[check-2]]*/ + } + )", + UnorderedElementsAre(Pair("check-2", "unsafe: input.cc:9:7"))); + + ExpectLatticeChecksFor( + R"( + #include "unchecked_optional_access_test.h" + + using IntOpt = $ns::$optional; + IntOpt MakeOpt(); + + void target() { + IntOpt opt = 0; + opt = MakeOpt(); + opt.value(); + /*[[check-3]]*/ + } + )", + UnorderedElementsAre(Pair("check-3", "unsafe: input.cc:10:7"))); + + ExpectLatticeChecksFor( + R"( + #include "unchecked_optional_access_test.h" + + using IntOpt = $ns::$optional; + const IntOpt& MakeOpt(); + + void target() { + IntOpt opt = 0; + opt = MakeOpt(); + opt.value(); + /*[[check-4]]*/ + } + )", + UnorderedElementsAre(Pair("check-4", "unsafe: input.cc:10:7"))); +} + +// Verifies that the model sees through aliases. +TEST_P(UncheckedOptionalAccessTest, WithAlias) { + ExpectLatticeChecksFor( + R"( + #include "unchecked_optional_access_test.h" + + template + using MyOptional = $ns::$optional; + + void target(MyOptional opt) { + opt.value(); + /*[[check]]*/ + } + )", + UnorderedElementsAre(Pair("check", "unsafe: input.cc:8:7"))); +} + +TEST_P(UncheckedOptionalAccessTest, OptionalValueOptional) { + // Basic test that nested values are populated. We nest an optional because + // its easy to use in a test, but the type of the nested value shouldn't + // matter. + ExpectLatticeChecksFor( + R"( + #include "unchecked_optional_access_test.h" + + using Foo = $ns::$optional; + + void target($ns::$optional foo) { + if (foo && *foo) { + foo->value(); + /*[[access]]*/ + } + } + )", + UnorderedElementsAre(Pair("access", "safe"))); + + // Mutation is supported for nested values. + ExpectLatticeChecksFor( + R"( + #include "unchecked_optional_access_test.h" + + using Foo = $ns::$optional; + + void target($ns::$optional foo) { + if (foo && *foo) { + foo->reset(); + foo->value(); + /*[[reset]]*/ + } + } + )", + UnorderedElementsAre(Pair("reset", "unsafe: input.cc:9:9"))); +} + +// Tests that structs can be nested. We use an optional field because its easy +// to use in a test, but the type of the field shouldn't matter. +TEST_P(UncheckedOptionalAccessTest, OptionalValueStruct) { + ExpectLatticeChecksFor( + R"( + #include "unchecked_optional_access_test.h" + + struct Foo { + $ns::$optional opt; + }; + + void target($ns::$optional foo) { + if (foo && foo->opt) { + foo->opt.value(); + /*[[access]]*/ + } + } + )", + UnorderedElementsAre(Pair("access", "safe"))); +} + +TEST_P(UncheckedOptionalAccessTest, OptionalValueInitialization) { + // FIXME: Fix when to initialize `value`. All unwrapping should be safe in + // this example, but `value` initialization is done multiple times during the + // fixpoint iterations and joining the environment won't correctly merge them. + ExpectLatticeChecksFor( + R"( + #include "unchecked_optional_access_test.h" + + using Foo = $ns::$optional; + + void target($ns::$optional foo, bool b) { + if (!foo.has_value()) return; + if (b) { + if (!foo->has_value()) return; + // We have created `foo.value()`. + foo->value(); + } else { + if (!foo->has_value()) return; + // We have created `foo.value()` again, in a different environment. + foo->value(); + } + // Now we merge the two values. UncheckedOptionalAccessModel::merge() will + // throw away the "value" property. + foo->value(); + /*[[merge]]*/ + } + )", + UnorderedElementsAre(Pair("merge", "unsafe: input.cc:19:7"))); +} + +TEST_P(UncheckedOptionalAccessTest, AssignThroughLvalueReferencePtr) { + ExpectLatticeChecksFor( + R"( + #include "unchecked_optional_access_test.h" + + template + struct smart_ptr { + typename std::add_lvalue_reference::type operator*() &; + }; + + void target() { + smart_ptr<$ns::$optional> x; + *x = $ns::nullopt; + (*x).value(); + /*[[check]]*/ + } + )", + UnorderedElementsAre(Pair("check", "unsafe: input.cc:12:7"))); +} + +TEST_P(UncheckedOptionalAccessTest, CorrelatedBranches) { + ExpectLatticeChecksFor(R"code( + #include "unchecked_optional_access_test.h" + + void target(bool b, $ns::$optional opt) { + if (b || opt.has_value()) { + if (!b) { + opt.value(); + /*[[check-1]]*/ + } + } + } + )code", + UnorderedElementsAre(Pair("check-1", "safe"))); + + ExpectLatticeChecksFor(R"code( + #include "unchecked_optional_access_test.h" + + void target(bool b, $ns::$optional opt) { + if (b && !opt.has_value()) return; + if (b) { + opt.value(); + /*[[check-2]]*/ + } + } + )code", + UnorderedElementsAre(Pair("check-2", "safe"))); + + ExpectLatticeChecksFor( + R"code( + #include "unchecked_optional_access_test.h" + + void target(bool b, $ns::$optional opt) { + if (opt.has_value()) b = true; + if (b) { + opt.value(); + /*[[check-3]]*/ + } + } + )code", + UnorderedElementsAre(Pair("check-3", "unsafe: input.cc:7:9"))); + + ExpectLatticeChecksFor(R"code( + #include "unchecked_optional_access_test.h" + + void target(bool b, $ns::$optional opt) { + if (b) return; + if (opt.has_value()) b = true; + if (b) { + opt.value(); + /*[[check-4]]*/ + } + } + )code", + UnorderedElementsAre(Pair("check-4", "safe"))); + + ExpectLatticeChecksFor(R"( + #include "unchecked_optional_access_test.h" + + void target(bool b, $ns::$optional opt) { + if (opt.has_value() == b) { + if (b) { + opt.value(); + /*[[check-5]]*/ + } + } + } + )", + UnorderedElementsAre(Pair("check-5", "safe"))); + + ExpectLatticeChecksFor(R"( + #include "unchecked_optional_access_test.h" + + void target(bool b, $ns::$optional opt) { + if (opt.has_value() != b) { + if (!b) { + opt.value(); + /*[[check-6]]*/ + } + } + } + )", + UnorderedElementsAre(Pair("check-6", "safe"))); + + ExpectLatticeChecksFor(R"( + #include "unchecked_optional_access_test.h" + + void target(bool b) { + $ns::$optional opt1 = $ns::nullopt; + $ns::$optional opt2; + if (b) { + opt2 = $ns::nullopt; + } else { + opt2 = $ns::nullopt; + } + if (opt2.has_value()) { + opt1.value(); + /*[[check]]*/ + } + } + )", + UnorderedElementsAre(Pair("check", "safe"))); + + // FIXME: Add support for operator==. + // ExpectLatticeChecksFor(R"( + // #include "unchecked_optional_access_test.h" + // + // void target($ns::$optional opt1, $ns::$optional opt2) { + // if (opt1 == opt2) { + // if (opt1.has_value()) { + // opt2.value(); + // /*[[check-7]]*/ + // } + // } + // } + // )", + // UnorderedElementsAre(Pair("check-7", "safe"))); +} + +TEST_P(UncheckedOptionalAccessTest, JoinDistinctValues) { + ExpectLatticeChecksFor( + R"code( + #include "unchecked_optional_access_test.h" + + void target(bool b) { + $ns::$optional opt; + if (b) { + opt = Make<$ns::$optional>(); + } else { + opt = Make<$ns::$optional>(); + } + if (opt.has_value()) { + opt.value(); + /*[[check-1]]*/ + } else { + opt.value(); + /*[[check-2]]*/ + } + } + )code", + UnorderedElementsAre(Pair("check-1", "safe"), + Pair("check-2", "unsafe: input.cc:15:9"))); + + ExpectLatticeChecksFor(R"code( + #include "unchecked_optional_access_test.h" + + void target(bool b) { + $ns::$optional opt; + if (b) { + opt = Make<$ns::$optional>(); + if (!opt.has_value()) return; + } else { + opt = Make<$ns::$optional>(); + if (!opt.has_value()) return; + } + opt.value(); + /*[[check-3]]*/ + } + )code", + UnorderedElementsAre(Pair("check-3", "safe"))); + + ExpectLatticeChecksFor( + R"code( + #include "unchecked_optional_access_test.h" + + void target(bool b) { + $ns::$optional opt; + if (b) { + opt = Make<$ns::$optional>(); + if (!opt.has_value()) return; + } else { + opt = Make<$ns::$optional>(); + } + opt.value(); + /*[[check-4]]*/ + } + )code", + UnorderedElementsAre(Pair("check-4", "unsafe: input.cc:12:7"))); + + ExpectLatticeChecksFor( + R"code( + #include "unchecked_optional_access_test.h" + + void target(bool b) { + $ns::$optional opt; + if (b) { + opt = 1; + } else { + opt = 2; + } + opt.value(); + /*[[check-5]]*/ + } + )code", + UnorderedElementsAre(Pair("check-5", "safe"))); + + ExpectLatticeChecksFor( + R"code( + #include "unchecked_optional_access_test.h" + + void target(bool b) { + $ns::$optional opt; + if (b) { + opt = 1; + } else { + opt = Make<$ns::$optional>(); + } + opt.value(); + /*[[check-6]]*/ + } + )code", + UnorderedElementsAre(Pair("check-6", "unsafe: input.cc:11:7"))); +} + +TEST_P(UncheckedOptionalAccessTest, ReassignValueInLoop) { + ExpectLatticeChecksFor(R"( + #include "unchecked_optional_access_test.h" + + void target() { + $ns::$optional opt = 3; + while (Make()) { + opt.value(); + /*[[check-1]]*/ + } + } + )", + UnorderedElementsAre(Pair("check-1", "safe"))); + + ExpectLatticeChecksFor(R"( + #include "unchecked_optional_access_test.h" + + void target() { + $ns::$optional opt = 3; + while (Make()) { + opt.value(); + /*[[check-2]]*/ + + opt = Make<$ns::$optional>(); + if (!opt.has_value()) return; + } + } + )", + UnorderedElementsAre(Pair("check-2", "safe"))); + + ExpectLatticeChecksFor( + R"( + #include "unchecked_optional_access_test.h" + + void target() { + $ns::$optional opt = 3; + while (Make()) { + opt.value(); + /*[[check-3]]*/ + + opt = Make<$ns::$optional>(); + } + } + )", + UnorderedElementsAre(Pair("check-3", "unsafe: input.cc:7:9"))); + + ExpectLatticeChecksFor( + R"( + #include "unchecked_optional_access_test.h" + + void target() { + $ns::$optional opt = 3; + while (Make()) { + opt.value(); + /*[[check-4]]*/ + + opt = Make<$ns::$optional>(); + if (!opt.has_value()) continue; + } + } + )", + UnorderedElementsAre(Pair("check-4", "unsafe: input.cc:7:9"))); +} + // FIXME: Add support for: // - constructors (copy, move) // - assignment operators (default, copy, move) // - invalidation (passing optional by non-const reference/pointer) -// - nested `optional` values diff --git a/clang/unittests/Basic/FileManagerTest.cpp b/clang/unittests/Basic/FileManagerTest.cpp index b8b12a91483d5..535d4d9e09c67 100644 --- a/clang/unittests/Basic/FileManagerTest.cpp +++ b/clang/unittests/Basic/FileManagerTest.cpp @@ -411,7 +411,7 @@ TEST_F(FileManagerTest, getVirtualFileWithDifferentName) { #endif // !_WIN32 static StringRef getSystemRoot() { - return is_style_windows(llvm::sys::path::Style::native) ? "C:/" : "/"; + return is_style_windows(llvm::sys::path::Style::native) ? "C:\\" : "/"; } TEST_F(FileManagerTest, makeAbsoluteUsesVFS) { diff --git a/clang/unittests/Driver/ToolChainTest.cpp b/clang/unittests/Driver/ToolChainTest.cpp index c652b093dc993..3637b10cdd667 100644 --- a/clang/unittests/Driver/ToolChainTest.cpp +++ b/clang/unittests/Driver/ToolChainTest.cpp @@ -18,6 +18,7 @@ #include "clang/Driver/Driver.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/MC/TargetRegistry.h" +#include "llvm/Support/Host.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" @@ -387,6 +388,28 @@ struct SimpleDiagnosticConsumer : public DiagnosticConsumer { std::vector> Errors; }; +static void validateTargetProfile(StringRef TargetProfile, + StringRef ExpectTriple, Driver &TheDriver, + DiagnosticsEngine &Diags) { + EXPECT_TRUE(TheDriver.BuildCompilation( + {"clang", "--driver-mode=dxc", TargetProfile.data(), "foo.hlsl"})); + EXPECT_STREQ(TheDriver.getTargetTriple().c_str(), ExpectTriple.data()); + EXPECT_EQ(Diags.getNumErrors(), 0u); +} + +static void validateTargetProfile(StringRef TargetProfile, + StringRef ExpectError, Driver &TheDriver, + DiagnosticsEngine &Diags, + SimpleDiagnosticConsumer *DiagConsumer, + unsigned NumOfErrors) { + EXPECT_TRUE(TheDriver.BuildCompilation( + {"clang", "--driver-mode=dxc", TargetProfile.data(), "foo.hlsl"})); + EXPECT_EQ(Diags.getNumErrors(), NumOfErrors); + EXPECT_STREQ(DiagConsumer->Errors.back().c_str(), ExpectError.data()); + Diags.Clear(); + DiagConsumer->clear(); +} + TEST(DxcModeTest, TargetProfileValidation) { IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); @@ -400,111 +423,40 @@ TEST(DxcModeTest, TargetProfileValidation) { IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagConsumer); Driver TheDriver("/bin/clang", "", Diags, "", InMemoryFileSystem); - std::unique_ptr C( - TheDriver.BuildCompilation({"clang", "--driver-mode=dxc", "foo.hlsl"})); - EXPECT_TRUE(C); - EXPECT_TRUE(!C->containsError()); - - auto &TC = C->getDefaultToolChain(); - bool ContainsError = false; - auto Args = TheDriver.ParseArgStrings({"-Tvs_6_0"}, false, ContainsError); - EXPECT_FALSE(ContainsError); - auto Triple = TC.ComputeEffectiveClangTriple(Args); - EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.0-vertex"); - EXPECT_EQ(Diags.getNumErrors(), 0u); - - Args = TheDriver.ParseArgStrings({"-Ths_6_1"}, false, ContainsError); - EXPECT_FALSE(ContainsError); - Triple = TC.ComputeEffectiveClangTriple(Args); - EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.1-hull"); - EXPECT_EQ(Diags.getNumErrors(), 0u); - - Args = TheDriver.ParseArgStrings({"-Tds_6_2"}, false, ContainsError); - EXPECT_FALSE(ContainsError); - Triple = TC.ComputeEffectiveClangTriple(Args); - EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.2-domain"); - EXPECT_EQ(Diags.getNumErrors(), 0u); - - Args = TheDriver.ParseArgStrings({"-Tds_6_2"}, false, ContainsError); - EXPECT_FALSE(ContainsError); - Triple = TC.ComputeEffectiveClangTriple(Args); - EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.2-domain"); - EXPECT_EQ(Diags.getNumErrors(), 0u); - - Args = TheDriver.ParseArgStrings({"-Tgs_6_3"}, false, ContainsError); - EXPECT_FALSE(ContainsError); - Triple = TC.ComputeEffectiveClangTriple(Args); - EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.3-geometry"); - EXPECT_EQ(Diags.getNumErrors(), 0u); - - Args = TheDriver.ParseArgStrings({"-Tps_6_4"}, false, ContainsError); - EXPECT_FALSE(ContainsError); - Triple = TC.ComputeEffectiveClangTriple(Args); - EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.4-pixel"); - EXPECT_EQ(Diags.getNumErrors(), 0u); - - Args = TheDriver.ParseArgStrings({"-Tcs_6_5"}, false, ContainsError); - EXPECT_FALSE(ContainsError); - Triple = TC.ComputeEffectiveClangTriple(Args); - EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.5-compute"); - EXPECT_EQ(Diags.getNumErrors(), 0u); - - Args = TheDriver.ParseArgStrings({"-Tms_6_6"}, false, ContainsError); - EXPECT_FALSE(ContainsError); - Triple = TC.ComputeEffectiveClangTriple(Args); - EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.6-mesh"); - EXPECT_EQ(Diags.getNumErrors(), 0u); - Args = TheDriver.ParseArgStrings({"-Tas_6_7"}, false, ContainsError); - EXPECT_FALSE(ContainsError); - Triple = TC.ComputeEffectiveClangTriple(Args); - EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.7-amplification"); - EXPECT_EQ(Diags.getNumErrors(), 0u); - - Args = TheDriver.ParseArgStrings({"-Tlib_6_x"}, false, ContainsError); - EXPECT_FALSE(ContainsError); - Triple = TC.ComputeEffectiveClangTriple(Args); - EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.15-library"); - EXPECT_EQ(Diags.getNumErrors(), 0u); + validateTargetProfile("-Tvs_6_0", "dxil--shadermodel6.0-vertex", TheDriver, + Diags); + validateTargetProfile("-Ths_6_1", "dxil--shadermodel6.1-hull", TheDriver, + Diags); + validateTargetProfile("-Tds_6_2", "dxil--shadermodel6.2-domain", TheDriver, + Diags); + validateTargetProfile("-Tds_6_2", "dxil--shadermodel6.2-domain", TheDriver, + Diags); + validateTargetProfile("-Tgs_6_3", "dxil--shadermodel6.3-geometry", TheDriver, + Diags); + validateTargetProfile("-Tps_6_4", "dxil--shadermodel6.4-pixel", TheDriver, + Diags); + validateTargetProfile("-Tcs_6_5", "dxil--shadermodel6.5-compute", TheDriver, + Diags); + validateTargetProfile("-Tms_6_6", "dxil--shadermodel6.6-mesh", TheDriver, + Diags); + validateTargetProfile("-Tas_6_7", "dxil--shadermodel6.7-amplification", + TheDriver, Diags); + validateTargetProfile("-Tlib_6_x", "dxil--shadermodel6.15-library", TheDriver, + Diags); // Invalid tests. - Args = TheDriver.ParseArgStrings({"-Tpss_6_1"}, false, ContainsError); - EXPECT_FALSE(ContainsError); - Triple = TC.ComputeEffectiveClangTriple(Args); - EXPECT_STREQ(Triple.c_str(), "unknown-unknown-shadermodel"); - EXPECT_EQ(Diags.getNumErrors(), 1u); - EXPECT_STREQ(DiagConsumer->Errors.back().c_str(), - "invalid profile : pss_6_1"); - Diags.Clear(); - DiagConsumer->clear(); - - Args = TheDriver.ParseArgStrings({"-Tps_6_x"}, false, ContainsError); - EXPECT_FALSE(ContainsError); - Triple = TC.ComputeEffectiveClangTriple(Args); - EXPECT_STREQ(Triple.c_str(), "unknown-unknown-shadermodel"); - EXPECT_EQ(Diags.getNumErrors(), 2u); - EXPECT_STREQ(DiagConsumer->Errors.back().c_str(), "invalid profile : ps_6_x"); - Diags.Clear(); - DiagConsumer->clear(); - - Args = TheDriver.ParseArgStrings({"-Tlib_6_1"}, false, ContainsError); - EXPECT_FALSE(ContainsError); - Triple = TC.ComputeEffectiveClangTriple(Args); - EXPECT_STREQ(Triple.c_str(), "unknown-unknown-shadermodel"); - EXPECT_EQ(Diags.getNumErrors(), 3u); - EXPECT_STREQ(DiagConsumer->Errors.back().c_str(), - "invalid profile : lib_6_1"); - Diags.Clear(); - DiagConsumer->clear(); - - Args = TheDriver.ParseArgStrings({"-Tfoo"}, false, ContainsError); - EXPECT_FALSE(ContainsError); - Triple = TC.ComputeEffectiveClangTriple(Args); - EXPECT_STREQ(Triple.c_str(), "unknown-unknown-shadermodel"); - EXPECT_EQ(Diags.getNumErrors(), 4u); - EXPECT_STREQ(DiagConsumer->Errors.back().c_str(), "invalid profile : foo"); - Diags.Clear(); - DiagConsumer->clear(); + validateTargetProfile("-Tpss_6_1", "invalid profile : pss_6_1", TheDriver, + Diags, DiagConsumer, 1); + + validateTargetProfile("-Tps_6_x", "invalid profile : ps_6_x", TheDriver, + Diags, DiagConsumer, 2); + validateTargetProfile("-Tlib_6_1", "invalid profile : lib_6_1", TheDriver, + Diags, DiagConsumer, 3); + validateTargetProfile("-Tfoo", "invalid profile : foo", TheDriver, Diags, + DiagConsumer, 4); + validateTargetProfile("", "target profile option (-T) is missing", TheDriver, + Diags, DiagConsumer, 5); } TEST(DxcModeTest, ValidatorVersionValidation) { @@ -520,8 +472,8 @@ TEST(DxcModeTest, ValidatorVersionValidation) { IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagConsumer); Driver TheDriver("/bin/clang", "", Diags, "", InMemoryFileSystem); - std::unique_ptr C( - TheDriver.BuildCompilation({"clang", "--driver-mode=dxc", "foo.hlsl"})); + std::unique_ptr C(TheDriver.BuildCompilation( + {"clang", "--driver-mode=dxc", "-Tlib_6_7", "foo.hlsl"})); EXPECT_TRUE(C); EXPECT_TRUE(!C->containsError()); @@ -610,4 +562,94 @@ TEST(DxcModeTest, ValidatorVersionValidation) { DiagConsumer->clear(); } +TEST(ToolChainTest, Toolsets) { + // Ignore this test on Windows hosts. + llvm::Triple Host(llvm::sys::getProcessTriple()); + if (Host.isOSWindows()) + GTEST_SKIP(); + + IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + + // Check (newer) GCC toolset installation. + { + IntrusiveRefCntPtr InMemoryFileSystem( + new llvm::vfs::InMemoryFileSystem); + + // These should be ignored. + InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-2", 0, + llvm::MemoryBuffer::getMemBuffer("\n")); + InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-", 0, + llvm::MemoryBuffer::getMemBuffer("\n")); + InMemoryFileSystem->addFile("/opt/rh/gcc-toolset--", 0, + llvm::MemoryBuffer::getMemBuffer("\n")); + InMemoryFileSystem->addFile("/opt/rh/gcc-toolset--1", 0, + llvm::MemoryBuffer::getMemBuffer("\n")); + + // File needed for GCC installation detection. + InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-12/root/usr/lib/gcc/" + "x86_64-redhat-linux/11/crtbegin.o", + 0, llvm::MemoryBuffer::getMemBuffer("\n")); + + DiagnosticsEngine Diags(DiagID, &*DiagOpts, new SimpleDiagnosticConsumer); + Driver TheDriver("/bin/clang", "x86_64-redhat-linux", Diags, + "clang LLVM compiler", InMemoryFileSystem); + std::unique_ptr C( + TheDriver.BuildCompilation({"clang", "--gcc-toolchain="})); + ASSERT_TRUE(C); + std::string S; + { + llvm::raw_string_ostream OS(S); + C->getDefaultToolChain().printVerboseInfo(OS); + } + EXPECT_EQ("Found candidate GCC installation: " + "/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" + "Selected GCC installation: " + "/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" + "Candidate multilib: .;@m64\n" + "Selected multilib: .;@m64\n", + S); + } + + // And older devtoolset. + { + IntrusiveRefCntPtr InMemoryFileSystem( + new llvm::vfs::InMemoryFileSystem); + + // These should be ignored. + InMemoryFileSystem->addFile("/opt/rh/devtoolset-2", 0, + llvm::MemoryBuffer::getMemBuffer("\n")); + InMemoryFileSystem->addFile("/opt/rh/devtoolset-", 0, + llvm::MemoryBuffer::getMemBuffer("\n")); + InMemoryFileSystem->addFile("/opt/rh/devtoolset--", 0, + llvm::MemoryBuffer::getMemBuffer("\n")); + InMemoryFileSystem->addFile("/opt/rh/devtoolset--1", 0, + llvm::MemoryBuffer::getMemBuffer("\n")); + + // File needed for GCC installation detection. + InMemoryFileSystem->addFile("/opt/rh/devtoolset-12/root/usr/lib/gcc/" + "x86_64-redhat-linux/11/crtbegin.o", + 0, llvm::MemoryBuffer::getMemBuffer("\n")); + + DiagnosticsEngine Diags(DiagID, &*DiagOpts, new SimpleDiagnosticConsumer); + Driver TheDriver("/bin/clang", "x86_64-redhat-linux", Diags, + "clang LLVM compiler", InMemoryFileSystem); + std::unique_ptr C( + TheDriver.BuildCompilation({"clang", "--gcc-toolchain="})); + ASSERT_TRUE(C); + std::string S; + { + llvm::raw_string_ostream OS(S); + C->getDefaultToolChain().printVerboseInfo(OS); + } + EXPECT_EQ("Found candidate GCC installation: " + "/opt/rh/devtoolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" + "Selected GCC installation: " + "/opt/rh/devtoolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" + "Candidate multilib: .;@m64\n" + "Selected multilib: .;@m64\n", + S); + } +} + } // end anonymous namespace. diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index c1257059c8649..972f3f195d856 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -23846,6 +23846,22 @@ TEST_F(FormatTest, LikelyUnlikely) { " return 29;\n", Style); + verifyFormat("while (limit > 0) [[unlikely]] {\n" + " --limit;\n" + "}", + Style); + verifyFormat("for (auto &limit : limits) [[likely]] {\n" + " --limit;\n" + "}", + Style); + + verifyFormat("for (auto &limit : limits) [[unlikely]]\n" + " --limit;", + Style); + verifyFormat("while (limit > 0) [[likely]]\n" + " --limit;", + Style); + Style.AttributeMacros.push_back("UNLIKELY"); Style.AttributeMacros.push_back("LIKELY"); verifyFormat("if (argc > 5) UNLIKELY\n" @@ -23874,6 +23890,22 @@ TEST_F(FormatTest, LikelyUnlikely) { " return 42;\n" "}\n", Style); + + verifyFormat("for (auto &limit : limits) UNLIKELY {\n" + " --limit;\n" + "}", + Style); + verifyFormat("while (limit > 0) LIKELY {\n" + " --limit;\n" + "}", + Style); + + verifyFormat("while (limit > 0) UNLIKELY\n" + " --limit;", + Style); + verifyFormat("for (auto &limit : limits) LIKELY\n" + " --limit;", + Style); } TEST_F(FormatTest, PenaltyIndentedWhitespace) { @@ -25100,12 +25132,12 @@ TEST_F(FormatTest, RemoveBraces) { FormatStyle Style = getLLVMStyle(); Style.RemoveBracesLLVM = true; - // The following eight test cases are fully-braced versions of the examples at + // The following test cases are fully-braced versions of the examples at // "llvm.org/docs/CodingStandards.html#don-t-use-braces-on-simple-single- // statement-bodies-of-if-else-loop-statements". - // 1. Omit the braces, since the body is simple and clearly associated with - // the if. + // Omit the braces since the body is simple and clearly associated with the + // `if`. verifyFormat("if (isa(D))\n" " handleFunctionDecl(D);\n" "else if (isa(D))\n" @@ -25117,7 +25149,7 @@ TEST_F(FormatTest, RemoveBraces) { "}", Style); - // 2. Here we document the condition itself and not the body. + // Here we document the condition itself and not the body. verifyFormat("if (isa(D)) {\n" " // It is necessary that we explain the situation with this\n" " // surprisingly long comment, so it would be unclear\n" @@ -25125,32 +25157,29 @@ TEST_F(FormatTest, RemoveBraces) { " // the scope of the `if`.\n" " // Because the condition is documented, we can't really\n" " // hoist this comment that applies to the body above the\n" - " // if.\n" + " // `if`.\n" " handleOtherDecl(D);\n" "}", Style); - // 3. Use braces on the outer `if` to avoid a potential dangling else + // Use braces on the outer `if` to avoid a potential dangling `else` // situation. verifyFormat("if (isa(D)) {\n" - " for (auto *A : D.attrs())\n" - " if (shouldProcessAttr(A))\n" - " handleAttr(A);\n" + " if (shouldProcessAttr(A))\n" + " handleAttr(A);\n" "}", "if (isa(D)) {\n" - " for (auto *A : D.attrs()) {\n" - " if (shouldProcessAttr(A)) {\n" - " handleAttr(A);\n" - " }\n" + " if (shouldProcessAttr(A)) {\n" + " handleAttr(A);\n" " }\n" "}", Style); - // 4. Use braces for the `if` block to keep it uniform with the else block. + // Use braces for the `if` block to keep it uniform with the `else` block. verifyFormat("if (isa(D)) {\n" " handleFunctionDecl(D);\n" "} else {\n" - " // In this else case, it is necessary that we explain the\n" + " // In this `else` case, it is necessary that we explain the\n" " // situation with this surprisingly long comment, so it\n" " // would be unclear without the braces whether the\n" " // following statement is in the scope of the `if`.\n" @@ -25158,9 +25187,9 @@ TEST_F(FormatTest, RemoveBraces) { "}", Style); - // 5. This should also omit braces. The `for` loop contains only a single + // This should also omit braces. The `for` loop contains only a single // statement, so it shouldn't have braces. The `if` also only contains a - // single simple statement (the for loop), so it also should omit braces. + // single simple statement (the `for` loop), so it also should omit braces. verifyFormat("if (isa(D))\n" " for (auto *A : D.attrs())\n" " handleAttr(A);", @@ -25171,18 +25200,26 @@ TEST_F(FormatTest, RemoveBraces) { "}", Style); - // 6. Use braces for the outer `if` since the nested `for` is braced. + // Use braces for a `do-while` loop and its enclosing statement. + verifyFormat("if (Tok->is(tok::l_brace)) {\n" + " do {\n" + " Tok = Tok->Next;\n" + " } while (Tok);\n" + "}", + Style); + + // Use braces for the outer `if` since the nested `for` is braced. verifyFormat("if (isa(D)) {\n" " for (auto *A : D.attrs()) {\n" - " // In this for loop body, it is necessary that we explain\n" - " // the situation with this surprisingly long comment,\n" - " // forcing braces on the `for` block.\n" + " // In this `for` loop body, it is necessary that we\n" + " // explain the situation with this surprisingly long\n" + " // comment, forcing braces on the `for` block.\n" " handleAttr(A);\n" " }\n" "}", Style); - // 7. Use braces on the outer block because there are more than two levels of + // Use braces on the outer block because there are more than two levels of // nesting. verifyFormat("if (isa(D)) {\n" " for (auto *A : D.attrs())\n" @@ -25198,7 +25235,7 @@ TEST_F(FormatTest, RemoveBraces) { "}", Style); - // 8. Use braces on the outer block because of a nested `if`, otherwise the + // Use braces on the outer block because of a nested `if`; otherwise the // compiler would warn: `add explicit braces to avoid dangling else` verifyFormat("if (auto *D = dyn_cast(D)) {\n" " if (shouldProcess(D))\n" @@ -25385,6 +25422,25 @@ TEST_F(FormatTest, RemoveBraces) { "}", Style); + verifyFormat("if (isa(D)) {\n" + " for (auto *A : D.attrs())\n" + " if (shouldProcessAttr(A))\n" + " handleAttr(A);\n" + "}", + "if (isa(D)) {\n" + " for (auto *A : D.attrs()) {\n" + " if (shouldProcessAttr(A)) {\n" + " handleAttr(A);\n" + " }\n" + " }\n" + "}", + Style); + + verifyFormat("do {\n" + " ++I;\n" + "} while (hasMore() && Filter(*I));", + "do { ++I; } while (hasMore() && Filter(*I));", Style); + verifyFormat("if (a)\n" " if (b)\n" " c;\n" @@ -25409,6 +25465,128 @@ TEST_F(FormatTest, RemoveBraces) { " h;", Style); + verifyFormat("if (a) {\n" + " b;\n" + "} else if (c) {\n" + " d;\n" + " e;\n" + "}", + "if (a) {\n" + " b;\n" + "} else {\n" + " if (c) {\n" + " d;\n" + " e;\n" + " }\n" + "}", + Style); + + verifyFormat("if (a) {\n" + " b;\n" + " c;\n" + "} else if (d) {\n" + " e;\n" + " f;\n" + "}", + "if (a) {\n" + " b;\n" + " c;\n" + "} else {\n" + " if (d) {\n" + " e;\n" + " f;\n" + " }\n" + "}", + Style); + + verifyFormat("if (a) {\n" + " b;\n" + "} else if (c) {\n" + " d;\n" + "} else {\n" + " e;\n" + " f;\n" + "}", + "if (a) {\n" + " b;\n" + "} else {\n" + " if (c) {\n" + " d;\n" + " } else {\n" + " e;\n" + " f;\n" + " }\n" + "}", + Style); + + verifyFormat("if (a) {\n" + " b;\n" + "} else if (c) {\n" + " d;\n" + "} else if (e) {\n" + " f;\n" + " g;\n" + "}", + "if (a) {\n" + " b;\n" + "} else {\n" + " if (c) {\n" + " d;\n" + " } else if (e) {\n" + " f;\n" + " g;\n" + " }\n" + "}", + Style); + + verifyFormat("if (a) {\n" + " if (b)\n" + " c;\n" + " else if (d) {\n" + " e;\n" + " f;\n" + " }\n" + "} else {\n" + " g;\n" + "}", + "if (a) {\n" + " if (b)\n" + " c;\n" + " else {\n" + " if (d) {\n" + " e;\n" + " f;\n" + " }\n" + " }\n" + "} else {\n" + " g;\n" + "}", + Style); + + verifyFormat("if (a)\n" + " if (b)\n" + " c;\n" + " else {\n" + " if (d) {\n" + " e;\n" + " f;\n" + " }\n" + " }\n" + "else\n" + " g;", + Style); + + verifyFormat("if (a) {\n" + " b;\n" + " c;\n" + "} else { // comment\n" + " if (d) {\n" + " e;\n" + " f;\n" + " }\n" + "}", + Style); + verifyFormat("if (a)\n" " b;\n" "else if (c)\n" @@ -25606,6 +25784,25 @@ TEST_F(FormatTest, RemoveBraces) { "}", Style); + verifyFormat("if (a)\n" + " b;\n" + "else if (c) {\n" + " d;\n" + " e;\n" + "} else\n" + " f = g(foo, bar,\n" + " baz);", + "if (a)\n" + " b;\n" + "else {\n" + " if (c) {\n" + " d;\n" + " e;\n" + " } else\n" + " f = g(foo, bar, baz);\n" + "}", + Style); + Style.ColumnLimit = 0; verifyFormat("if (a)\n" " b234567890223456789032345678904234567890 = " diff --git a/clang/unittests/Frontend/PCHPreambleTest.cpp b/clang/unittests/Frontend/PCHPreambleTest.cpp index d253d937ace97..2ce24c91ac0f1 100644 --- a/clang/unittests/Frontend/PCHPreambleTest.cpp +++ b/clang/unittests/Frontend/PCHPreambleTest.cpp @@ -24,6 +24,13 @@ using namespace clang; namespace { +std::string Canonicalize(const Twine &Path) { + SmallVector PathVec; + Path.toVector(PathVec); + llvm::sys::path::remove_dots(PathVec, true); + return std::string(PathVec.begin(), PathVec.end()); +} + class ReadCountingInMemoryFileSystem : public vfs::InMemoryFileSystem { std::map ReadCounts; @@ -31,16 +38,13 @@ class ReadCountingInMemoryFileSystem : public vfs::InMemoryFileSystem public: ErrorOr> openFileForRead(const Twine &Path) override { - SmallVector PathVec; - Path.toVector(PathVec); - llvm::sys::path::remove_dots(PathVec, true); - ++ReadCounts[std::string(PathVec.begin(), PathVec.end())]; + ++ReadCounts[Canonicalize(Path)]; return InMemoryFileSystem::openFileForRead(Path); } unsigned GetReadCount(const Twine &Path) const { - auto it = ReadCounts.find(Path.str()); + auto it = ReadCounts.find(Canonicalize(Path)); return it == ReadCounts.end() ? 0 : it->second; } }; diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp index 4eaa1636d230e..183b0d3aa2078 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp @@ -87,8 +87,8 @@ TEST(RecursiveASTVisitor, VisitsLambdaExprAndImplicitClass) { } TEST(RecursiveASTVisitor, VisitsAttributedLambdaExpr) { - if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).isPS4()) - GTEST_SKIP(); // PS4 does not support fastcall. + if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).isPS()) + GTEST_SKIP(); // PS4/PS5 do not support fastcall. LambdaExprVisitor Visitor; Visitor.ExpectMatch("", 1, 12); EXPECT_TRUE(Visitor.runOver( diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 2c0d46e6647a4..1a73b300cf9df 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -3331,24 +3331,24 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { OS << "const llvm::Triple &T = Target.getTriple();\n"; OS << "switch (Syntax) {\n"; - OS << "case AttrSyntax::GNU:\n"; + OS << "case AttributeCommonInfo::Syntax::AS_GNU:\n"; OS << " return llvm::StringSwitch(Name)\n"; GenerateHasAttrSpellingStringSwitch(GNU, OS, "GNU"); - OS << "case AttrSyntax::Declspec:\n"; + OS << "case AttributeCommonInfo::Syntax::AS_Declspec:\n"; OS << " return llvm::StringSwitch(Name)\n"; GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec"); - OS << "case AttrSyntax::Microsoft:\n"; + OS << "case AttributeCommonInfo::Syntax::AS_Microsoft:\n"; OS << " return llvm::StringSwitch(Name)\n"; GenerateHasAttrSpellingStringSwitch(Microsoft, OS, "Microsoft"); - OS << "case AttrSyntax::Pragma:\n"; + OS << "case AttributeCommonInfo::Syntax::AS_Pragma:\n"; OS << " return llvm::StringSwitch(Name)\n"; GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma"); - OS << "case AttrSyntax::HLSLSemantic:\n"; + OS << "case AttributeCommonInfo::Syntax::AS_HLSLSemantic:\n"; OS << " return llvm::StringSwitch(Name)\n"; GenerateHasAttrSpellingStringSwitch(HLSLSemantic, OS, "HLSLSemantic"); - auto fn = [&OS](const char *Spelling, const char *Variety, + auto fn = [&OS](const char *Spelling, const std::map> &List) { - OS << "case AttrSyntax::" << Variety << ": {\n"; + OS << "case AttributeCommonInfo::Syntax::AS_" << Spelling << ": {\n"; // C++11-style attributes are further split out based on the Scope. for (auto I = List.cbegin(), E = List.cend(); I != E; ++I) { if (I != List.cbegin()) @@ -3363,8 +3363,13 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { } OS << "\n} break;\n"; }; - fn("CXX11", "CXX", CXX); - fn("C2x", "C", C2x); + fn("CXX11", CXX); + fn("C2x", C2x); + OS << "case AttributeCommonInfo::Syntax::AS_Keyword:\n"; + OS << "case AttributeCommonInfo::Syntax::AS_ContextSensitiveKeyword:\n"; + OS << " llvm_unreachable(\"hasAttribute not supported for keyword\");\n"; + OS << " return 0;\n"; + OS << "}\n"; } @@ -3734,7 +3739,7 @@ static void GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) { if (!StmtSubjects.empty()) { OS << "bool diagAppertainsToDecl(Sema &S, const ParsedAttr &AL, "; OS << "const Decl *D) const override {\n"; - OS << " S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl)\n"; + OS << " S.Diag(AL.getLoc(), diag::err_attribute_invalid_on_decl)\n"; OS << " << AL << D->getLocation();\n"; OS << " return false;\n"; OS << "}\n\n"; diff --git a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp index f4bf4b19911a1..f8b14c5d33e23 100644 --- a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -1534,14 +1534,22 @@ static void emitDiagTable(std::map &DiagsInGroup, const bool hasSubGroups = !SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty()); if (hasSubGroups) { - OS << "/* DiagSubGroup" << I.second.IDNo << " */ " << SubGroupIndex; + OS << "/* DiagSubGroup" << I.second.IDNo << " */ " << SubGroupIndex + << ", "; if (IsPedantic) SubGroupIndex += GroupsInPedantic.size(); SubGroupIndex += SubGroups.size() + 1; } else { - OS << "0"; + OS << "0, "; } + std::string Documentation = I.second.Defs.back() + ->getValue("Documentation") + ->getValue() + ->getAsUnquotedString(); + + OS << "R\"(" << StringRef(Documentation).trim() << ")\""; + OS << ")\n"; } OS << "#endif // DIAG_ENTRY\n\n"; diff --git a/clang/utils/TableGen/RISCVVEmitter.cpp b/clang/utils/TableGen/RISCVVEmitter.cpp index dc6cbcbbf4ed5..8b008e0eec72b 100644 --- a/clang/utils/TableGen/RISCVVEmitter.cpp +++ b/clang/utils/TableGen/RISCVVEmitter.cpp @@ -155,10 +155,10 @@ void emitIntrinsicFuncDef(const RVVIntrinsic &RVVI, raw_ostream &OS) { OS << ");\n"; } -void emitMangledFuncDef(const RVVIntrinsic &RVVI, raw_ostream &OS) { +void emitOverloadedFuncDef(const RVVIntrinsic &RVVI, raw_ostream &OS) { OS << "__attribute__((__clang_builtin_alias__("; OS << "__builtin_rvv_" << RVVI.getBuiltinName() << ")))\n"; - OS << RVVI.getOutputType()->getTypeStr() << " " << RVVI.getMangledName() + OS << RVVI.getOutputType()->getTypeStr() << " " << RVVI.getOverloadedName() << "("; // Emit function arguments const RVVTypes &InputTypes = RVVI.getInputTypes(); @@ -289,7 +289,7 @@ void RVVEmitter::createHeader(raw_ostream &OS) { if (!Inst.isMasked() && !Inst.hasUnMaskedOverloaded()) return; OS << "__rvv_aio "; - emitMangledFuncDef(Inst, OS); + emitOverloadedFuncDef(Inst, OS); }); OS << "#undef __rvv_aio\n"; @@ -387,8 +387,8 @@ void RVVEmitter::createRVVIntrinsics( for (auto *R : RV) { StringRef Name = R->getValueAsString("Name"); StringRef SuffixProto = R->getValueAsString("Suffix"); - StringRef OverloadedName = R->getValueAsString("MangledName"); - StringRef OverloadedSuffixProto = R->getValueAsString("MangledSuffix"); + StringRef OverloadedName = R->getValueAsString("OverloadedName"); + StringRef OverloadedSuffixProto = R->getValueAsString("OverloadedSuffix"); StringRef Prototypes = R->getValueAsString("Prototype"); StringRef TypeRange = R->getValueAsString("TypeRange"); bool HasMasked = R->getValueAsBit("HasMasked"); diff --git a/clang/utils/hmaptool/CMakeLists.txt b/clang/utils/hmaptool/CMakeLists.txt index 01b6a920fb944..1b77727fa791b 100644 --- a/clang/utils/hmaptool/CMakeLists.txt +++ b/clang/utils/hmaptool/CMakeLists.txt @@ -1,9 +1,14 @@ -add_custom_command(OUTPUT "${LLVM_TOOLS_BINARY_DIR}/hmaptool" - COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/hmaptool" "${LLVM_TOOLS_BINARY_DIR}" +# FIXME: ideally we would just provide CURRENT_TOOLS_DIR globally instead of +# computing it just for function(configure_lit_site_cfg) +set_llvm_build_mode() +string(REPLACE "${CMAKE_CFG_INTDIR}" "${LLVM_BUILD_MODE}" CURRENT_TOOLS_DIR "${LLVM_RUNTIME_OUTPUT_INTDIR}") + +add_custom_command(OUTPUT "${CURRENT_TOOLS_DIR}/hmaptool" + COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/hmaptool" "${CURRENT_TOOLS_DIR}" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/hmaptool") install(PROGRAMS hmaptool DESTINATION "${LLVM_TOOLS_INSTALL_DIR}" COMPONENT hmaptool) -add_custom_target(hmaptool ALL DEPENDS "${LLVM_TOOLS_BINARY_DIR}/hmaptool") +add_custom_target(hmaptool ALL DEPENDS "${CURRENT_TOOLS_DIR}/hmaptool") set_target_properties(hmaptool PROPERTIES FOLDER "Utils") if(NOT LLVM_ENABLE_IDE) diff --git a/clang/www/c_dr_status.html b/clang/www/c_dr_status.html index d0ae947f4189f..75709d418a837 100644 --- a/clang/www/c_dr_status.html +++ b/clang/www/c_dr_status.html @@ -1,5 +1,5 @@ + "https://www.w3.org/TR/html4/strict.dtd"> @@ -49,211 +49,211 @@

C defect report implementation status

Available in Clang? -
1 + 1 C89 Do functions return values by copying? - Unknown + Yes - 2 + 2 NAD Subclause 6.8.3.2: Semantics of # Unknown - 3 + 3 NAD Subclause 6.1.8: Preprocessing numbers Unknown - 4 + 4 NAD Are multiple definitions of unused identifiers with external linkage permitted? Yes - 5 + 5 NAD May a conforming implementation define and recognize a pragma which would change the semantics of the language? Yes - 6 + 6 C89 It is unclear how the strtoul function behaves when presented with a subject sequence that begins with a minus sign N/A - 7 + 7 NAD Are declarations of the form struct-or-union identifier ; permitted after the identifier tag has already been declared? Yes - 8 + 8 NAD Can a conforming C compiler to perform dead-store elimination? Yes - 9 + 9 C89 Use of typedef names in parameter declarations No - 10 + 10 NAD Is a typedef to an incomplete type legal? Yes - 11 + 11 C89 Merging of declarations for linked identifier Yes - 12 + 12 NAD Is it valid to take the address of a dereferenced void pointer? Yes - 13 + 13 C89 Compatible and composite function types Yes - 14 + 14 C89 Issues with setjmp and fscanf descriptions N/A - 15 + 15 NAD What is the promoted type of a plain int bit-field? Yes - 16 + 16 C89 What does static storage duration do when zero for the type is not all zero bits? Unknown - 17 + 17 C89 39 unrelated questions about C89 Unknown - 18 + 18 NAD How does fscanf behave in the presence of multibyte characters? N/A - 19 + 19 NAD Definition of the term "printing character" and isgraph() N/A - 20 + 20 NAD Is a compiler which allows the Relaxed Ref/Def linkage model to be considered a conforming compiler? Yes - 21 + 21 C89 What is the result of: printf("%#.4o", 345);? N/A - 22 + 22 C89 What is the result of: strtod("100ergs", &ptr);? N/A - 23 + 23 NAD what is the result of strtod("0.0e99999", &ptr);? N/A - 24 + 24 NAD In subclause 7.10.1.4 The strtod function: What does '"C" locale' mean? N/A - 25 + 25 NAD What is meant by 'representable floating-point value?' Yes - 26 + 26 NAD Can a strictly conforming program contain a string literal with '$' or '@'? Yes - 27 + 27 C89 Can there be characters in the character set that are not in the required source character set? Yes - 28 + 28 NAD Do object access rules apply to dynamically allocated objects? Unknown - 29 + 29 NAD Do two types have to have the same tag to be compatible? No - 30 + 30 NAD Can 'sin(DBL_MAX)' result in 'errno' being set to 'EDOM'? N/A - 31 + 31 NAD Can constant expressions overflow? Yes - 32 + 32 NAD Must implementations diagnose extensions to the constant evaluation rules? No - 33 + 33 NAD Conformance questions around 'shall' violations outside of constraints sections Yes - 34 + 34 C89 External declarations in different scopes Yes - 35 + 35 NAD Questions about definition of functions without a prototype @@ -264,31 +264,31 @@

C defect report implementation status

- 36 + 36 NAD May floating-point constants be represented with more precision than implied by its type? Yes - 37 + 37 NAD Questions about multibyte characters and Unicode Yes - 38 + 38 NAD Questions about argument substitution during macro expansion Yes - 39 + 39 NAD Questions about the "C" locale Yes - 40 + 40 NAD 9 unrelated questions about C89 @@ -298,1699 +298,1699 @@

C defect report implementation status

- 41 + 41 NAD Do characters defined in 5.2.1 impact 7.3.1? N/A - 42 + 42 NAD On the behavior of library functions and overlapping objects N/A - 43 + 43 C89 On the definition of the NULL macro Yes - 44 + 44 NAD On the result of the offsetof macro Yes - 45 + 45 NAD Is the behavior of freopen defined when the file is invalid? N/A - 46 + 46 NAD Use of typedef names in parameter declarations Yes - 47 + 47 NAD Questions about declaration conformance Yes - 48 + 48 NAD Clarifications on the abort() function N/A - 49 + 49 C89 Can strxfrm() output more characters than were input? N/A - 50 + 50 NAD Do wide string literals implicitly include <stddef.h>? Yes - 51 + 51 NAD Question on pointer arithmetic Yes - 52 + 52 C89 Editorial corrections Yes - 53 + 53 C89 Accessing a pointer to a function with a prototype through a pointer to pointer to function without a prototype Yes - 54 + 54 C89 Can the string handling functions have a length of 0? N/A - 55 + 55 C89 Signal handler macros should have distinct values N/A - 56 + 56 NAD Floating-point representation precision requirements Yes - 57 + 57 NAD Is there an integral type for every pointer? Yes - 58 + 58 NAD Is there a limit on the number of digits processed by scanf and strtdo? N/A - 59 + 59 NAD Do types have to be completed? Yes - 60 + 60 C89 Array initialization from a string literal Yes - 61 + 61 NAD Whitespace in scanf format string N/A - 62 + 62 NAD Can the rename function be defined to fail? N/A - 63 + 63 Dup Floating-point representation precision requirements Duplicate of 56 - 64 + 64 NAD Null pointer constants Yes - 65 + 65 C89 Questions on locales N/A - 66 + 66 NAD Another question on locales N/A - 67 + 67 NAD Integer and integral type confusion Yes - 68 + 68 NAD 'char' and signed vs unsigned integer types Yes - 69 + 69 NAD Questions about the representation of integer types Yes - 70 + 70 NAD Interchangeability of function arguments Yes - 71 + 71 C89 Enumerated types Yes - 72 + 72 NAD Definition of object and pointer arithmetic Unknown - 73 + 73 NAD Definition of object and array access Unknown - 74 + 74 NAD Alignment and structure padding Unknown - 75 + 75 NAD Alignment of allocated memory N/A - 76 + 76 Open Pointers to the end of arrays Not resolved - 77 + 77 NAD Stability of addresses Yes - 78 + 78 NAD Uniqueness of addresses Unknown - 79 + 79 NAD Constancy of system library function addresses N/A - 80 + 80 C89 Merging of string constants Yes - 81 + 81 NAD Left shift operator Yes - 82 + 82 C89 Multiple varargs Unknown - 83 + 83 C89 Use of library functions N/A - 84 + 84 NAD Incomplete type in function declaration Yes - 85 + 85 C89 Returning from main Unknown - 86 + 86 NAD Object-like macros in system headers Yes - 87 + 87 NAD Order of evaluation Unknown - 88 + 88 NAD Compatibility of incomplete types Yes - 89 + 89 C89 Multiple definitions of macros Yes - 90 + 90 NAD Multibyte characters in formats N/A - 91 + 91 NAD Multibyte encodings Yes - 92 + 92 Dup Partial initialization of strings Duplicate of 60 - 93 + 93 C89 Reservation of identifiers Yes - 94 + 94 NAD Are constraints on function return the same as assignment? Yes - 95 + 95 NAD Is initialization as constrained as assignment? Yes - 96 + 96 NAD Arrays of incomplete types Yes - 97 + 97 Dup Use of offsetof with an incomplete type Duplicate of 40 - 98 + 98 NAD Pre/post increment/decrement of function or incomplete types Yes - 99 + 99 NAD ANSI/ISO C Defect report #rfg6 Unknown - 100 + 100 Dup - ANSI/ISO C Defect report #rfg7 - Duplicate of 1 + Defect with the return statement + Duplicate of 1 - 101 + 101 C89 - ANSI/ISO C Defect report #rfg8 - Unknown + Type qualifiers and "as if by assignment" + Yes - 102 + 102 NAD - ANSI/ISO C Defect report #rfg9 - Unknown + Tag redeclaration constraints + Yes - 103 + 103 NAD - ANSI/ISO C Defect report #rfg10 - Unknown + Formal parameters of incomplete type + Yes - 104 + 104 Dup - ANSI/ISO C Defect report #rfg11 - Duplicate of 84 + Incomplete tag types in a parameter list + Duplicate of 84 - 105 + 105 Dup - ANSI/ISO C Defect report #rfg12 - Duplicate of 17 + Precedence of requirements on compatible types + Duplicate of 17 - 106 + 106 NAD - ANSI/ISO C Defect report #rfg13 - Unknown + When can you dereference a void pointer? + Yes - 107 + 107 NAD - ANSI/ISO C Defect report #rfg14 + Type requirements of the assert macro parameter N/A - 108 + 108 NAD - ANSI/ISO C Defect report #rfg15 - Unknown + Can a macro identifier hide a keyword? + Yes - 109 + 109 NAD - ANSI/ISO C Defect report #rfg16 - Unknown + Are undefined values and undefined behavior the same? + Yes - 110 + 110 Dup Formal parameters having array-of-non-object types - Duplicate of 47 + Duplicate of 47 - 111 + 111 NAD Conversion of pointer-to-qualified type values to type (void*) values - Unknown + Yes - 112 + 112 NAD Null pointer constants and relational comparisons - Unknown + Yes - 113 + 113 NAD Return expressions in functions declared to return qualified void - Unknown + Yes - 114 + 114 NAD Initialization of multi-dimensional char array objects - Unknown + Yes - 115 + 115 NAD Member declarators as declarators - Unknown + Yes - 116 + 116 NAD Implicit unary & applied to register arrays - Unknown + Yes - 117 + 117 NAD Abstract semantics, sequence points, and expression evaluation - Unknown + Yes - 118 + 118 C89 Completion point for enumerated types - Unknown + Yes - 119 + 119 NAD Initialization of multi-dimensional array objects - Unknown + Yes - 120 + 120 NAD Semantics of assignment to (and initialization of) bit-fields - Unknown + Yes - 121 + 121 NAD Conversions of pointer values to integral types - Unknown + Yes - 122 + 122 Dup Conversion/widening of bit-fields - Duplicate of 15 + Duplicate of 15 - 123 + 123 NAD 'Type categories' and qualified types - Unknown + Yes - 124 + 124 C89 Casts to 'a void type' versus casts to 'the void type' - Unknown + Yes - 125 + 125 NAD Using things declared as 'extern (qualified) void' - Unknown + Yes - 126 + 126 NAD What does 'synonym' mean with respect to typedef names? Unknown - 127 + 127 Dup Composite type of an enumerated type and an integral type Duplicate of 13 - 128 + 128 NAD Editorial issue relating to tag declarations in type specifiers Unknown - 129 + 129 NAD Tags and name spaces Unknown - 130 + 130 NAD Guarantees when writing text to a stream N/A - 131 + 131 C89 const member qualification and assignment Unknown - 132 + 132 Dup Can undefined behavior occur at translation time, or only at run time? Duplicate of 109 - 133 + 133 NAD Undefined behavior not previously listed in subclause G2 Unknown - 134 + 134 NAD What is an 'error number' for strerror? N/A - 135 + 135 NAD Can the size argument to 'fwrite' be zero? N/A - 136 + 136 NAD 'mktime' and time gaps N/A - 137 + 137 NAD 'printf' and negative floating point values N/A - 138 + 138 C89 Is there an allocated storage duration? Unknown - 139 + 139 C89 Compatibility of complete and incomplete types Unknown - 140 + 140 NAD Behavior of 'setvbuf' N/A - 141 + 141 NAD What is the meaning of EOF? N/A - 142 + 142 C89 Reservation of macro names Unknown - 143 + 143 C89 'fopen' modes N/A - 144 + 144 C89 Preprocessing of preprocessing directives Unknown - 145 + 145 C89 Constant expressions Unknown - 146 + 146 C89 Nugatory constraint Unknown - 147 + 147 C89 Sequence points in library functions Unknown - 148 + 148 NAD Defining library functions Unknown - 149 + 149 C89 The term "variable" Unknown - 150 + 150 C89 Initialization of a char array from a string literal Unknown - 151 + 151 C89 Behavior of 'printf' and flags N/A - 152 + 152 NAD Can you 'longjmp' out of a signal handler? N/A - 153 + 153 Dup Can 'f()' be considered a call to a function-like macro with one empty argument? Duplicate of 3 - 154 + 154 NAD Consistency of implementation-defined values Unknown - 155 + 155 C89 Zero-sized allocations N/A - 156 + 156 C89 Closed streams N/A - 157 + 157 C89 Legitimacy of type synonyms Unknown - 158 + 158 C89 Null pointer conversions Unknown - 159 + 159 C89 Consistency of the C Standard Defects exist in the way the Standard refers to itself Unknown - 160 + 160 C89 Reservation of identifiers Unknown - 161 + 161 NAD Details of reserved symbols Unknown - 162 + 162 C89 'gmtime' and 'localtime' N/A - 163 + 163 C89 Undeclared identifiers Unknown - 164 + 164 NAD Bad declarations Unknown - 165 + 165 C89 Tags and incomplete types Unknown - 166 + 166 Open Meaning of lvalue Not resolved - 167 + 167 Open Consistency of the C Standard (Defect Report UK 015) Not resolved - 168 + 168 Open Consistency of the C Standard (Defect Report UK 016) Not resolved - 169 + 169 C89 Trigraphs Unknown - 170 + 170 C89 Operators and punctuators Unknown - 171 + 171 Open Ranges of integral types Not resolved - 172 + 172 Open Relational and equality operators Not resolved - 173 + 173 Open Line numbers Not resolved - 174 + 174 Open Implicit conversions Not resolved - 175 + 175 Open Correction to Technical Corrigendum 1 Not resolved - 176 + 176 Open Diagnostics for #error Not resolved - 177 + 177 Open Preprocessing directives Not resolved - 178 + 178 Open Conformance with array members and allocations Not resolved - 201 + 201 NAD Integer types longer than long Unknown - 202 + 202 C99 Change return type of certain <fenv.h> functions N/A - 203 + 203 C99 C locale conflict with ISO/IEC 9945-2 N/A - 204 + 204 C99 size_t and ptrdiff_t as a long long type Unknown - 205 + 205 NAD New keyword __at_least Yes - 206 + 206 NAD Default argument conversion of float _Complex Unknown - 207 + 207 C99 Handling of imaginary types Unknown - 208 + 208 C99 Ambiguity in initialization Unknown - 209 + 209 C99 Problem implementing INTN_C macros N/A - 210 + 210 C99 'fprintf' %a and %A conversions recommended practice N/A - 211 + 211 C99 Accuracy of decimal string to/from "binary" (non-decimal) floating-point conversions Unknown - 212 + 212 NAD Binding of multibyte conversion state objects N/A - 213 + 213 C99 Lacuna in 'mbrtowc' N/A - 214 + 214 NAD 'atexit' function registration N/A - 215 + 215 C99 Equality operators Unknown - 216 + 216 C99 Source character encodings Unknown - 217 + 217 NAD 'asctime' limits N/A - 218 + 218 C99 Signs of non-numeric floating point values Unknown - 219 + 219 NAD Effective types Unknown - 220 + 220 C99 Definition of "decimal integer" N/A - 221 + 221 NAD Lacuna in pointer arithmetic Unknown - 222 + 222 C99 Partially initialized structures Unknown - 223 + 223 C99 'FP_FAST_FMAF' and 'FP_FAST_FMAL' should be integer constant N/A - 224 + 224 C99 fpclassify return is not defined N/A - 225 + 225 C99 strtod, strtof and strtold expected form of the subject sequence N/A - 226 + 226 NAD strftime references Yes - 227 + 227 NAD strftime %U, %V, and %W conversion specifiers N/A - 228 + 228 C99 wmemcmp declaration in Annex B N/A - 229 + 229 C99 localeconv() *_sep_by_space table entries issues N/A - 230 + 230 C99 Enumerated type rank Unknown - 231 + 231 NAD Semantics of text-line and non-directive Unknown - 232 + 232 C99 Typo in Annex I Yes - 233 + 233 C99 %g, %G precision specification N/A - 234 + 234 C99 Miscellaneous Typos Yes - 235 + 235 C99 "C" locale collating behaviour not defined N/A - 236 + 236 NAD The interpretation of type based aliasing rule when applied to union objects or allocated objects Unknown - 237 + 237 NAD Declarations using [static] Unknown - 238 + 238 C99 Decriptions of fma() overflow and underflow errors are missing N/A - 239 + 239 C99 Annex F nexttoward description is inconsistent with 7.12.11.4 and F.9.8.3 N/A - 240 + 240 C99 lrint, llrint, lround, llround, and ilogb descriptions are not consistent for unrepresentable results N/A - 241 + 241 C99 Make the base standard and Annex F consistent for pow(0, <0) N/A - 242 + 242 C99 N/A - 243 + 243 C99 Make the base standard and Annex F consistent for fmod(), remainder(), and remquo() for a zero divisor N/A - 244 + 244 C99 tgamma(zero or negative integer) should be considered a pole error N/A - 245 + 245 C99 Missing paragraph numbers Yes - 246 + 246 NAD Completion of declarators Unknown - 247 + 247 C99 Are values a form of behaviour? Unknown - 248 + 248 C99 limits are required for optional types Unknown - 249 + 249 C99 Lacuna applying C89:TC1 to C99 Unknown - 250 + 250 C99 Non-directives within macro arguments Unknown - 251 + 251 C99 Are struct fred and union fred the same type? Unknown - 252 + 252 NAD Incomplete argument types when calling non-prototyped functions Unknown - 253 + 253 NAD "overriding" in designated initializers Unknown - 254 + 254 NAD mbtowc and partial characters N/A - 255 + 255 NAD Non-prototyped function calls and argument mismatches Unknown - 256 + 256 NAD Multiple inclusion of headers N/A - 257 + 257 NAD Common initial sequences and related issues with unions Unknown - 258 + 258 NAD Ordering of "defined" and macro replacement Unknown - 259 + 259 NAD Macro invocations with no arguments Unknown - 260 + 260 NAD Indeterminate values and identical representations Unknown - 261 + 261 NAD Constant expressions Unknown - 262 + 262 C99 Maximum size of bit fields Unknown - 263 + 263 C99 All-zero bits representations Unknown - 264 + 264 NAD Graphic characters N/A - 265 + 265 C99 Preprocessor arithmetic Unknown - 266 + 266 NAD Overflow of sizeof Unknown - 267 + 267 C99 Typos in 5.1.2.3, 7.24.4.4.5, 7.24.6.1, 7.24.6.1 N/A - 268 + 268 C99 Jumps into iteration statements Unknown - 269 + 269 C99 Lacunae in exact-width integer types N/A - 270 + 270 C99 wint_t is not the promoted version of wchar_t N/A - 271 + 271 NAD Lacuna in iswctype and towctrans N/A - 272 + 272 C99 Type category Unknown - 273 + 273 C99 Meaning of __STDC_ISO_10646__ Unknown - 274 + 274 C99 Meaning of "character" in <string.h> functions N/A - 275 + 275 C99 Bitwise-OR of nothing N/A - 276 + 276 C99 Orientation of perror N/A - 277 + 277 NAD Declarations within iteration statements Unknown - 278 + 278 C99 Lacuna in character encodings Unknown - 279 + 279 C99 Wide character code values for members of the basic character set Unknown - 280 + 280 NAD struct tm, member tm_isdst, and mktime() in <time.h> N/A - 281 + 281 C99 CLOCKS_PER_SEC should not be a constant expression N/A - 282 + 282 C99 Flexible array members & struct padding Unknown - 283 + 283 C99 Accessing a non-current union member ("type punning") Unknown - 284 + 284 NAD Does <math.h> define INT_MIN and INT_MAX? N/A - 285 + 285 C99 Conversion of an imaginary type to _Bool Unknown - 286 + 286 C99 Correctly rounded and rounding direction/mode N/A - 287 + 287 Dup Floating-point status flags and sequence points Duplicate of 87 - 288 + 288 NAD Deficiency on multibyte conversions N/A - 289 + 289 C99 Function prototype with [restrict] Unknown - 290 + 290 C99 FLT_EVAL_METHOD and extra precision and/or range Unknown - 291 + 291 C99 Corrections to requirements on inexact floating-point exceptions Unknown - 292 + 292 C99 Use of the word variable Unknown - 293 + 293 C99 Typo in Standard - double complex instead of complex in an example Yes - 294 + 294 NAD Technical question on C99 restrict keyword Unknown - 295 + 295 C99 Incomplete types for function parameters Unknown - 296 + 296 C99 Is exp(INFINITY) overflow? A range error? A divide-by-zero exception? INFINITY without any errors? N/A - 297 + 297 C99 May FE_* floating-point exception flags have bits in common? N/A - 298 + 298 C99 Validity of constant in unsigned long long range Unknown - 299 + 299 C99 Is cabs() a type-generic macro? N/A - 300 + 300 NAD Translation-time expresssion evaluation Unknown - 301 + 301 NAD Meaning of FE_* macros in <fenv.h> Unknown - 302 + 302 C99 6.10.2p5: Adding underscore to portable include file name character set Unknown - 303 + 303 C99 6.10p2: Breaking up the very long sentence describing preprocessing directive Unknown - 304 + 304 C99 Clarifying illegal tokens in #if directives Unknown - 305 + 305 C99 6.10.1p3: Clarifying handling of keywords in #if directives Unknown - 306 + 306 C99 6.10.3p9: Clarifying that rescanning applies to object-like macros Unknown - 307 + 307 C99 6.10.3p10: Clarifiying arguments vs. parameters Unknown - 308 + 308 C99 Clarify that source files et al. need not be "files" Yes - 309 + 309 C99 Clarifying trigraph substitution Unknown - 310 + 310 C99 Add non-corner case example of trigraphs Yes - 311 + 311 C99 Definition of variably modified types Unknown - 312 + 312 C99 Meaning of "known constant size" Yes - 313 + 313 NAD Incomplete arrays of VLAs Unknown - 314 + 314 NAD Cross-translation-unit tagged type compatibility Unknown - 315 + 315 C99 Implementation-defined bit-field types Unknown - 316 + 316 NAD Unprototyped function types Unknown - 317 + 317 NAD Function definitions with empty parentheses Unknown - 318 + 318 C99 (double)0.1f with FLT_EVAL_METHOD being 2 Unknown - 319 + 319 NAD printf("%a", 1.0) and trailing zeros N/A - 320 + 320 C99 Scope of variably modified type Unknown - 321 + 321 C99 Wide character code values for members of the basic character set Unknown - 322 + 322 C99 Problem with TC2 Change #67 (Add perror to the list defining byte input/output functions) N/A - 323 + 323 C99 Potential problems with TC2 #34, #35, and #36 N/A - 324 + 324 C99 Tokenization obscurities Unknown - 325 + 325 NAD strerror() N/A - 326 + 326 C99 asctime() N/A - 327 + 327 C99 Italicize definition of variable length array type, add forward references Yes - 328 + 328 C99 String literals in compound literal initialization Unknown - 329 + 329 C99 Math functions and directed rounding N/A - 330 + 330 C99 Externally visible exceptional conditions N/A - 331 + 331 NAD permit FE_DIVBYZERO when errno says EDOM N/A - 332 + 332 C99 gets is generally unsafe N/A - 333 + 333 C99 Missing Predefined Macro Name Unknown - 334 + 334 Open Missing semantics of comparison macros Not resolved - 335 + 335 NAD _Bool bit-fields Unknown - 336 + 336 C99 What does TMP_MAX actually indicate? N/A - 337 + 337 C99 stdio.h macro definition problems N/A - 338 + 338 C11 C99 seems to exclude indeterminate value from being an uninitialized register Unknown - 339 + 339 Dup Variably modified compound literal Duplicate of 328 - 340 + 340 C99 Composite types for variable-length arrays Unknown - 341 + 341 C99 [*] in abstract declarators Unknown - 342 + 342 Dup VLAs and conditional expressions Duplicate of 340 - 343 + 343 C99 Initializing qualified wchar_t arrays Unknown - 344 + 344 C99 Casts in preprocessor conditional expressions Unknown - 345 + 345 C11 Where does parameter scope start? Unknown @@ -2137,7 +2137,12 @@

C defect report implementation status

423 C11 Defect Report relative to n1570: underspecification for qualified rvalues - Clang 15 + +
Partial + Clang properly handles dropping qualifiers from cast operations, but + does not yet handle dropping qualifiers from the function return type. +
+ 424 diff --git a/clang/www/c_status.html b/clang/www/c_status.html index 1d23ce7a97b9d..17d18d8724f8d 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -85,7 +85,7 @@

C99 implementation status

Clang implements a significant portion of the ISO 9899:1999 (C99) standard, but the status of individual proposals is still under investigation.

Note, the list of C99 features comes from the C99 committee draft. Not all C99 documents are publicly available, so the documents referenced in this section may be inaccurate, unknown, or not linked.

- Yes remove implicit function declaration - N636 + N636 Unknown preprocessor arithmetic done in intmax_t/uintmax_t - N736 + N736 Unknown mixed declarations and code - N740 + N740 Yes @@ -264,17 +264,17 @@

C99 implementation status

integer constant type rules - N629 + N629 Unknown integer promotion rules - N725 + N725 Unknown macros with a variable number of arguments - N707 + N707 Yes @@ -289,12 +289,12 @@

C99 implementation status

inline functions - N741 + N741 Yes boolean type in <stdbool.h> - N815 + N815 Yes @@ -319,7 +319,7 @@

C99 implementation status

_Pragma preprocessing operator - N634 + N634 @@ -329,26 +329,26 @@

C99 implementation status

standard pragmas - N631 + N631 Unknown - N696 + N696 Unknown __func__ predefined identifier - N611 + N611 Yes va_copy macro - N671 + N671 Yes LIA compatibility annex - N792 + N792 No @@ -368,7 +368,7 @@

C99 implementation status

relaxed restrictions on portable header names - N772 + N772 Unknown @@ -395,218 +395,218 @@

C11 implementation status

A finer-grained specification for sequencing - N1252 + N1252 Unknown Clarification of expressions - N1282 + N1282 Unknown Extending the lifetime of temporary objects (factored approach) - N1285 + N1285 Unknown Requiring signed char to have no padding bits - N1310 + N1310 Unknown Initializing static or external variables - N1311 + N1311 Unknown Conversion between pointers and floating types - N1316 + N1316 Yes Adding TR 19769 to the C Standard Library - N1326 + N1326 Clang 3.3 Static assertions - N1330 + N1330 Yes Parallel memory sequencing model proposal - N1349 + N1349 Unknown Analyzability (#1, #4 - conditionally normative) - N1350 + N1350 Unknown FLT_EVAL_METHOD issues (first change only) - N1353 + N1353 Unknown _Bool bit-fields - N1356 + N1356 Unknown Technical corrigendum for C1X - N1359 + N1359 Unknown Benign typedef redefinition - N1360 + N1360 Clang 3.1 Thread-local storage - N1364 + N1364 Clang 3.3 Constant expressions - N1365 + N1365 Unknown Contractions and expression evaluation methods - N1367 + N1367 Unknown FLT_EVAL_METHOD and return - N1382 + N1382 Unknown Floating-point to int/_Bool conversions - N1391 + N1391 Unknown Analyzability (along the lines) - N1394 + N1394 Unknown Wide function returns (alternate proposal) - N1396 + N1396 Unknown Alignment - N1397 + N1397 Clang 3.2 - N1447 + N1447 Clang 3.2 Anonymous member-structures and unions (modulo "name lookup") - N1406 + N1406 Yes Completeness of types - N1439 + N1439 Unknown Generic macro facility - N1441 + N1441 Yes Dependency ordering for C memory model - N1444 + N1444 Unknown Subsetting the standard - N1460 + N1460 Unknown Assumed types in F.9.2 - N1468 + N1468 Unknown Supporting the 'noreturn' property in C1x - N1478 + N1478 Clang 3.3 Updates to C++ memory model based on formalization - N1480 + N1480 Unknown Explicit initializers for atomics - N1482 + N1482 Unknown Atomics proposal (minus ternary op) - N1485 + N1485 Yes UTF-8 string literals - N1488 + N1488 Clang 3.3 Optimizing away infinite loops - N1509 + N1509 Yes Conditional normative status for Annex G - N1514 + N1514 Unknown Creation of complex value - N1464 + N1464 Unknown Recommendations for extended identifier characters for C and C++ - N1518 + N1518 Unknown Atomic C1x/C++0x compatibility refinements (1st part only) - N1526 + N1526 Yes Atomic bitfields implementation defined - N1530 + N1530 Yes Small fix for the effect of alignment on struct/union type compatibility - N1532 + N1532 Yes Synthesis re _Atomic - N1537 + N1537 Unknown Clarification for wide evaluation - N1531 + N1531 Unknown @@ -635,217 +635,487 @@

C2x implementation status

Evaluation formats - N2186 + N2186 Unknown Clarifying the restrict Keyword v2 - N2660 + N2660 Unknown Harmonizing static_assert with C++ - N2665 + N2665 Clang 9 nodiscard attribute - N2667 + N2267 Clang 9 maybe_unused attribute - N2670 + N2270 Clang 9 TS 18661 Integration - N2314 + N2314 Unknown - N2341 + N2341 Unknown - N2401 + N2401 Unknown - N2359 + N2359 Unknown - N2546 + N2546 Unknown Preprocessor line numbers unspecified - N2322 + N2322 Yes deprecated attribute - N2334 + N2334 Clang 9 Attributes - N2335 + N2335 Clang 9 - N2554 + N2554 Clang 9 Defining new types in offsetof - N2350 + N2350 Yes fallthrough attribute - N2408 + N2408 Clang 9 Two's complement sign representation - N2412 + N2412 Clang 14 Adding the u8 character prefix - N2418 + N2418 Clang 15 Remove support for function definitions with identifier lists - N2432 + N2432 Clang 15 *_IS_IEC_60559 feature test macros - N2379 + N2379 Unknown Floating-point negation and conversion - N2416 + N2416 Unknown Annex F.8 update for implementation extensions and rounding - N2384 + N2384 Unknown _Bool definitions for true and false - N2393 + N2393 No [[nodiscard("should have a reason")]] - N2448 + N2448 Clang 10 Allowing unnamed parameters in function definitions - N2480 + N2480 Clang 11 Free positioning of labels inside compound statements - N2508 + N2508 No Clarification request for C17 example of undefined behavior - N2517 + N2517 No Querying attribute support - N2553 + N2553 Clang 9 Binary literals - N2549 + N2549 Clang 9 Allow duplicate attributes - N2557 + N2557 Clang 13 Character encoding of diagnostic text - N2563 + N2563 Yes What we think we reserve - N2572 + N2572 Partial Decimal floating-point triples - N2580 + N2580 Unknown Remove mixed wide string literal concatenation - N2594 + N2594 Clang 9 Update to IEC 60559:2020 - N2600 + N2600 Unknown Compatibility of Pointers to Arrays with Qualifiers - N2607 + N2607 Partial String functions for freestanding implementations - N2524 + N2524 No Digit separators - N2626 + N2626 Clang 13 Missing DEC_EVAL_METHOD - N2640 + N2640 Unknown Missing +(x) in table - N2641 + N2641 Unknown Add support for preprocessing directives elifdef and elifndef - N2645 + N2645 Clang 13 + + + [[maybe_unused]] for labels + N2662 + No + + + Zeros compare equal + N2670 + Unknown + + + Negative values + N2671 + Yes + + + 5.2.4.2.2 cleanup + N2672 + Yes + + + Adding a Fundamental Type for N-bit integers + N2763 + Clang 15 + + + + #warning directive + N2686 + Yes + + + Sterile characters + N2686 + Yes + + + Integer constant expressions + N2713 + No + + + Numerically equal + N2716 + Unknown + + + char16_t & char32_t string literals shall be UTF-16 & UTF-32 + N2728 + Unknown + + + IEC 60559 binding + N2749 + Unknown + + + Static initialization of DFP zeros + N2755 + Unknown + + + __has_include for C + N2799 + Yes + + + + Annex F overflow and underflow + N2747 + Yes + + + Remove UB from Incomplete Types in Function Parameters + N2770 + Yes + + + Variably-modified types + N2778 + Yes + + + Types do not have types + N2781 + Yes + + + 5.2.4.2.2 cleanup (N2672 update) + N2806 + Yes + + + Allow 16-bit ptrdiff_t + N2808 + Yes + + + Proposal to update CFP freestanding requirements + N2823 + Unknown + + + Types and sizes + N2838 + Unknown + + + Clarifying integer terms + N2837 + Yes + + + Clarification for max exponent macros + N2843 + Unknown + + + Clarification about expression transformations + N2846 + Unknown + + + Contradiction about INFINITY macro + N2848 + Unknown + + + Require exact-width integer type interfaces + N2872 + Yes + + + + @, $, and ‘ in the source/execution character set + N2701 + Yes + + + Quantum exponent of NaN (version 2) + N2754 + Unknown + + + The noreturn attribute + N2764 + Clang 15 + + + Literal suffixes for bit-precise integers + N2775 + Clang 15 + + + *_HAS_SUBNORM==0 implies what? + N2797 + Yes + + + Disambiguate the storage class of some compound literals + N2819 + Unknown + + + Add annotations for unreachable control flow v2 + N2826 + No + + + Unicode Sequences More Than 21 Bits are a Constraint Violation r0 + N2828 + Clang 3.6 + + + Make assert() macro user friendly for C and C++ v2 + N2829 + No + + + Identifier Syntax using Unicode Standard Annex 31 + N2836 + No + + + No function declarators without prototypes + N2841 + Clang 15 + + + Remove default argument promotions for _FloatN types + N2844 + Unknown + + + Revised Suggestions of Change for Numerically Equal/Equivalent + N2847 + Unknown + + + 5.2.4.2.2 Cleanup, Again Again (N2806 update) + N2879 + Yes + + + Clarification for max exponent macros-update + N2882 + Unknown + + + Consistent, Warningless, and Intuitive Initialization with {}, revision 2 + N2900 + Unknown + + + Not-so-magic: typeof, r5 + N2927 + +
Partial + Clang supports typeof in GNU standards mode, but its + compatibility with this proposal is unknown. Also, Clang does not yet + support remove_quals. +
+ + + + Type annex tgmath narrowing macros with integer args v2 + N2931 + Unknown + + + Revise spelling of keywords v7 + N2934 + No + + + Make false and true first-class language features v8 + N2935 + Clang 15 + + + Properly define blocks as part of the grammar v3 + N2937 + Yes + + + + Annex X (replacing Annex H) for IEC 60559 interchange + N2601 + No + + + Indeterminate Values and Trap Representations + N2861 + Yes + + + Remove ATOMIC_VAR_INIT v2 + N2886 + No + + + Require exact-width integer type interfaces v2 + N2888 + Yes + + + Wording Change for Variably-Modified Types + N2992 + Yes + - diff --git a/clang/www/get_started.html b/clang/www/get_started.html index ab5f7fac6a6c9..48ce7f8edbbcf 100755 --- a/clang/www/get_started.html +++ b/clang/www/get_started.html @@ -69,9 +69,13 @@

On Unix-like Systems

  • cd llvm-project
  • mkdir build (in-tree build is not supported)
  • cd build
  • -
  • cmake -DLLVM_ENABLE_PROJECTS=clang -G "Unix Makefiles" ../llvm
  • +
  • This builds both LLVM and Clang in release mode. Alternatively, if + you need a debug build, switch Release to Debug. See + frequently used cmake variables + for more options. +
  • +
  • cmake -DLLVM_ENABLE_PROJECTS=clang -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" ../llvm
  • make
  • -
  • This builds both LLVM and Clang for debug mode.
  • Note: For subsequent Clang development, you can just run make clang.
  • CMake allows you to generate project files for several IDEs: Xcode, diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index 84575b49079c1..cdafdfc7ecc3b 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -31,6 +31,7 @@ endif() include(SetPlatformToolchainTools) include(base-config-ix) include(CompilerRTUtils) +include(CMakeDependentOption) option(COMPILER_RT_BUILD_BUILTINS "Build builtins" ON) mark_as_advanced(COMPILER_RT_BUILD_BUILTINS) @@ -211,6 +212,11 @@ set(CXXLIBS none default libstdc++ libc++) set_property(CACHE SANITIZER_TEST_CXX PROPERTY STRINGS ;${CXXLIBS}) handle_default_cxx_lib(SANITIZER_TEST_CXX) +option(COMPILER_RT_USE_LLVM_UNWINDER "Use the LLVM unwinder." OFF) +cmake_dependent_option(COMPILER_RT_ENABLE_STATIC_UNWINDER + "Statically link the LLVM unwinder." OFF + "COMPILER_RT_USE_LLVM_UNWINDER" OFF) + set(DEFAULT_SANITIZER_USE_STATIC_LLVM_UNWINDER OFF) if (FUCHSIA) set(DEFAULT_SANITIZER_USE_STATIC_LLVM_UNWINDER ON) @@ -504,6 +510,15 @@ string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} list(APPEND COMPILER_RT_COMMON_CFLAGS ${stdlib_flag}) list(APPEND COMPILER_RT_COMMON_LINK_FLAGS ${stdlib_flag}) +if(COMPILER_RT_USE_LLVM_UNWINDER) + if (COMPILER_RT_ENABLE_STATIC_UNWINDER) + set(unwinder_target unwind_static) + else() + set(unwinder_target unwind_shared) + endif() + list(APPEND SANITIZER_CXX_ABI_LIBRARIES "$<$:$>") +endif() + macro(append_libcxx_libs var) if (${var}_INTREE) if (SANITIZER_USE_STATIC_LLVM_UNWINDER AND (TARGET unwind_static OR HAVE_LIBUNWIND)) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index 8cd80590258a5..cd45176cf2ba7 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -4,9 +4,19 @@ include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) include(CheckIncludeFiles) include(CheckLibraryExists) +include(LLVMCheckCompilerLinkerFlag) include(CheckSymbolExists) include(TestBigEndian) +# The compiler driver may be implicitly trying to link against libunwind. +# This is normally ok (libcxx relies on an unwinder), but if libunwind is +# built in the same cmake invocation as compiler-rt and we're using the +# in tree version of runtimes, we'd be linking against the just-built +# libunwind (and the compiler implicit -lunwind wouldn't succeed as the newly +# built libunwind isn't installed yet). For those cases, it'd be good to +# link with --uwnindlib=none. Check if that option works. +llvm_check_compiler_linker_flag(C "--unwindlib=none" CXX_SUPPORTS_UNWINDLIB_NONE_FLAG) + check_library_exists(c fopen "" COMPILER_RT_HAS_LIBC) if (COMPILER_RT_USE_BUILTINS_LIBRARY) include(HandleCompilerRT) diff --git a/compiler-rt/lib/asan/asan_errors.cpp b/compiler-rt/lib/asan/asan_errors.cpp index a22bf130d8233..10f7c17991d72 100644 --- a/compiler-rt/lib/asan/asan_errors.cpp +++ b/compiler-rt/lib/asan/asan_errors.cpp @@ -279,9 +279,7 @@ void ErrorRssLimitExceeded::Print() { void ErrorOutOfMemory::Print() { Decorator d; Printf("%s", d.Error()); - Report( - "ERROR: AddressSanitizer: allocator is out of memory trying to allocate " - "0x%zx bytes\n", requested_size); + ERROR_OOM("allocator is trying to allocate 0x%zx bytes\n", requested_size); Printf("%s", d.Default()); stack->Print(); PrintHintAllocatorCannotReturnNull(); diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h index e448d9798a1fc..cc5f5836e7423 100644 --- a/compiler-rt/lib/asan/asan_mapping.h +++ b/compiler-rt/lib/asan/asan_mapping.h @@ -176,6 +176,8 @@ # define ASAN_SHADOW_OFFSET_DYNAMIC # elif SANITIZER_APPLE && defined(__aarch64__) # define ASAN_SHADOW_OFFSET_DYNAMIC +# elif SANITIZER_FREEBSD && defined(__aarch64__) +# define ASAN_SHADOW_OFFSET_CONST 0x0000800000000000 # elif SANITIZER_RISCV64 # define ASAN_SHADOW_OFFSET_CONST 0x0000000d55550000 # elif defined(__aarch64__) diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index 1b2c7b201c229..795fe2ab316d8 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -165,8 +165,10 @@ set(GENERIC_SOURCES subvsi3.c subvti3.c trampoline_setup.c + truncdfbf2.c truncdfhf2.c truncdfsf2.c + truncsfbf2.c truncsfhf2.c ucmpdi2.c ucmpti2.c diff --git a/compiler-rt/lib/builtins/atomic.c b/compiler-rt/lib/builtins/atomic.c index 6d54b61f6410f..852bb20f08672 100644 --- a/compiler-rt/lib/builtins/atomic.c +++ b/compiler-rt/lib/builtins/atomic.c @@ -365,6 +365,9 @@ OPTIMISED_CASES #define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW(n, lockfree, type, xor, ^) OPTIMISED_CASES #undef OPTIMISED_CASE +// Allow build with clang without __c11_atomic_fetch_nand builtin (pre-14) +#if __has_builtin(__c11_atomic_fetch_nand) #define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW_NAND(n, lockfree, type) OPTIMISED_CASES #undef OPTIMISED_CASE +#endif diff --git a/compiler-rt/lib/builtins/fp_trunc.h b/compiler-rt/lib/builtins/fp_trunc.h index 00595edd5e018..7a54564a3520a 100644 --- a/compiler-rt/lib/builtins/fp_trunc.h +++ b/compiler-rt/lib/builtins/fp_trunc.h @@ -59,6 +59,12 @@ typedef uint16_t dst_rep_t; #define DST_REP_C UINT16_C static const int dstSigBits = 10; +#elif defined DST_BFLOAT +typedef uint16_t dst_t; +typedef uint16_t dst_rep_t; +#define DST_REP_C UINT16_C +static const int dstSigBits = 7; + #else #error Destination should be single precision or double precision! #endif // end destination precision diff --git a/compiler-rt/lib/builtins/gcc_personality_v0.c b/compiler-rt/lib/builtins/gcc_personality_v0.c index afb9e2e113def..58fd7ceb58c35 100644 --- a/compiler-rt/lib/builtins/gcc_personality_v0.c +++ b/compiler-rt/lib/builtins/gcc_personality_v0.c @@ -143,7 +143,7 @@ static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) { } #if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ - !defined(__ARM_DWARF_EH__) + !defined(__ARM_DWARF_EH__) && !defined(__SEH__) #define USING_ARM_EHABI 1 _Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception *, struct _Unwind_Context *); diff --git a/compiler-rt/lib/builtins/os_version_check.c b/compiler-rt/lib/builtins/os_version_check.c index d7194b99ae54c..ebfb2dfc72ddd 100644 --- a/compiler-rt/lib/builtins/os_version_check.c +++ b/compiler-rt/lib/builtins/os_version_check.c @@ -307,8 +307,8 @@ static void readSystemProperties(void) { } int32_t __isOSVersionAtLeast(int32_t Major, int32_t Minor, int32_t Subminor) { - (int32_t) Minor; - (int32_t) Subminor; + (void) Minor; + (void) Subminor; static pthread_once_t once = PTHREAD_ONCE_INIT; pthread_once(&once, readSystemProperties); diff --git a/compiler-rt/lib/builtins/truncdfbf2.c b/compiler-rt/lib/builtins/truncdfbf2.c new file mode 100644 index 0000000000000..dbd54dcd50caf --- /dev/null +++ b/compiler-rt/lib/builtins/truncdfbf2.c @@ -0,0 +1,13 @@ +//===-- lib/truncdfbf2.c - double -> bfloat conversion ------------*- 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 +// +//===----------------------------------------------------------------------===// + +#define SRC_DOUBLE +#define DST_BFLOAT +#include "fp_trunc_impl.inc" + +COMPILER_RT_ABI dst_t __truncdfbf2(double a) { return __truncXfYf2__(a); } diff --git a/compiler-rt/lib/builtins/truncsfbf2.c b/compiler-rt/lib/builtins/truncsfbf2.c new file mode 100644 index 0000000000000..6bed116af9868 --- /dev/null +++ b/compiler-rt/lib/builtins/truncsfbf2.c @@ -0,0 +1,13 @@ +//===-- lib/truncsfbf2.c - single -> bfloat conversion ------------*- 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 +// +//===----------------------------------------------------------------------===// + +#define SRC_SINGLE +#define DST_BFLOAT +#include "fp_trunc_impl.inc" + +COMPILER_RT_ABI dst_t __truncsfbf2(float a) { return __truncXfYf2__(a); } diff --git a/compiler-rt/lib/dfsan/scripts/build-libc-list.py b/compiler-rt/lib/dfsan/scripts/build-libc-list.py index daa6248b82a95..524749640e4e2 100755 --- a/compiler-rt/lib/dfsan/scripts/build-libc-list.py +++ b/compiler-rt/lib/dfsan/scripts/build-libc-list.py @@ -11,6 +11,30 @@ # uninstrumented, thus allowing the instrumentation pass to treat calls to those # functions correctly. +# Typical usage will list runtime libraries which are not instrumented by dfsan. +# This would include libc, and compiler builtins. +# +# ./build-libc-list.py \ +# --lib-file=/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 \ +# --lib-file=/lib/x86_64-linux-gnu/libanl.so.1 \ +# --lib-file=/lib/x86_64-linux-gnu/libBrokenLocale.so.1 \ +# --lib-file=/lib/x86_64-linux-gnu/libcidn.so.1 \ +# --lib-file=/lib/x86_64-linux-gnu/libcrypt.so.1 \ +# --lib-file=/lib/x86_64-linux-gnu/libc.so.6 \ +# --lib-file=/lib/x86_64-linux-gnu/libdl.so.2 \ +# --lib-file=/lib/x86_64-linux-gnu/libm.so.6 \ +# --lib-file=/lib/x86_64-linux-gnu/libnsl.so.1 \ +# --lib-file=/lib/x86_64-linux-gnu/libpthread.so.0 \ +# --lib-file=/lib/x86_64-linux-gnu/libresolv.so.2 \ +# --lib-file=/lib/x86_64-linux-gnu/librt.so.1 \ +# --lib-file=/lib/x86_64-linux-gnu/libthread_db.so.1 \ +# --lib-file=/lib/x86_64-linux-gnu/libutil.so.1 \ +# --lib-file=/usr/lib/x86_64-linux-gnu/libc_nonshared.a \ +# --lib-file=/usr/lib/x86_64-linux-gnu/libpthread_nonshared.a \ +# --lib-file=/lib/x86_64-linux-gnu/libgcc_s.so.1 \ +# --lib-file=/usr/lib/gcc/x86_64-linux-gnu/4.6/libgcc.a \ +# --error-missing-lib + import os import subprocess import sys @@ -33,30 +57,6 @@ def defined_function_list(object): p = OptionParser() -p.add_option('--libc-dso-path', metavar='PATH', - help='path to libc DSO directory', - default='/lib/x86_64-linux-gnu') -p.add_option('--libc-archive-path', metavar='PATH', - help='path to libc archive directory', - default='/usr/lib/x86_64-linux-gnu') - -p.add_option('--libgcc-dso-path', metavar='PATH', - help='path to libgcc DSO directory', - default='/lib/x86_64-linux-gnu') -p.add_option('--libgcc-archive-path', metavar='PATH', - help='path to libgcc archive directory', - default='/usr/lib/gcc/x86_64-linux-gnu/4.6') - -p.add_option('--with-libstdcxx', action='store_true', - dest='with_libstdcxx', - help='include libstdc++ in the list (inadvisable)') -p.add_option('--libstdcxx-dso-path', metavar='PATH', - help='path to libstdc++ DSO directory', - default='/usr/lib/x86_64-linux-gnu') - -p.add_option('--only-explicit-files', action='store_true', - dest='only_explicit_files', default=False, - help='Only process --lib-file, not the default libc libraries.') p.add_option('--lib-file', action='append', metavar='PATH', help='Specific library files to add.', default=[]) @@ -67,43 +67,10 @@ def defined_function_list(object): (options, args) = p.parse_args() -def build_libs_list(): - libs = [os.path.join(options.libc_dso_path, name) for name in - ['ld-linux-x86-64.so.2', - 'libanl.so.1', - 'libBrokenLocale.so.1', - 'libcidn.so.1', - 'libcrypt.so.1', - 'libc.so.6', - 'libdl.so.2', - 'libm.so.6', - 'libnsl.so.1', - 'libpthread.so.0', - 'libresolv.so.2', - 'librt.so.1', - 'libthread_db.so.1', - 'libutil.so.1']] - libs += [os.path.join(options.libc_archive_path, name) for name in - ['libc_nonshared.a', - 'libpthread_nonshared.a']] - - libs.append(os.path.join(options.libgcc_dso_path, 'libgcc_s.so.1')) - libs.append(os.path.join(options.libgcc_archive_path, 'libgcc.a')) - - if options.with_libstdcxx: - libs.append(os.path.join(options.libstdcxx_dso_path, 'libstdc++.so.6')) - - return libs - -libs = [] -if options.only_explicit_files: - libs = options.lib_file - if not libs: - print >> sys.stderr, 'No libraries provided.' - exit(1) -else: - libs = build_libs_list() - libs.extend(options.lib_file) +libs = options.lib_file +if not libs: + print >> sys.stderr, 'No libraries provided.' + exit(1) missing_lib = False functions = [] diff --git a/compiler-rt/lib/fuzzer/CMakeLists.txt b/compiler-rt/lib/fuzzer/CMakeLists.txt index d51de53f5accd..856cd732d5175 100644 --- a/compiler-rt/lib/fuzzer/CMakeLists.txt +++ b/compiler-rt/lib/fuzzer/CMakeLists.txt @@ -138,15 +138,15 @@ if(OS_NAME MATCHES "Linux|Fuchsia" AND COMPILER_RT_LIBCXX_PATH AND COMPILER_RT_LIBCXXABI_PATH) macro(partially_link_libcxx name dir arch) - if(${arch} MATCHES "i386") - set(EMULATION_ARGUMENT "-m" "elf_i386") - else() - set(EMULATION_ARGUMENT "") + get_target_flags_for_arch(${arch} target_cflags) + if(CMAKE_CXX_COMPILER_ID MATCHES Clang) + get_compiler_rt_target(${arch} target) + set(target_cflags "--target=${target} ${target_cflags}") endif() set(cxx_${arch}_merge_dir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${arch}_merge.dir") file(MAKE_DIRECTORY ${cxx_${arch}_merge_dir}) add_custom_command(TARGET clang_rt.${name}-${arch} POST_BUILD - COMMAND ${CMAKE_LINKER} ${EMULATION_ARGUMENT} --whole-archive "$" --no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o + COMMAND ${CMAKE_CXX_COMPILER} ${target_cflags} -Wl,--whole-archive "$" -Wl,--no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o COMMAND ${CMAKE_OBJCOPY} --localize-hidden ${name}.o COMMAND ${CMAKE_COMMAND} -E remove "$" COMMAND ${CMAKE_AR} qcs "$" ${name}.o diff --git a/compiler-rt/lib/hwasan/hwasan_fuchsia.cpp b/compiler-rt/lib/hwasan/hwasan_fuchsia.cpp index 94e5c5fb69c78..b066d4fdd1142 100644 --- a/compiler-rt/lib/hwasan/hwasan_fuchsia.cpp +++ b/compiler-rt/lib/hwasan/hwasan_fuchsia.cpp @@ -15,6 +15,9 @@ #include "sanitizer_common/sanitizer_fuchsia.h" #if SANITIZER_FUCHSIA +#include +#include + #include "hwasan.h" #include "hwasan_interface_internal.h" #include "hwasan_report.h" @@ -182,9 +185,20 @@ void InstallAtExitHandler() {} void HwasanInstallAtForkHandler() {} -// TODO(fxbug.dev/81499): Once we finalize the tagged pointer ABI in zircon, we should come back -// here and implement the appropriate check that TBI is enabled. -void InitializeOsSupport() {} +void InitializeOsSupport() { +#ifdef __aarch64__ + uint32_t features = 0; + CHECK_EQ(zx_system_get_features(ZX_FEATURE_KIND_ADDRESS_TAGGING, &features), + ZX_OK); + if (features != ZX_ARM64_FEATURE_ADDRESS_TAGGING_TBI && + flags()->fail_without_syscall_abi) { + Printf( + "FATAL: HWAddressSanitizer requires a kernel with tagged address " + "ABI.\n"); + Die(); + } +#endif +} } // namespace __hwasan diff --git a/compiler-rt/lib/lsan/lsan_allocator.h b/compiler-rt/lib/lsan/lsan_allocator.h index 539330491b02a..b67d9d7750efc 100644 --- a/compiler-rt/lib/lsan/lsan_allocator.h +++ b/compiler-rt/lib/lsan/lsan_allocator.h @@ -49,8 +49,7 @@ struct ChunkMetadata { u32 stack_trace_id; }; -#if defined(__mips64) || defined(__aarch64__) || defined(__i386__) || \ - defined(__arm__) || SANITIZER_RISCV64 || defined(__hexagon__) +#if !SANITIZER_CAN_USE_ALLOCATOR64 template struct AP32 { static const uptr kSpaceBeg = 0; @@ -65,7 +64,7 @@ struct AP32 { template using PrimaryAllocatorASVT = SizeClassAllocator32>; using PrimaryAllocator = PrimaryAllocatorASVT; -#elif defined(__x86_64__) || defined(__powerpc64__) || defined(__s390x__) +#else # if SANITIZER_FUCHSIA || defined(__powerpc64__) const uptr kAllocatorSpace = ~(uptr)0; const uptr kAllocatorSize = 0x40000000000ULL; // 4T. diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp index 2e38b1ce8eec3..d6510d34fd689 100644 --- a/compiler-rt/lib/lsan/lsan_common.cpp +++ b/compiler-rt/lib/lsan/lsan_common.cpp @@ -1032,13 +1032,11 @@ SANITIZER_INTERFACE_WEAK_DEF(const char *, __lsan_default_options, void) { } #if !SANITIZER_SUPPORTS_WEAK_HOOKS -SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE int -__lsan_is_turned_off() { +SANITIZER_INTERFACE_WEAK_DEF(int, __lsan_is_turned_off, void) { return 0; } -SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE const char * -__lsan_default_suppressions() { +SANITIZER_INTERFACE_WEAK_DEF(const char *, __lsan_default_suppressions, void) { return ""; } #endif diff --git a/compiler-rt/lib/orc/CMakeLists.txt b/compiler-rt/lib/orc/CMakeLists.txt index 7375934c47ec9..d2786acf3cfe0 100644 --- a/compiler-rt/lib/orc/CMakeLists.txt +++ b/compiler-rt/lib/orc/CMakeLists.txt @@ -9,6 +9,7 @@ set(ORC_SOURCES macho_platform.cpp elfnix_platform.cpp run_program_wrapper.cpp + dlfcn_wrapper.cpp ) # Implementation files for all ORC architectures. diff --git a/compiler-rt/lib/orc/c_api.h b/compiler-rt/lib/orc/c_api.h index 47f46b891d966..96d01df15e86c 100644 --- a/compiler-rt/lib/orc/c_api.h +++ b/compiler-rt/lib/orc/c_api.h @@ -9,9 +9,6 @@ |* *| |* This file defines the C API for the ORC runtime *| |* *| -|* NOTE: The OrtRTWrapperFunctionResult type must be kept in sync with the *| -|* definition in llvm/include/llvm-c/OrcShared.h. *| -|* *| \*===----------------------------------------------------------------------===*/ #ifndef ORC_RT_C_API_H diff --git a/compiler-rt/lib/orc/dlfcn_wrapper.cpp b/compiler-rt/lib/orc/dlfcn_wrapper.cpp new file mode 100644 index 0000000000000..c513aae97bb39 --- /dev/null +++ b/compiler-rt/lib/orc/dlfcn_wrapper.cpp @@ -0,0 +1,52 @@ +//===- dlfcn_wrapper.cpp --------------------------------------------------===// +// +// 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 is a part of the ORC runtime support library. +// +//===----------------------------------------------------------------------===// + +#include "adt.h" +#include "common.h" +#include "wrapper_function_utils.h" + +#include + +using namespace __orc_rt; + +extern "C" const char *__orc_rt_jit_dlerror(); +extern "C" void *__orc_rt_jit_dlopen(const char *path, int mode); +extern "C" int __orc_rt_jit_dlclose(void *dso_handle); + +ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult +__orc_rt_jit_dlerror_wrapper(const char *ArgData, size_t ArgSize) { + return WrapperFunction::handle( + ArgData, ArgSize, + []() { return std::string(__orc_rt_jit_dlerror()); }) + .release(); +} + +ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult +__orc_rt_jit_dlopen_wrapper(const char *ArgData, size_t ArgSize) { + return WrapperFunction::handle( + ArgData, ArgSize, + [](const std::string &Path, int32_t mode) { + return ExecutorAddr::fromPtr( + __orc_rt_jit_dlopen(Path.c_str(), mode)); + }) + .release(); +} + +ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult +__orc_rt_jit_dlclose_wrapper(const char *ArgData, size_t ArgSize) { + return WrapperFunction::handle( + ArgData, ArgSize, + [](ExecutorAddr &DSOHandle) { + return __orc_rt_jit_dlclose(DSOHandle.toPtr()); + }) + .release(); +} diff --git a/compiler-rt/lib/orc/elfnix_platform.cpp b/compiler-rt/lib/orc/elfnix_platform.cpp index 7800bcd7ff15a..6f502b20f8caf 100644 --- a/compiler-rt/lib/orc/elfnix_platform.cpp +++ b/compiler-rt/lib/orc/elfnix_platform.cpp @@ -15,6 +15,7 @@ #include "error.h" #include "wrapper_function_utils.h" +#include #include #include #include @@ -133,12 +134,6 @@ class ELFNixPlatformRuntimeState { static ELFNixPlatformRuntimeState *MOPS; - using InitSectionHandler = - Error (*)(const std::vector &Sections, - const ELFNixJITDylibInitializers &MOJDIs); - const std::vector> InitSections = - {{".init_array", runInitArray}}; - void *PlatformJDDSOHandle; // FIXME: Move to thread-state. @@ -378,21 +373,29 @@ Expected ELFNixPlatformRuntimeState::dlopenInitialize(string_view Path, return JDS->Header; } +long getPriority(const std::string &name) { + auto pos = name.find_last_not_of("0123456789"); + if (pos == name.size() - 1) + return 65535; + else + return std::strtol(name.c_str() + pos + 1, nullptr, 10); +} + Error ELFNixPlatformRuntimeState::initializeJITDylib( ELFNixJITDylibInitializers &MOJDIs) { auto &JDS = getOrCreateJITDylibState(MOJDIs); ++JDS.RefCount; - for (auto &KV : InitSections) { - const auto &Name = KV.first; - const auto &Handler = KV.second; - auto I = MOJDIs.InitSections.find(Name); - if (I != MOJDIs.InitSections.end()) { - if (auto Err = Handler(I->second, MOJDIs)) - return Err; - } - } + using SectionList = std::vector; + std::sort(MOJDIs.InitSections.begin(), MOJDIs.InitSections.end(), + [](const std::pair &LHS, + const std::pair &RHS) -> bool { + return getPriority(LHS.first) < getPriority(RHS.first); + }); + for (auto &Entry : MOJDIs.InitSections) + if (auto Err = runInitArray(Entry.second, MOJDIs)) + return Err; return Error::success(); } diff --git a/compiler-rt/lib/orc/elfnix_platform.h b/compiler-rt/lib/orc/elfnix_platform.h index 12b9591979b77..e0ee9591dfc62 100644 --- a/compiler-rt/lib/orc/elfnix_platform.h +++ b/compiler-rt/lib/orc/elfnix_platform.h @@ -47,7 +47,7 @@ struct ELFNixJITDylibInitializers { std::string Name; ExecutorAddr DSOHandleAddress; - std::unordered_map InitSections; + std::vector> InitSections; }; class ELFNixJITDylibDeinitializers {}; diff --git a/compiler-rt/lib/profile/InstrProfilingUtil.c b/compiler-rt/lib/profile/InstrProfilingUtil.c index cd179d03bc831..cd18cba3e268f 100644 --- a/compiler-rt/lib/profile/InstrProfilingUtil.c +++ b/compiler-rt/lib/profile/InstrProfilingUtil.c @@ -46,7 +46,7 @@ #include "InstrProfiling.h" #include "InstrProfilingUtil.h" -COMPILER_RT_WEAK unsigned lprofDirMode = 0755; +COMPILER_RT_VISIBILITY unsigned lprofDirMode = 0755; COMPILER_RT_VISIBILITY void __llvm_profile_recursive_mkdir(char *path) { diff --git a/compiler-rt/lib/safestack/safestack_platform.h b/compiler-rt/lib/safestack/safestack_platform.h index 81e4c2645ce25..2b1fc139baa90 100644 --- a/compiler-rt/lib/safestack/safestack_platform.h +++ b/compiler-rt/lib/safestack/safestack_platform.h @@ -94,7 +94,7 @@ inline void *Mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { #if SANITIZER_NETBSD return __mmap(addr, length, prot, flags, fd, 0, offset); -#elif defined(__x86_64__) && (SANITIZER_FREEBSD) +#elif SANITIZER_FREEBSD && (defined(__aarch64__) || defined(__x86_64__)) return (void *)__syscall(SYS_mmap, addr, length, prot, flags, fd, offset); #else return (void *)syscall(SYS_mmap, addr, length, prot, flags, fd, offset); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp index 1c6520819ef93..129f925e6fb68 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp @@ -128,8 +128,7 @@ void NORETURN ReportAllocationSizeTooBig(uptr user_size, uptr max_size, void NORETURN ReportOutOfMemory(uptr requested_size, const StackTrace *stack) { { ScopedAllocatorErrorReport report("out-of-memory", stack); - Report("ERROR: %s: allocator is out of memory trying to allocate 0x%zx " - "bytes\n", SanitizerToolName, requested_size); + ERROR_OOM("allocator is trying to allocate 0x%zx bytes\n", requested_size); } Die(); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp index 0b7401f925f2f..82236453157fa 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp @@ -46,9 +46,15 @@ void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, Die(); } recursion_count++; - Report("ERROR: %s failed to " - "%s 0x%zx (%zd) bytes of %s (error code: %d)\n", - SanitizerToolName, mmap_type, size, size, mem_type, err); + if (ErrorIsOOM(err)) { + ERROR_OOM("failed to %s 0x%zx (%zd) bytes of %s (error code: %d)\n", + mmap_type, size, size, mem_type, err); + } else { + Report( + "ERROR: %s failed to " + "%s 0x%zx (%zd) bytes of %s (error code: %d)\n", + SanitizerToolName, mmap_type, size, size, mem_type, err); + } #if !SANITIZER_GO DumpProcessMap(); #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 9614883a96057..345c262af9728 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -311,6 +311,18 @@ void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, const char *mmap_type, error_t err, bool raw_report = false); +// Returns true if the platform-specific error reported is an OOM error. +bool ErrorIsOOM(error_t err); + +// This reports an error in the form: +// +// `ERROR: {{SanitizerToolName}}: out of memory: {{err_msg}}` +// +// Downstream tools that read sanitizer output will know that errors starting +// in this format are specifically OOM errors. +#define ERROR_OOM(err_msg, ...) \ + Report("ERROR: %s: out of memory: " err_msg, SanitizerToolName, __VA_ARGS__) + // Specific tools may override behavior of "Die" function to do tool-specific // job. typedef void (*DieCallbackType)(void); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 3b316f5edea80..9b828ffc36e47 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -1367,8 +1367,13 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3, void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5); static const int PR_SET_NAME = 15; + static const int PR_SET_VMA = 0x53564d41; static const int PR_SCHED_CORE = 62; static const int PR_SCHED_CORE_GET = 0; + if (option == PR_SET_VMA && arg2 == 0UL) { + char *name = (char *)arg5; + COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1); + } int res = REAL(prctl(option, arg2, arg3, arg4, arg5)); if (option == PR_SET_NAME) { char buff[16]; @@ -2518,13 +2523,31 @@ INTERCEPTOR(int, __b64_pton, char const *src, char *target, SIZE_T targsize) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, target, res); return res; } -# define INIT___B64_TO \ +#define INIT___B64_TO \ COMMON_INTERCEPT_FUNCTION(__b64_ntop); \ COMMON_INTERCEPT_FUNCTION(__b64_pton); #else // SANITIZER_INTERCEPT___B64_TO #define INIT___B64_TO #endif // SANITIZER_INTERCEPT___B64_TO +#if SANITIZER_INTERCEPT___DN_EXPAND + INTERCEPTOR(int, __dn_expand, unsigned char const *base, + unsigned char const *end, unsigned char const *src, char *dest, + int space) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, __dn_expand, base, end, src, dest, space); + // TODO: add read check if __dn_comp intercept added + int res = REAL(__dn_expand)(base, end, src, dest, space); + if (res >= 0) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res + 1); + return res; +} +#define INIT___DN_EXPAND \ + COMMON_INTERCEPT_FUNCTION(__dn_expand); +#else // SANITIZER_INTERCEPT___DN_EXPAND +#define INIT___DN_EXPAND +#endif // SANITIZER_INTERCEPT___DN_EXPAND + #if SANITIZER_INTERCEPT_POSIX_SPAWN @@ -4945,6 +4968,27 @@ INTERCEPTOR(int, pthread_attr_getaffinity_np, void *attr, SIZE_T cpusetsize, #define INIT_PTHREAD_ATTR_GETAFFINITY_NP #endif +#if SANITIZER_INTERCEPT_PTHREAD_GETAFFINITY_NP +INTERCEPTOR(int, pthread_getaffinity_np, void *attr, SIZE_T cpusetsize, + void *cpuset) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, pthread_getaffinity_np, attr, cpusetsize, + cpuset); + // FIXME: under ASan the call below may write to freed memory and corrupt + // its metadata. See + // https://github.com/google/sanitizers/issues/321. + int res = REAL(pthread_getaffinity_np)(attr, cpusetsize, cpuset); + if (!res && cpusetsize && cpuset) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize); + return res; +} + +#define INIT_PTHREAD_GETAFFINITY_NP \ + COMMON_INTERCEPT_FUNCTION(pthread_getaffinity_np); +#else +#define INIT_PTHREAD_GETAFFINITY_NP +#endif + #if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED INTERCEPTOR_PTHREAD_MUTEXATTR_GET(pshared, sizeof(int)) #define INIT_PTHREAD_MUTEXATTR_GETPSHARED \ @@ -10310,6 +10354,42 @@ INTERCEPTOR(int, sigaltstack, void *ss, void *oss) { #define INIT_SIGALTSTACK #endif +#if SANITIZER_INTERCEPT_PROCCTL +INTERCEPTOR(int, procctl, int idtype, u64 id, int cmd, uptr data) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, procctl, idtype, id, cmd, data); + static const int PROC_REAP_ACQUIRE = 2; + static const int PROC_REAP_RELEASE = 3; + static const int PROC_REAP_STATUS = 4; + static const int PROC_REAP_GETPIDS = 5; + static const int PROC_REAP_KILL = 6; + if (cmd < PROC_REAP_ACQUIRE || cmd > PROC_REAP_KILL) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)data, sizeof(int)); + } else { + // reap_acquire/reap_release bears no arguments. + if (cmd > PROC_REAP_RELEASE) { + unsigned int reapsz; + switch (cmd) { + case PROC_REAP_STATUS: + reapsz = struct_procctl_reaper_status_sz; + break; + case PROC_REAP_GETPIDS: + reapsz = struct_procctl_reaper_pids_sz; + break; + case PROC_REAP_KILL: + reapsz = struct_procctl_reaper_kill_sz; + break; + } + COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)data, reapsz); + } + } + return REAL(procctl)(idtype, id, cmd, data); +} +#define INIT_PROCCTL COMMON_INTERCEPT_FUNCTION(procctl) +#else +#define INIT_PROCCTL +#endif + #if SANITIZER_INTERCEPT_UNAME INTERCEPTOR(int, uname, struct utsname *utsname) { #if SANITIZER_LINUX @@ -10427,6 +10507,7 @@ static void InitializeCommonInterceptors() { INIT_GLOB; INIT_GLOB64; INIT___B64_TO; + INIT___DN_EXPAND; INIT_POSIX_SPAWN; INIT_WAIT; INIT_WAIT4; @@ -10516,6 +10597,7 @@ static void InitializeCommonInterceptors() { INIT_PTHREAD_ATTR_GET_SCHED; INIT_PTHREAD_ATTR_GETINHERITSCHED; INIT_PTHREAD_ATTR_GETAFFINITY_NP; + INIT_PTHREAD_GETAFFINITY_NP; INIT_PTHREAD_MUTEXATTR_GETPSHARED; INIT_PTHREAD_MUTEXATTR_GETTYPE; INIT_PTHREAD_MUTEXATTR_GETPROTOCOL; @@ -10667,6 +10749,7 @@ static void InitializeCommonInterceptors() { INIT_QSORT_R; INIT_BSEARCH; INIT_SIGALTSTACK; + INIT_PROCCTL INIT_UNAME; INIT___XUNAME; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp index 848953a6ab007..d8cf93ecbeca2 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp @@ -128,6 +128,8 @@ uptr GetMaxUserVirtualAddress() { uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); } +bool ErrorIsOOM(error_t err) { return err == ZX_ERR_NO_MEMORY; } + static void *DoAnonymousMmapOrDie(uptr size, const char *mem_type, bool raw_report, bool die_for_nomem) { size = RoundUpTo(size, GetPageSize()); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp index 6c6f40a4c05ac..47acf10650dd0 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -901,6 +901,10 @@ bool internal_sigismember(__sanitizer_sigset_t *set, int signum) { return k_set->sig[idx] & ((uptr)1 << bit); } #elif SANITIZER_FREEBSD +uptr internal_procctl(int type, int id, int cmd, void *data) { + return internal_syscall(SYSCALL(procctl), type, id, cmd, data); +} + void internal_sigdelset(__sanitizer_sigset_t *set, int signum) { sigset_t *rset = reinterpret_cast(set); sigdelset(rset, signum); @@ -1789,7 +1793,7 @@ void *internal_start_thread(void *(*func)(void *), void *arg) { return 0; } void internal_join_thread(void *th) {} #endif -#if defined(__aarch64__) +#if SANITIZER_LINUX && defined(__aarch64__) // Android headers in the older NDK releases miss this definition. struct __sanitizer_esr_context { struct _aarch64_ctx head; @@ -1810,6 +1814,11 @@ static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) { } return false; } +#elif SANITIZER_FREEBSD && defined(__aarch64__) +// FreeBSD doesn't provide ESR in the ucontext. +static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) { + return false; +} #endif using Context = ucontext_t; @@ -2035,10 +2044,17 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { *bp = ucontext->uc_mcontext.arm_fp; *sp = ucontext->uc_mcontext.arm_sp; #elif defined(__aarch64__) +# if SANITIZER_FREEBSD + ucontext_t *ucontext = (ucontext_t*)context; + *pc = ucontext->uc_mcontext.mc_gpregs.gp_elr; + *bp = ucontext->uc_mcontext.mc_gpregs.gp_x[29]; + *sp = ucontext->uc_mcontext.mc_gpregs.gp_sp; +# else ucontext_t *ucontext = (ucontext_t*)context; *pc = ucontext->uc_mcontext.pc; *bp = ucontext->uc_mcontext.regs[29]; *sp = ucontext->uc_mcontext.sp; +# endif #elif defined(__hppa__) ucontext_t *ucontext = (ucontext_t*)context; *pc = ucontext->uc_mcontext.sc_iaoq[0]; @@ -2186,7 +2202,8 @@ void CheckASLR() { } #elif SANITIZER_FREEBSD int aslr_status; - if (UNLIKELY(procctl(P_PID, 0, PROC_ASLR_STATUS, &aslr_status) == -1)) { + int r = internal_procctl(P_PID, 0, PROC_ASLR_STATUS, &aslr_status); + if (UNLIKELY(r == -1)) { // We're making things less 'dramatic' here since // the cmd is not necessarily guaranteed to be here // just yet regarding FreeBSD release diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h index ebd60e0b10f27..45d8c921da12c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h @@ -82,6 +82,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, #endif int internal_uname(struct utsname *buf); #elif SANITIZER_FREEBSD +uptr internal_procctl(int type, int id, int cmd, void *data); void internal_sigdelset(__sanitizer_sigset_t *set, int signum); #elif SANITIZER_NETBSD void internal_sigdelset(__sanitizer_sigset_t *set, int signum); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h index 66141dc091145..7676e1ca264d6 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h @@ -65,7 +65,8 @@ #if defined(__APPLE__) # define SANITIZER_APPLE 1 // SANITIZER_MAC will be deprecated/removed in the future -# define SANITIZER_MAC SANITIZER_APPLE +# define SANITIZER_MAC \ + error "SANITIZER_MAC will be removed, please use SANITIZER_APPLE" # include # if TARGET_OS_OSX # define SANITIZER_OSX 1 @@ -99,7 +100,8 @@ # endif #else # define SANITIZER_APPLE 0 -# define SANITIZER_MAC SANITIZER_APPLE +# define SANITIZER_MAC \ + error "SANITIZER_MAC will be removed, please use SANITIZER_APPLE" # define SANITIZER_OSX 0 # define SANITIZER_IOS 0 # define SANITIZER_WATCHOS 0 @@ -283,7 +285,8 @@ #ifndef SANITIZER_CAN_USE_ALLOCATOR64 # if (SANITIZER_ANDROID && defined(__aarch64__)) || SANITIZER_FUCHSIA # define SANITIZER_CAN_USE_ALLOCATOR64 1 -# elif defined(__mips64) || defined(__aarch64__) +# elif defined(__mips64) || defined(__aarch64__) || defined(__i386__) || \ + defined(__arm__) || SANITIZER_RISCV64 || defined(__hexagon__) # define SANITIZER_CAN_USE_ALLOCATOR64 0 # else # define SANITIZER_CAN_USE_ALLOCATOR64 (SANITIZER_WORDSIZE == 64) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 8d31f5aeca9e0..f81d61474af6f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -236,6 +236,7 @@ #define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS) #define SANITIZER_INTERCEPT_GLOB64 SI_GLIBC #define SANITIZER_INTERCEPT___B64_TO SI_LINUX_NOT_ANDROID +#define SANITIZER_INTERCEPT___DN_EXPAND SI_LINUX_NOT_ANDROID #define SANITIZER_INTERCEPT_POSIX_SPAWN SI_POSIX #define SANITIZER_INTERCEPT_WAIT SI_POSIX #define SANITIZER_INTERCEPT_INET SI_POSIX @@ -347,6 +348,7 @@ #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED \ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP SI_GLIBC +#define SANITIZER_INTERCEPT_PTHREAD_GETAFFINITY_NP SI_LINUX_NOT_ANDROID #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED SI_POSIX #define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED \ (SI_POSIX && !SI_NETBSD) @@ -591,6 +593,7 @@ #define SANITIZER_INTERCEPT_UNAME (SI_POSIX && !SI_FREEBSD) #define SANITIZER_INTERCEPT___XUNAME SI_FREEBSD #define SANITIZER_INTERCEPT_FLOPEN SI_FREEBSD +#define SANITIZER_INTERCEPT_PROCCTL SI_FREEBSD // This macro gives a way for downstream users to override the above // interceptor macros irrespective of the platform they are on. They have diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp index 0d25fa80e2ed8..37e72cd5d45ea 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp @@ -205,6 +205,10 @@ unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info); unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats); unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req); unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req); +unsigned struct_procctl_reaper_status_sz = sizeof(struct __sanitizer_procctl_reaper_status); +unsigned struct_procctl_reaper_pidinfo_sz = sizeof(struct __sanitizer_procctl_reaper_pidinfo); +unsigned struct_procctl_reaper_pids_sz = sizeof(struct __sanitizer_procctl_reaper_pids); +unsigned struct_procctl_reaper_kill_sz = sizeof(struct __sanitizer_procctl_reaper_kill); const unsigned long __sanitizer_bufsiz = BUFSIZ; const unsigned IOCTL_NOT_PRESENT = 0; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h index 9859c52ec69f3..daef1177a2dba 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h @@ -424,6 +424,38 @@ struct __sanitizer__ttyent { char *ty_group; }; +// procctl reaper data for PROCCTL_REAPER flags +struct __sanitizer_procctl_reaper_status { + unsigned int rs_flags; + unsigned int rs_children; + unsigned int rs_descendants; + pid_t rs_reaper; + pid_t rs_pid; + unsigned int rs_pad0[15]; +}; + +struct __sanitizer_procctl_reaper_pidinfo { + pid_t pi_pid; + pid_t pi_subtree; + unsigned int pi_flags; + unsigned int pi_pad0[15]; +}; + +struct __sanitizer_procctl_reaper_pids { + unsigned int rp_count; + unsigned int rp_pad0[15]; + struct __sanitize_procctl_reapper_pidinfo *rp_pids; +}; + +struct __sanitizer_procctl_reaper_kill { + int rk_sig; + unsigned int rk_flags; + pid_t rk_subtree; + unsigned int rk_killed; + pid_t rk_fpid; + unsigned int rk_pad[15]; +}; + # define IOC_NRBITS 8 # define IOC_TYPEBITS 8 # if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__) @@ -480,6 +512,11 @@ extern unsigned struct_ppp_stats_sz; extern unsigned struct_sioc_sg_req_sz; extern unsigned struct_sioc_vif_req_sz; +extern unsigned struct_procctl_reaper_status_sz; +extern unsigned struct_procctl_reaper_pidinfo_sz; +extern unsigned struct_procctl_reaper_pids_sz; +extern unsigned struct_procctl_reaper_kill_sz; + // ioctl request identifiers // A special value to mark ioctls that are not present on the target platform, diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp index ecfcffb34a5a2..2de160d8da563 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp @@ -152,7 +152,6 @@ typedef struct user_fpregs elf_fpregset_t; #include #include #include -#include #endif // SANITIZER_ANDROID #include @@ -172,8 +171,13 @@ typedef struct user_fpregs elf_fpregset_t; // Include these after system headers to avoid name clashes and ambiguities. # include "sanitizer_common.h" # include "sanitizer_internal_defs.h" +# include "sanitizer_platform_interceptors.h" # include "sanitizer_platform_limits_posix.h" +#if SANITIZER_INTERCEPT_CRYPT_R +#include +#endif + namespace __sanitizer { unsigned struct_utsname_sz = sizeof(struct utsname); unsigned struct_stat_sz = sizeof(struct stat); @@ -271,9 +275,12 @@ namespace __sanitizer { unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT; unsigned struct_rlimit64_sz = sizeof(struct rlimit64); unsigned struct_statvfs64_sz = sizeof(struct statvfs64); - unsigned struct_crypt_data_sz = sizeof(struct crypt_data); #endif // SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_INTERCEPT_CRYPT_R + unsigned struct_crypt_data_sz = sizeof(struct crypt_data); +#endif + #if SANITIZER_LINUX && !SANITIZER_ANDROID unsigned struct_timex_sz = sizeof(struct timex); unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp index 19dfaa9e4e017..b0e32b50c0764 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp @@ -41,6 +41,8 @@ uptr GetMmapGranularity() { return GetPageSize(); } +bool ErrorIsOOM(error_t err) { return err == ENOMEM; } + void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { size = RoundUpTo(size, GetPageSizeCached()); uptr res = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE, diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h index df122ed3425c3..29a08386d0b9f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h @@ -90,9 +90,10 @@ class SymbolizerProcess { // Customizable by subclasses. virtual bool StartSymbolizerSubprocess(); - virtual bool ReadFromSymbolizer(char *buffer, uptr max_length); + virtual bool ReadFromSymbolizer(); // Return the environment to run the symbolizer in. virtual char **GetEnvP() { return GetEnviron(); } + InternalMmapVector &GetBuff() { return buffer_; } private: virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const { @@ -113,8 +114,7 @@ class SymbolizerProcess { fd_t input_fd_; fd_t output_fd_; - static const uptr kBufferSize = 16 * 1024; - char buffer_[kBufferSize]; + InternalMmapVector buffer_; static const uptr kMaxTimesRestarted = 5; static const int kSymbolizerStartupTimeMillis = 10; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp index 9177990418566..16cb65e1aac96 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp @@ -500,9 +500,9 @@ const char *SymbolizerProcess::SendCommandImpl(const char *command) { return nullptr; if (!WriteToSymbolizer(command, internal_strlen(command))) return nullptr; - if (!ReadFromSymbolizer(buffer_, kBufferSize)) - return nullptr; - return buffer_; + if (!ReadFromSymbolizer()) + return nullptr; + return buffer_.data(); } bool SymbolizerProcess::Restart() { @@ -513,31 +513,33 @@ bool SymbolizerProcess::Restart() { return StartSymbolizerSubprocess(); } -bool SymbolizerProcess::ReadFromSymbolizer(char *buffer, uptr max_length) { - if (max_length == 0) - return true; - uptr read_len = 0; - while (true) { +bool SymbolizerProcess::ReadFromSymbolizer() { + buffer_.clear(); + constexpr uptr max_length = 1024; + bool ret = true; + do { uptr just_read = 0; - bool success = ReadFromFile(input_fd_, buffer + read_len, - max_length - read_len - 1, &just_read); + uptr size_before = buffer_.size(); + buffer_.resize(size_before + max_length); + buffer_.resize(buffer_.capacity()); + bool ret = ReadFromFile(input_fd_, &buffer_[size_before], + buffer_.size() - size_before, &just_read); + + if (!ret) + just_read = 0; + + buffer_.resize(size_before + just_read); + // We can't read 0 bytes, as we don't expect external symbolizer to close // its stdout. - if (!success || just_read == 0) { + if (just_read == 0) { Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_); - return false; - } - read_len += just_read; - if (ReachedEndOfOutput(buffer, read_len)) - break; - if (read_len + 1 == max_length) { - Report("WARNING: Symbolizer buffer too small\n"); - read_len = 0; + ret = false; break; } - } - buffer[read_len] = '\0'; - return true; + } while (!ReachedEndOfOutput(buffer_.data(), buffer_.size())); + buffer_.push_back('\0'); + return ret; } bool SymbolizerProcess::WriteToSymbolizer(const char *buffer, uptr length) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp index 6f18d7cbd7470..8be7709b6038b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp @@ -225,24 +225,24 @@ class Addr2LineProcess final : public SymbolizerProcess { bool ReachedEndOfOutput(const char *buffer, uptr length) const override; - bool ReadFromSymbolizer(char *buffer, uptr max_length) override { - if (!SymbolizerProcess::ReadFromSymbolizer(buffer, max_length)) + bool ReadFromSymbolizer() override { + if (!SymbolizerProcess::ReadFromSymbolizer()) return false; - // The returned buffer is empty when output is valid, but exceeds - // max_length. - if (*buffer == '\0') - return true; + auto &buff = GetBuff(); // We should cut out output_terminator_ at the end of given buffer, // appended by addr2line to mark the end of its meaningful output. // We cannot scan buffer from it's beginning, because it is legal for it // to start with output_terminator_ in case given offset is invalid. So, // scanning from second character. - char *garbage = internal_strstr(buffer + 1, output_terminator_); + char *garbage = internal_strstr(buff.data() + 1, output_terminator_); // This should never be NULL since buffer must end up with // output_terminator_. CHECK(garbage); + // Trim the buffer. - garbage[0] = '\0'; + uintptr_t new_size = garbage - buff.data(); + GetBuff().resize(new_size); + GetBuff().push_back('\0'); return true; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc b/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc index eb41ff9ccbed5..e7f95d33ad0d3 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc @@ -19,7 +19,8 @@ # define SYSCALL(name) __NR_ ## name #endif -#if defined(__x86_64__) && (SANITIZER_FREEBSD || SANITIZER_APPLE) +#if (defined(__x86_64__) && (SANITIZER_FREEBSD || SANITIZER_APPLE)) || \ + (defined(__aarch64__) && SANITIZER_FREEBSD) # define internal_syscall __syscall # else # define internal_syscall syscall diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp index 53770331199fd..c997514cfed7f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp @@ -131,6 +131,11 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, } #endif // #if !SANITIZER_GO +bool ErrorIsOOM(error_t err) { + // TODO: This should check which `err`s correspond to OOM. + return false; +} + void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (rv == 0) diff --git a/compiler-rt/lib/sanitizer_common/symbolizer/scripts/ar_to_bc.sh b/compiler-rt/lib/sanitizer_common/symbolizer/scripts/ar_to_bc.sh index fa05d61a7c6d9..7b69539ec59da 100755 --- a/compiler-rt/lib/sanitizer_common/symbolizer/scripts/ar_to_bc.sh +++ b/compiler-rt/lib/sanitizer_common/symbolizer/scripts/ar_to_bc.sh @@ -30,7 +30,12 @@ pushd $SCRATCH_DIR for INPUT in *; do for OBJ in $($AR t $INPUT); do $AR x $INPUT $OBJ - mv -f $OBJ $(basename $INPUT).$OBJ + if [[ $(file $OBJ) =~ 'LLVM IR bitcode' ]]; then + mv -f $OBJ $(basename $INPUT).$OBJ + else + # Skip $OBJ which may come from an assembly file (e.g. Support/BLAKE3/*.S). + rm -f $OBJ + fi done done diff --git a/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh b/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh index 196a876a6e7e4..599f063b45c9b 100755 --- a/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh +++ b/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh @@ -140,7 +140,6 @@ if [[ ! -d ${LLVM_BUILD} ]]; then -DLLVM_ENABLE_ZLIB=ON \ -DLLVM_ENABLE_TERMINFO=OFF \ -DLLVM_ENABLE_THREADS=OFF \ - -DLLVM_DISABLE_ASSEMBLY_FILES=ON \ $LLVM_SRC fi cd ${LLVM_BUILD} diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_leb128_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_leb128_test.cpp index c0c75c4705045..ae4c8b5d8b218 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_leb128_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_leb128_test.cpp @@ -25,10 +25,12 @@ static uptr BitsNeeded(u64 v) { if (!v) return 1; uptr r = 0; - uptr uptr_bits = 8 * sizeof(uptr); - while (v >> uptr_bits) { - r += uptr_bits; - v >>= uptr_bits; + if (sizeof(uptr) != sizeof(u64)) { + uptr uptr_bits = 8 * sizeof(uptr); + while (v >> uptr_bits) { + r += uptr_bits; + v >>= uptr_bits; + } } return r + MostSignificantSetBitIndex(v) + 1; } diff --git a/compiler-rt/lib/scudo/standalone/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/CMakeLists.txt index e293db18d30ed..f439f6f9d2d6f 100644 --- a/compiler-rt/lib/scudo/standalone/CMakeLists.txt +++ b/compiler-rt/lib/scudo/standalone/CMakeLists.txt @@ -36,6 +36,7 @@ list(APPEND SCUDO_LINK_FLAGS -ffunction-sections -fdata-sections -Wl,--gc-sectio # We don't use the C++ standard library, so avoid including it by mistake. append_list_if(COMPILER_RT_HAS_NOSTDLIBXX_FLAG -nostdlib++ SCUDO_LINK_FLAGS) +append_list_if(CXX_SUPPORTS_UNWINDLIB_NONE_FLAG --unwindlib=none SCUDO_LINK_FLAGS) if(ANDROID) list(APPEND SCUDO_CFLAGS -fno-emulated-tls) diff --git a/compiler-rt/lib/scudo/standalone/fuchsia.cpp b/compiler-rt/lib/scudo/standalone/fuchsia.cpp index 088f077b4d9eb..8ab2b382a36a8 100644 --- a/compiler-rt/lib/scudo/standalone/fuchsia.cpp +++ b/compiler-rt/lib/scudo/standalone/fuchsia.cpp @@ -89,6 +89,8 @@ void *map(void *Addr, uptr Size, const char *Name, uptr Flags, uintptr_t P; zx_vm_option_t MapFlags = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_ALLOW_FAULTS; + if (Addr) + DCHECK(Data); const uint64_t Offset = Addr ? reinterpret_cast(Addr) - Data->VmarBase : 0; if (Offset) diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp index 17dbdff8a5393..807f6be2eee37 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp @@ -402,7 +402,11 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) { #elif defined(__powerpc__) # define LONG_JMP_SP_ENV_SLOT 0 #elif SANITIZER_FREEBSD -# define LONG_JMP_SP_ENV_SLOT 2 +# ifdef __aarch64__ +# define LONG_JMP_SP_ENV_SLOT 1 +# else +# define LONG_JMP_SP_ENV_SLOT 2 +# endif #elif SANITIZER_LINUX # ifdef __aarch64__ # define LONG_JMP_SP_ENV_SLOT 13 diff --git a/compiler-rt/test/asan/TestCases/suppressions-library.cpp b/compiler-rt/test/asan/TestCases/suppressions-library.cpp index 39ede0840105d..d11802a20ad3f 100644 --- a/compiler-rt/test/asan/TestCases/suppressions-library.cpp +++ b/compiler-rt/test/asan/TestCases/suppressions-library.cpp @@ -4,7 +4,6 @@ // Check that without suppressions, we catch the issue. // RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s -// FIXME: Remove usage of backticks around basename below. // REQUIRES: shell // RUN: echo "interceptor_via_lib:"%xdynamiclib_filename > %t.supp diff --git a/compiler-rt/test/fuzzer/TableLookupTest.cpp b/compiler-rt/test/fuzzer/TableLookupTest.cpp index 247963cca698e..3d0246138264c 100644 --- a/compiler-rt/test/fuzzer/TableLookupTest.cpp +++ b/compiler-rt/test/fuzzer/TableLookupTest.cpp @@ -22,7 +22,7 @@ const size_t N = 1 << 12; // Use either `Counters[Idx] = 1` or `Counters[Idx]++;` // depending on whether multiple occurrences of the event 'Idx' // is important to distinguish from one occurrence. -#ifdef __linux__ +#if defined(__linux__) || defined(__FreeBSD__) __attribute__((section("__libfuzzer_extra_counters"))) #endif #ifdef _WIN32 diff --git a/compiler-rt/test/hwasan/TestCases/sizes.cpp b/compiler-rt/test/hwasan/TestCases/sizes.cpp index 4a1156b91b5cb..2cb70f52147ac 100644 --- a/compiler-rt/test/hwasan/TestCases/sizes.cpp +++ b/compiler-rt/test/hwasan/TestCases/sizes.cpp @@ -84,6 +84,6 @@ int main(int argc, char **argv) { } // CHECK-max: {{ERROR: HWAddressSanitizer: requested allocation size .* exceeds maximum supported size}} -// CHECK-oom: ERROR: HWAddressSanitizer: allocator is out of memory +// CHECK-oom: ERROR: HWAddressSanitizer: out of memory: allocator is trying to allocate // CHECK-calloc: ERROR: HWAddressSanitizer: calloc parameters overflow // CHECK-reallocarray: ERROR: HWAddressSanitizer: reallocarray parameters overflow diff --git a/compiler-rt/test/msan/Linux/b64.cpp b/compiler-rt/test/msan/Linux/b64.cpp index 1eb72800af203..90a31db233c78 100644 --- a/compiler-rt/test/msan/Linux/b64.cpp +++ b/compiler-rt/test/msan/Linux/b64.cpp @@ -1,4 +1,4 @@ -// RUN: %clangxx_msan -O0 %s -o %t -lresolv && %run %t +// RUN: %clangxx_msan -O0 %s -o %t && %run %t // RUN: not %run %t NTOP_READ 2>&1 | FileCheck %s --check-prefix=NTOP_READ // RUN: not %run %t PTON_READ 2>&1 | FileCheck %s --check-prefix=PTON_READ diff --git a/compiler-rt/test/msan/Linux/dn_expand.cpp b/compiler-rt/test/msan/Linux/dn_expand.cpp new file mode 100644 index 0000000000000..a7b2b37562edd --- /dev/null +++ b/compiler-rt/test/msan/Linux/dn_expand.cpp @@ -0,0 +1,42 @@ +// RUN: %clangxx_msan -O0 %s -o %t && %run %t + +#include +#include +#include + +#include + +void testWrite() { + char unsigned input[] = {0xff, 0xc5, 0xf7, 0xff, 0x00, 0x00, 0xff, 0x0a, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x10, 0x01, 0x05, 0x00, 0x01, 0x0a, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00}; + char output[1024]; + + int res = dn_expand(input, input + sizeof(input), input + 23, output, + sizeof(output)); + + assert(res >= 0); + __msan_check_mem_is_initialized(output, res); +} + +void testWriteZeroLength() { + char unsigned input[] = { + 0xff, 0xc5, 0xf7, 0xff, 0x00, 0x00, 0xff, 0x0a, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x10, 0x01, 0x05, 0x00, 0x01, 0x00, + }; + char output[1024]; + + int res = dn_expand(input, input + sizeof(input), input + 23, output, + sizeof(output)); + + assert(res >= 0); + __msan_check_mem_is_initialized(output, res); +} + +int main(int iArgc, const char *szArgv[]) { + testWrite(); + testWriteZeroLength(); + + return 0; +} diff --git a/compiler-rt/test/msan/Linux/pthread_getaffinity_np.cpp b/compiler-rt/test/msan/Linux/pthread_getaffinity_np.cpp new file mode 100644 index 0000000000000..e87b898a7bc5d --- /dev/null +++ b/compiler-rt/test/msan/Linux/pthread_getaffinity_np.cpp @@ -0,0 +1,15 @@ +// RUN: %clangxx_msan -O0 %s -o %t && %run %t + +#include +#include + +#include + +int main() { + cpu_set_t set_x[4]; + int res = pthread_getaffinity_np(pthread_self(), sizeof(set_x), set_x); + assert(res == 0); + __msan_check_mem_is_initialized(set_x, sizeof(set_x)); + + return 0; +} diff --git a/compiler-rt/test/orc/TestCases/Darwin/x86-64/lljit-ehframe.cpp b/compiler-rt/test/orc/TestCases/Darwin/x86-64/lljit-ehframe.cpp new file mode 100644 index 0000000000000..b73ec2387028e --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Darwin/x86-64/lljit-ehframe.cpp @@ -0,0 +1,15 @@ +// RUN: %clangxx -fPIC -emit-llvm -c -o %t %s +// RUN: %lli_orc_jitlink -relocation-model=pic %t | FileCheck %s + +// CHECK: catch + +#include + +int main(int argc, char *argv[]) { + try { + throw 0; + } catch (int X) { + puts("catch"); + } + return 0; +} diff --git a/compiler-rt/test/orc/TestCases/Darwin/x86-64/lljit-initialize-deinitialize.ll b/compiler-rt/test/orc/TestCases/Darwin/x86-64/lljit-initialize-deinitialize.ll new file mode 100644 index 0000000000000..e5b976423238b --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Darwin/x86-64/lljit-initialize-deinitialize.ll @@ -0,0 +1,32 @@ +; RUN: %lli_orc_jitlink -relocation-model=pic %s | FileCheck %s + +; CHECK: constructor +; CHECK-NEXT: main +; CHECK-NEXT: destructor + +@__dso_handle = external hidden global i8 +@.str = private unnamed_addr constant [5 x i8] c"main\00", align 1 +@.str.1 = private unnamed_addr constant [12 x i8] c"constructor\00", align 1 +@.str.2 = private unnamed_addr constant [11 x i8] c"destructor\00", align 1 +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @constructor, i8* null }] + +define dso_local void @destructor(i8* %0) { + %2 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i64 0, i64 0)) + ret void +} + +declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) + +; Function Attrs: nofree norecurse nounwind uwtable +define dso_local i32 @main(i32 %0, i8** nocapture readnone %1) local_unnamed_addr #2 { + %3 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0)) + ret i32 0 +} + +declare i32 @puts(i8* nocapture readonly) + +define internal void @constructor() { + %1 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str.1, i64 0, i64 0)) #5 + %2 = tail call i32 @__cxa_atexit(void (i8*)* @destructor, i8* null, i8* nonnull @__dso_handle) #5 + ret void +} diff --git a/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/lljit-ehframe.cpp b/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/lljit-ehframe.cpp new file mode 100644 index 0000000000000..b73ec2387028e --- /dev/null +++ b/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/lljit-ehframe.cpp @@ -0,0 +1,15 @@ +// RUN: %clangxx -fPIC -emit-llvm -c -o %t %s +// RUN: %lli_orc_jitlink -relocation-model=pic %t | FileCheck %s + +// CHECK: catch + +#include + +int main(int argc, char *argv[]) { + try { + throw 0; + } catch (int X) { + puts("catch"); + } + return 0; +} diff --git a/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/lljit-initialize-deinitialize.ll b/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/lljit-initialize-deinitialize.ll new file mode 100644 index 0000000000000..34bfc10b9d897 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/lljit-initialize-deinitialize.ll @@ -0,0 +1,32 @@ +; RUN: %lli_orc_jitlink %s | FileCheck %s + +; CHECK: constructor +; CHECK-NEXT: main +; CHECK-NEXT: destructor + +@__dso_handle = external hidden global i8 +@.str = private unnamed_addr constant [5 x i8] c"main\00", align 1 +@.str.1 = private unnamed_addr constant [12 x i8] c"constructor\00", align 1 +@.str.2 = private unnamed_addr constant [11 x i8] c"destructor\00", align 1 +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @constructor, i8* null }] + +define dso_local void @destructor(i8* %0) { + %2 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i64 0, i64 0)) + ret void +} + +declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) + +; Function Attrs: nofree norecurse nounwind uwtable +define dso_local i32 @main(i32 %0, i8** nocapture readnone %1) local_unnamed_addr #2 { + %3 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0)) + ret i32 0 +} + +declare i32 @puts(i8* nocapture readonly) + +define internal void @constructor() { + %1 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str.1, i64 0, i64 0)) #5 + %2 = tail call i32 @__cxa_atexit(void (i8*)* @destructor, i8* null, i8* nonnull @__dso_handle) #5 + ret void +} diff --git a/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/priority-static-initializer.S b/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/priority-static-initializer.S new file mode 100644 index 0000000000000..13a52f32cef2a --- /dev/null +++ b/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/priority-static-initializer.S @@ -0,0 +1,99 @@ +// Test that ELF static initializers with different constructor priorities work +// and are executed in the proper order. +// +// RUN: %clang -c -o %t %s +// RUN: %llvm_jitlink %t | FileCheck %s + +// CHECK: constructor 100 +// CHECK-NEXT: constructor 200 +// CHECK-NEXT: constructor 65535 +// CHECK-NEXT: main +// CHECK-NEXT: destructor + + .text + + .globl destructor + .p2align 4, 0x90 + .type destructor,@function +destructor: +.Ldestructor$local: + + leaq .L.str.d(%rip), %rdi + jmp puts@PLT + + .globl main + .p2align 4, 0x90 + .type main,@function +main: +.Lmain$local: + + pushq %rax + leaq .L.str(%rip), %rdi + callq puts@PLT + xorl %eax, %eax + popq %rcx + retq + + .p2align 4, 0x90 + .type constructor.65535,@function +constructor.65535: + + pushq %rax + leaq .L.str.65535(%rip), %rdi + callq puts@PLT + leaq .Ldestructor$local(%rip), %rdi + leaq __dso_handle(%rip), %rdx + xorl %esi, %esi + popq %rax + jmp __cxa_atexit@PLT + + .p2align 4, 0x90 + .type constructor.200,@function +constructor.200: + + leaq .L.str.200(%rip), %rdi + jmp puts@PLT + + .p2align 4, 0x90 + .type constructor.100,@function +constructor.100: + + leaq .L.str.100(%rip), %rdi + jmp puts@PLT + + .hidden __dso_handle + .type .L.str,@object + .section .rodata.str1.1,"aMS",@progbits,1 +.L.str: + .asciz "main" + .size .L.str, 5 + + .type .L.str.100,@object +.L.str.100: + .asciz "constructor 100" + .size .L.str.100, 16 + + .type .L.str.200,@object +.L.str.200: + .asciz "constructor 200" + .size .L.str.200, 16 + + .type .L.str.65535,@object +.L.str.65535: + .asciz "constructor 65535" + .size .L.str.65535, 18 + + .type .L.str.d,@object +.L.str.d: + .asciz "destructor" + .size .L.str.d, 11 + + .section .init_array.100,"aw",@init_array + .p2align 3 + .quad constructor.100 + .section .init_array.200,"aw",@init_array + .p2align 3 + .quad constructor.200 + .section .init_array,"aw",@init_array + .p2align 3 + .quad constructor.65535 diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/ehframe-default.cpp b/compiler-rt/test/orc/TestCases/Linux/aarch64/ehframe-default.cpp new file mode 100644 index 0000000000000..0f7dcec4b5a5b --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/ehframe-default.cpp @@ -0,0 +1,14 @@ +// RUN: %clangxx -fexceptions -fPIC -c -o %t %s +// RUN: %llvm_jitlink %t + +extern "C" void llvm_jitlink_setTestResultOverride(long Value); + +int main(int argc, char *argv[]) { + llvm_jitlink_setTestResultOverride(1); + try { + throw 0; + } catch (int X) { + llvm_jitlink_setTestResultOverride(X); + } + return 0; +} diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/ehframe-libunwind.cpp b/compiler-rt/test/orc/TestCases/Linux/aarch64/ehframe-libunwind.cpp new file mode 100644 index 0000000000000..f56aa8fba950f --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/ehframe-libunwind.cpp @@ -0,0 +1,15 @@ +// REQUIRES: libunwind-available +// RUN: %clangxx -fexceptions -fPIC -c -o %t %s +// RUN: env LD_PRELOAD=%shared_libunwind %llvm_jitlink %t + +extern "C" void llvm_jitlink_setTestResultOverride(long Value); + +int main(int argc, char *argv[]) { + llvm_jitlink_setTestResultOverride(1); + try { + throw 0; + } catch (int X) { + llvm_jitlink_setTestResultOverride(X); + } + return 0; +} diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/lit.local.cfg.py b/compiler-rt/test/orc/TestCases/Linux/aarch64/lit.local.cfg.py new file mode 100644 index 0000000000000..ad928a9a56a29 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/lit.local.cfg.py @@ -0,0 +1,5 @@ +if config.root.host_arch != 'aarch64': + config.unsupported = True + +if config.target_arch != 'aarch64': + config.unsupported = True diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/lljit-ehframe.cpp b/compiler-rt/test/orc/TestCases/Linux/aarch64/lljit-ehframe.cpp new file mode 100644 index 0000000000000..b73ec2387028e --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/lljit-ehframe.cpp @@ -0,0 +1,15 @@ +// RUN: %clangxx -fPIC -emit-llvm -c -o %t %s +// RUN: %lli_orc_jitlink -relocation-model=pic %t | FileCheck %s + +// CHECK: catch + +#include + +int main(int argc, char *argv[]) { + try { + throw 0; + } catch (int X) { + puts("catch"); + } + return 0; +} diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/lljit-initialize-deinitialize.ll b/compiler-rt/test/orc/TestCases/Linux/aarch64/lljit-initialize-deinitialize.ll new file mode 100644 index 0000000000000..34bfc10b9d897 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/lljit-initialize-deinitialize.ll @@ -0,0 +1,32 @@ +; RUN: %lli_orc_jitlink %s | FileCheck %s + +; CHECK: constructor +; CHECK-NEXT: main +; CHECK-NEXT: destructor + +@__dso_handle = external hidden global i8 +@.str = private unnamed_addr constant [5 x i8] c"main\00", align 1 +@.str.1 = private unnamed_addr constant [12 x i8] c"constructor\00", align 1 +@.str.2 = private unnamed_addr constant [11 x i8] c"destructor\00", align 1 +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @constructor, i8* null }] + +define dso_local void @destructor(i8* %0) { + %2 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i64 0, i64 0)) + ret void +} + +declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) + +; Function Attrs: nofree norecurse nounwind uwtable +define dso_local i32 @main(i32 %0, i8** nocapture readnone %1) local_unnamed_addr #2 { + %3 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0)) + ret i32 0 +} + +declare i32 @puts(i8* nocapture readonly) + +define internal void @constructor() { + %1 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str.1, i64 0, i64 0)) #5 + %2 = tail call i32 @__cxa_atexit(void (i8*)* @destructor, i8* null, i8* nonnull @__dso_handle) #5 + ret void +} diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/priority-static-initializer.S b/compiler-rt/test/orc/TestCases/Linux/aarch64/priority-static-initializer.S new file mode 100644 index 0000000000000..858e7e9c75f5a --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/priority-static-initializer.S @@ -0,0 +1,111 @@ +// Test that ELF static initializers with different constructor priorities work +// and are executed in the proper order. +// +// RUN: %clang -c -o %t %s +// RUN: %llvm_jitlink %t | FileCheck %s + +// CHECK: constructor 100 +// CHECK-NEXT: constructor 200 +// CHECK-NEXT: constructor 65535 +// CHECK-NEXT: main +// CHECK-NEXT: destructor + + .text + .globl destructor + .p2align 2 + .type destructor,@function +destructor: +.Ldestructor$local: + + adrp x0, .L.str.2 + add x0, x0, :lo12:.L.str.2 + b puts + + .globl main + .p2align 2 + .type main,@function +main: + + str x30, [sp, #-16]! + adrp x0, .L.str + add x0, x0, :lo12:.L.str + bl puts + mov w0, wzr + ldr x30, [sp], #16 + ret + + .p2align 2 + .type constructor.65535,@function +constructor.65535: + + str x30, [sp, #-16]! + adrp x0, .L.str.65535 + add x0, x0, :lo12:.L.str.65535 + bl puts + adrp x0, .Ldestructor$local + add x0, x0, :lo12:.Ldestructor$local + adrp x2, __dso_handle + add x2, x2, :lo12:__dso_handle + mov x1, xzr + ldr x30, [sp], #16 + b __cxa_atexit + + .p2align 2 + .type constructor.100,@function +constructor.100: + + str x30, [sp, #-16]! + adrp x0, .L.str.100 + add x0, x0, :lo12:.L.str.100 + bl puts + ldr x30, [sp], #16 + ret + + .p2align 2 + .type constructor.200,@function +constructor.200: + + str x30, [sp, #-16]! + adrp x0, .L.str.200 + add x0, x0, :lo12:.L.str.200 + bl puts + ldr x30, [sp], #16 + ret + + .hidden __dso_handle + .type .L.str,@object + .section .rodata.str1.1,"aMS",@progbits,1 +.L.str: + .asciz "main" + .size .L.str, 5 + + .type .L.str.100,@object +.L.str.100: + .asciz "constructor 100" + .size .L.str.100, 16 + + .type .L.str.200,@object +.L.str.200: + .asciz "constructor 200" + .size .L.str.200, 16 + + .type .L.str.65535,@object +.L.str.65535: + .asciz "constructor 65535" + .size .L.str.65535, 18 + + + .type .L.str.2,@object +.L.str.2: + .asciz "destructor" + .size .L.str.2, 11 + + .section .init_array.100,"aw",@init_array + .p2align 3 + .xword constructor.100 + .section .init_array.200,"aw",@init_array + .p2align 3 + .xword constructor.200 + .section .init_array,"aw",@init_array + .p2align 3 + .xword constructor.65535 diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-atexit.S b/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-atexit.S new file mode 100644 index 0000000000000..338b052dd3a37 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-atexit.S @@ -0,0 +1,33 @@ +// Test that the runtime correctly interposes atexit. +// +// RUN: %clang -c -o %t %s +// RUN: %llvm_jitlink %t + + .text +// OnExit destructor resets the test result override to zero. + .globl on_exit + .p2align 2 + .type on_exit,@function +on_exit: + + mov w0, wzr + b llvm_jitlink_setTestResultOverride +.Lfunc_end0: + .size on_exit, .Lfunc_end0-on_exit + +// main registers the atexit and sets the test result to one. + .globl main + .p2align 2 + .type main,@function +main: + + stp x29, x30, [sp, #-16]! + mov x29, sp + adrp x0, :got:on_exit + ldr x0, [x0, :got_lo12:on_exit] + bl atexit + mov w0, wzr + ldp x29, x30, [sp], #16 + ret +.Lfunc_end1: + .size main, .Lfunc_end1-main diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-cxa-atexit.S b/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-cxa-atexit.S new file mode 100644 index 0000000000000..59b9fed3bc280 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-cxa-atexit.S @@ -0,0 +1,39 @@ +// Test that the runtime correctly interposes ___cxa_atexit. +// +// RUN: %clang -c -o %t %s +// RUN: %llvm_jitlink %t + + .text +// Destructor resets the test result override to zero. + .globl on_exit + .p2align 2 + .type on_exit,@function +on_exit: + + mov w0, wzr + b llvm_jitlink_setTestResultOverride +.Lfunc_end0: + .size on_exit, .Lfunc_end0-on_exit + +// main registers the atexit and sets the test result to one. + .globl main + .p2align 2 + .type main,@function +main: + + stp x29, x30, [sp, #-16]! + mov x29, sp + adrp x8, :got:__dso_handle + adrp x0, :got:on_exit + mov x1, xzr + ldr x8, [x8, :got_lo12:__dso_handle] + ldr x2, [x8] + ldr x0, [x0, :got_lo12:on_exit] + bl __cxa_atexit + mov w0, #1 + bl llvm_jitlink_setTestResultOverride + mov w0, wzr + ldp x29, x30, [sp], #16 + ret +.Lfunc_end1: + .size main, .Lfunc_end1-main diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-static-initializer.S b/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-static-initializer.S new file mode 100644 index 0000000000000..9daf80827918b --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-static-initializer.S @@ -0,0 +1,47 @@ +// Test that basic ELF static initializers work. The main function in this +// test returns the value of 'x', which is initially 1 in the data section, +// and reset to 0 if the _static_init function is run. If the static initializer +// does not run then main will return 1, causing the test to be treated as a +// failure. +// +// RUN: %clang -c -o %t %s +// RUN: %llvm_jitlink %t + + .text + .globl main + .p2align 2 + .type main,@function +main: + + adrp x8, :got:x + ldr x8, [x8, :got_lo12:x] + ldr w0, [x8] + ret +.Lfunc_end0: + .size main, .Lfunc_end0-main + +// static initializer sets the value of 'x' to zero. + + .section .text.startup,"ax",@progbits + .p2align 2 + .type static_init,@function +static_init: + + adrp x8, :got:x + ldr x8, [x8, :got_lo12:x] + str wzr, [x8] + ret +.Lfunc_end1: + .size static_init, .Lfunc_end1-static_init + + .type x,@object + .data + .globl x + .p2align 2 +x: + .word 1 + .size x, 4 + + .section .init_array,"aw",@init_array + .p2align 3 + .xword static_init diff --git a/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-ehframe.cpp b/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-ehframe.cpp new file mode 100644 index 0000000000000..b73ec2387028e --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-ehframe.cpp @@ -0,0 +1,15 @@ +// RUN: %clangxx -fPIC -emit-llvm -c -o %t %s +// RUN: %lli_orc_jitlink -relocation-model=pic %t | FileCheck %s + +// CHECK: catch + +#include + +int main(int argc, char *argv[]) { + try { + throw 0; + } catch (int X) { + puts("catch"); + } + return 0; +} diff --git a/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-initialize-deinitialize.ll b/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-initialize-deinitialize.ll new file mode 100644 index 0000000000000..34bfc10b9d897 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-initialize-deinitialize.ll @@ -0,0 +1,32 @@ +; RUN: %lli_orc_jitlink %s | FileCheck %s + +; CHECK: constructor +; CHECK-NEXT: main +; CHECK-NEXT: destructor + +@__dso_handle = external hidden global i8 +@.str = private unnamed_addr constant [5 x i8] c"main\00", align 1 +@.str.1 = private unnamed_addr constant [12 x i8] c"constructor\00", align 1 +@.str.2 = private unnamed_addr constant [11 x i8] c"destructor\00", align 1 +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @constructor, i8* null }] + +define dso_local void @destructor(i8* %0) { + %2 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i64 0, i64 0)) + ret void +} + +declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) + +; Function Attrs: nofree norecurse nounwind uwtable +define dso_local i32 @main(i32 %0, i8** nocapture readnone %1) local_unnamed_addr #2 { + %3 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0)) + ret i32 0 +} + +declare i32 @puts(i8* nocapture readonly) + +define internal void @constructor() { + %1 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str.1, i64 0, i64 0)) #5 + %2 = tail call i32 @__cxa_atexit(void (i8*)* @destructor, i8* null, i8* nonnull @__dso_handle) #5 + ret void +} diff --git a/compiler-rt/test/orc/TestCases/Linux/x86-64/priority-static-initializer.S b/compiler-rt/test/orc/TestCases/Linux/x86-64/priority-static-initializer.S new file mode 100644 index 0000000000000..13a52f32cef2a --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/x86-64/priority-static-initializer.S @@ -0,0 +1,99 @@ +// Test that ELF static initializers with different constructor priorities work +// and are executed in the proper order. +// +// RUN: %clang -c -o %t %s +// RUN: %llvm_jitlink %t | FileCheck %s + +// CHECK: constructor 100 +// CHECK-NEXT: constructor 200 +// CHECK-NEXT: constructor 65535 +// CHECK-NEXT: main +// CHECK-NEXT: destructor + + .text + + .globl destructor + .p2align 4, 0x90 + .type destructor,@function +destructor: +.Ldestructor$local: + + leaq .L.str.d(%rip), %rdi + jmp puts@PLT + + .globl main + .p2align 4, 0x90 + .type main,@function +main: +.Lmain$local: + + pushq %rax + leaq .L.str(%rip), %rdi + callq puts@PLT + xorl %eax, %eax + popq %rcx + retq + + .p2align 4, 0x90 + .type constructor.65535,@function +constructor.65535: + + pushq %rax + leaq .L.str.65535(%rip), %rdi + callq puts@PLT + leaq .Ldestructor$local(%rip), %rdi + leaq __dso_handle(%rip), %rdx + xorl %esi, %esi + popq %rax + jmp __cxa_atexit@PLT + + .p2align 4, 0x90 + .type constructor.200,@function +constructor.200: + + leaq .L.str.200(%rip), %rdi + jmp puts@PLT + + .p2align 4, 0x90 + .type constructor.100,@function +constructor.100: + + leaq .L.str.100(%rip), %rdi + jmp puts@PLT + + .hidden __dso_handle + .type .L.str,@object + .section .rodata.str1.1,"aMS",@progbits,1 +.L.str: + .asciz "main" + .size .L.str, 5 + + .type .L.str.100,@object +.L.str.100: + .asciz "constructor 100" + .size .L.str.100, 16 + + .type .L.str.200,@object +.L.str.200: + .asciz "constructor 200" + .size .L.str.200, 16 + + .type .L.str.65535,@object +.L.str.65535: + .asciz "constructor 65535" + .size .L.str.65535, 18 + + .type .L.str.d,@object +.L.str.d: + .asciz "destructor" + .size .L.str.d, 11 + + .section .init_array.100,"aw",@init_array + .p2align 3 + .quad constructor.100 + .section .init_array.200,"aw",@init_array + .p2align 3 + .quad constructor.200 + .section .init_array,"aw",@init_array + .p2align 3 + .quad constructor.65535 diff --git a/compiler-rt/test/orc/lit.cfg.py b/compiler-rt/test/orc/lit.cfg.py index b2e97cefbf0e8..78c653373be27 100644 --- a/compiler-rt/test/orc/lit.cfg.py +++ b/compiler-rt/test/orc/lit.cfg.py @@ -13,6 +13,7 @@ def build_invocation(compile_flags): # Assume that llvm-jitlink is in the config.llvm_tools_dir. llvm_jitlink = os.path.join(config.llvm_tools_dir, 'llvm-jitlink') +lli = os.path.join(config.llvm_tools_dir, 'lli') if config.host_os == 'Darwin': orc_rt_path = '%s/libclang_rt.orc_osx.a' % config.compiler_rt_libdir else: @@ -30,9 +31,11 @@ def build_invocation(compile_flags): build_invocation(config.cxx_mode_flags + [config.target_cflags]))) config.substitutions.append( ('%llvm_jitlink', (llvm_jitlink + ' -orc-runtime=' + orc_rt_path))) +config.substitutions.append( + ('%lli_orc_jitlink', (lli + ' -jit-kind=orc -jit-linker=jitlink -orc-runtime=' + orc_rt_path))) # Default test suffixes. -config.suffixes = ['.c', '.cpp', '.S'] +config.suffixes = ['.c', '.cpp', '.S', '.ll'] # Exclude Inputs directories. config.excludes = ['Inputs'] diff --git a/compiler-rt/test/sanitizer_common/TestCases/FreeBSD/procctl.cpp b/compiler-rt/test/sanitizer_common/TestCases/FreeBSD/procctl.cpp new file mode 100644 index 0000000000000..a5c6a5e670990 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/FreeBSD/procctl.cpp @@ -0,0 +1,28 @@ +// RUN: %clangxx %s -o %t && %run %t %p + +#include +#include +#include +#include + +int main() { + struct procctl_reaper_status status = {0}; + int res, aslr; + res = procctl(P_PID, getpid(), PROC_REAP_STATUS, &status); + if (res < 0) { + assert(errno == EPERM); + return 0; + } + + assert(status.rs_flags >= REAPER_STATUS_OWNED); + + res = procctl(P_PID, getpid(), PROC_ASLR_STATUS, &aslr); + if (res < 0) { + assert(errno == EPERM); + return 0; + } + + assert(aslr >= PROC_ASLR_FORCE_ENABLE); + + return 0; +} diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/b64.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/b64.cpp index 99f27421642cb..96fd0138648b3 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/b64.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/b64.cpp @@ -1,7 +1,4 @@ -// RUN: %clangxx %s -o %t -lresolv && %run %t %p - -// -lresolv fails on Android. -// UNSUPPORTED: android +// RUN: %clangxx %s -o %t && %run %t %p #include #include diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/dn_expand.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/dn_expand.cpp new file mode 100644 index 0000000000000..9a56f08c9763d --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/dn_expand.cpp @@ -0,0 +1,42 @@ +// RUN: %clangxx %s -o %t && %run %t %p + +#include +#include +#include + +#include + +void testWrite() { + char unsigned input[] = {0xff, 0xc5, 0xf7, 0xff, 0x00, 0x00, 0xff, 0x0a, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x10, 0x01, 0x05, 0x00, 0x01, 0x0a, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00}; + char output[1024]; + + int res = dn_expand(input, input + sizeof(input), input + 23, output, + sizeof(output)); + + assert(res == 12); + assert(strcmp(output, "google\\.com") == 0); +} + +void testWriteZeroLength() { + char unsigned input[] = { + 0xff, 0xc5, 0xf7, 0xff, 0x00, 0x00, 0xff, 0x0a, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x10, 0x01, 0x05, 0x00, 0x01, 0x00, + }; + char output[1024]; + + int res = dn_expand(input, input + sizeof(input), input + 23, output, + sizeof(output)); + + assert(res == 1); + assert(strcmp(output, "") == 0); +} + +int main(int iArgc, const char *szArgv[]) { + testWrite(); + testWriteZeroLength(); + + return 0; +} diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/prctl.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/prctl.cpp index a250dd5f8fa8d..581739500e7a9 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/prctl.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/prctl.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #ifndef PR_SCHED_CORE @@ -17,6 +18,11 @@ # define PR_SCHED_CORE_GET 0 #endif +#ifndef PR_SET_VMA +# define PR_SET_VMA 0x53564d41 +# define PR_SET_VMA_ANON_NAME 0 +#endif + int main() { int res; @@ -34,5 +40,25 @@ int main() { assert(cookie != 0); } + char invname[81], vlname[] = "prctl"; + for (auto i = 0; i < sizeof(invname); i++) { + invname[i] = 0x1e; + } + invname[80] = 0; + auto p = + mmap(nullptr, 128, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + assert(p != MAP_FAILED); + // regardless of kernel support, the name is invalid + res = prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (uintptr_t)p, 128, + (uintptr_t)invname); + assert(res == -1); + assert(errno == EINVAL); + res = prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (uintptr_t)p, 128, + (uintptr_t)vlname); + if (res < 0) { + assert(errno == EINVAL); + } + munmap(p, 128); + return 0; } diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/pthread_getaffinity_np.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/pthread_getaffinity_np.cpp new file mode 100644 index 0000000000000..e878a8914cf73 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/pthread_getaffinity_np.cpp @@ -0,0 +1,22 @@ +// RUN: %clangxx -O0 %s -o %t && %run %t + +// Android does not implement pthread_getaffinity_np. +// (Note: libresolv is integrated with libc, but apparently only +// sched_getaffinity). +// UNSUPPORTED: android + +#include +#include +#include + +#include + +int main() { + cpu_set_t set_x[4]; + pthread_t tid = pthread_self(); + int res = pthread_getaffinity_np(tid, sizeof(set_x), set_x); + assert(res == 0); + assert(CPU_COUNT_S(sizeof(set_x), set_x) == get_nprocs()); + + return 0; +} diff --git a/compiler-rt/test/sanitizer_common/TestCases/symbolize_stack.cpp b/compiler-rt/test/sanitizer_common/TestCases/symbolize_stack.cpp index 37b7e98339eb6..d6ec49b407f5d 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/symbolize_stack.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/symbolize_stack.cpp @@ -5,11 +5,6 @@ // On Darwin LSan reports a false positive // XFAIL: darwin && lsan -// FIXME: https://github.com/llvm/llvm-project/issues/55460 -// On Linux its possible for symbolizer output to be truncated and to match the -// check below. Remove when the underlying problem has been addressed. -// UNSUPPORTED: linux - #include #include diff --git a/cross-project-tests/debuginfo-tests/dexter/Commands.md b/cross-project-tests/debuginfo-tests/dexter/Commands.md index e151103017517..d5bd999f5adf0 100644 --- a/cross-project-tests/debuginfo-tests/dexter/Commands.md +++ b/cross-project-tests/debuginfo-tests/dexter/Commands.md @@ -144,7 +144,7 @@ type checked against the list of `types` --- ## DexExpectWatchValue DexExpectWatchValue(expr, *values [,**from_line=1][,**to_line=Max] - [,**on_line][,**require_in_order=True]) + [,**on_line][,**require_in_order=True][,**float_range]) Args: expr (str): expression to evaluate. @@ -159,6 +159,9 @@ type checked against the list of `types` on_line (int): Only evaluate the expression on this line. If provided, this overrides from_line and to_line. require_in_order (bool): If False the values can appear in any order. + float_range (float): If provided, `values` must be floats, and will + match an actual value if they are within `float_range` of each other. + ### Description Expect the expression `expr` to evaluate to the list of `values` diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py index cd93b2b289e6f..1027ba0d9beb4 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py @@ -15,7 +15,7 @@ from pathlib import PurePath from collections import defaultdict, OrderedDict -from dex.utils.Exceptions import CommandParseError +from dex.utils.Exceptions import CommandParseError, NonFloatValueInCommand from dex.command.CommandBase import CommandBase from dex.command.commands.DexCommandLine import DexCommandLine @@ -310,6 +310,10 @@ def _find_all_commands_in_file(path, file_lines, valid_commands, source_root_dir err_point = copy(cmd_point) err_point.char += len(command_name) raise format_parse_err(str(e), path, file_lines, err_point) + except NonFloatValueInCommand as e: + err_point = copy(cmd_point) + err_point.char += len(command_name) + raise format_parse_err(str(e), path, file_lines, err_point) else: if type(command) is DexLabel: add_line_label(labels, command, path, cmd_point.get_lineno()) diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexDeclareAddress.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexDeclareAddress.py index cf547601754fe..29d2dc7610742 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexDeclareAddress.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexDeclareAddress.py @@ -8,6 +8,7 @@ """ import os +from pathlib import PurePath from dex.command.CommandBase import CommandBase, StepExpectInfo @@ -37,13 +38,12 @@ def get_address_name(self): return self.addr_name def eval(self, step_collection): - assert os.path.exists(self.path) self.address_resolutions[self.get_address_name()] = None for step in step_collection.steps: loc = step.current_location - if (loc.path and os.path.exists(loc.path) and - os.path.samefile(loc.path, self.path) and + if (loc.path and self.path and + PurePath(loc.path) == PurePath(self.path) and loc.lineno == self.on_line): if self.hit_count > 0: self.hit_count -= 1 @@ -51,8 +51,10 @@ def eval(self, step_collection): try: watch = step.program_state.frames[0].watches[self.expression] except KeyError: - pass - else: + continue + try: hex_val = int(watch.value, 16) - self.address_resolutions[self.get_address_name()] = hex_val - break + except ValueError: + hex_val = None + self.address_resolutions[self.get_address_name()] = hex_val + break diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectWatchBase.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectWatchBase.py index 44c8bdbe0f25d..e79b1bb711e67 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectWatchBase.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectWatchBase.py @@ -14,9 +14,11 @@ import os import math from collections import namedtuple +from pathlib import PurePath from dex.command.CommandBase import CommandBase, StepExpectInfo from dex.command.StepValueInfo import StepValueInfo +from dex.utils.Exceptions import NonFloatValueInCommand class AddressExpression(object): def __init__(self, name, offset=0): @@ -55,6 +57,13 @@ def __init__(self, *args, **kwargs): self._from_line = kwargs.pop('from_line', 1) self._to_line = kwargs.pop('to_line', 999999) self._require_in_order = kwargs.pop('require_in_order', True) + self.float_range = kwargs.pop('float_range', None) + if self.float_range is not None: + for value in self.values: + try: + float(value) + except ValueError: + raise NonFloatValueInCommand(f'Non-float value \'{value}\' when float_range arg provided') if kwargs: raise TypeError('unexpected named args: {}'.format( ', '.join(kwargs))) @@ -134,6 +143,33 @@ def _get_expected_field(self, watch): """Return a field from watch that this ExpectWatch command is checking. """ + def _match_expected_floating_point(self, value): + """Checks to see whether value is a float that falls within the + acceptance range of one of this command's expected float values, and + returns the expected value if so; otherwise returns the original + value.""" + try: + value_as_float = float(value) + except ValueError: + return value + + possible_values = self.values + for expected in possible_values: + try: + expected_as_float = float(expected) + difference = abs(value_as_float - expected_as_float) + if difference <= self.float_range: + return expected + except ValueError: + pass + return value + + def _maybe_fix_float(self, value): + if self.float_range is not None: + return self._match_expected_floating_point(value) + else: + return value + def _handle_watch(self, step_info): self.times_encountered += 1 @@ -149,23 +185,25 @@ def _handle_watch(self, step_info): self.irretrievable_watches.append(step_info) return + expected_value = self._maybe_fix_float(step_info.expected_value) + # Check to see if this value matches with a resolved address. matching_address = None for v in self.values: if (isinstance(v, AddressExpression) and v.name in self.address_resolutions and - self.resolve_value(v) == step_info.expected_value): + self.resolve_value(v) == expected_value): matching_address = v break # If this is not an expected value, either a direct value or an address, # then this is an unexpected watch. - if step_info.expected_value not in self.values and matching_address is None: + if expected_value not in self.values and matching_address is None: self.unexpected_watches.append(step_info) return self.expected_watches.append(step_info) - value_to_remove = matching_address if matching_address is not None else step_info.expected_value + value_to_remove = matching_address if matching_address is not None else expected_value try: self._missing_values.remove(value_to_remove) except KeyError: @@ -176,7 +214,7 @@ def _check_watch_order(self, actual_watches, expected_values): or not. """ differences = [] - actual_values = [w.expected_value for w in actual_watches] + actual_values = [self._maybe_fix_float(w.expected_value) for w in actual_watches] value_differences = list(difflib.Differ().compare(actual_values, expected_values)) @@ -208,12 +246,11 @@ def _check_watch_order(self, actual_watches, expected_values): return differences def eval(self, step_collection): - assert os.path.exists(self.path) for step in step_collection.steps: loc = step.current_location - if (loc.path and os.path.exists(loc.path) and - os.path.samefile(loc.path, self.path) and + if (loc.path and self.path and + PurePath(loc.path) == PurePath(self.path) and loc.lineno in self.line_range): try: watch = step.program_state.frames[0].watches[self.expression] @@ -229,14 +266,16 @@ def eval(self, step_collection): # A list of all watches where the value has changed. value_change_watches = [] prev_value = None + all_expected_values = [] for watch in self.expected_watches: - if watch.expected_value != prev_value: + expected_value = self._maybe_fix_float(watch.expected_value) + all_expected_values.append(expected_value) + if expected_value != prev_value: value_change_watches.append(watch) - prev_value = watch.expected_value + prev_value = expected_value resolved_values = [self.resolve_value(v) for v in self.values] self.misordered_watches = self._check_watch_order( value_change_watches, [ - v for v in resolved_values if v in - [w.expected_value for w in self.expected_watches] + v for v in resolved_values if v in all_expected_values ]) diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/dextIR/ProgramState.py b/cross-project-tests/debuginfo-tests/dexter/dex/dextIR/ProgramState.py index 4f05189aed8bf..a1de5fbcf363d 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/dextIR/ProgramState.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/dextIR/ProgramState.py @@ -11,6 +11,7 @@ import os from collections import OrderedDict +from pathlib import PurePath from typing import List class SourceLocation: @@ -31,7 +32,7 @@ def match(self, other) -> bool: if not other or not isinstance(other, SourceLocation): return False - if self.path and (self.path != other.path): + if self.path and (other.path is None or (PurePath(self.path) != PurePath(other.path))): return False if self.lineno and (self.lineno != other.lineno): diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/utils/Exceptions.py b/cross-project-tests/debuginfo-tests/dexter/dex/utils/Exceptions.py index 39c0c2f169521..b636acbc0cee5 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/utils/Exceptions.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/utils/Exceptions.py @@ -54,6 +54,14 @@ def __init__(self, *args, **kwargs): self.caret = None +class NonFloatValueInCommand(CommandParseError): + """If a command has the float_range arg but at least one of its expected + values cannot be converted to a float.""" + + def __init__(self, *args, **kwargs): + super(NonFloatValueInCommand, self).__init__(*args, **kwargs) + self.value = None + class ToolArgumentError(Dexception): """If a tool argument is invalid.""" pass diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/penalty/float_range_out_range.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/penalty/float_range_out_range.cpp new file mode 100644 index 0000000000000..519a99a05d0dc --- /dev/null +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/penalty/float_range_out_range.cpp @@ -0,0 +1,16 @@ +// Purpose: +// Check that a \DexExpectWatchValue float_range that is not large enough +// detects unexpected watch values. +// +// UNSUPPORTED: system-darwin +// +// RUN: not %dexter_regression_test -- %s | FileCheck %s +// CHECK: float_range_out_range.cpp: + +int main() { + float a = 1.0f; + a = a - 0.5f; + return a; //DexLabel('check') +} + +// DexExpectWatchValue('a', '1.00000', from_line=ref('check1'), to_line=ref('check2'), float_range=0.4) diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/penalty/float_range_zero_nonmatch.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/penalty/float_range_zero_nonmatch.cpp new file mode 100644 index 0000000000000..e7e04c9f98e63 --- /dev/null +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/penalty/float_range_zero_nonmatch.cpp @@ -0,0 +1,15 @@ +// Purpose: +// Check that \DexExpectWatchValue float_range=0.0 matches only exact +// values. +// +// UNSUPPORTED: system-darwin +// +// RUN: not %dexter_regression_test -- %s | FileCheck %s +// CHECK: float_range_zero_nonmatch.cpp: + +int main() { + float a = 1.0f; + return a; //DexLabel('check') +} + +// DexExpectWatchValue('a', '1.0000001', on_line=ref('check'), float_range=0.0) diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_multiple.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_multiple.cpp new file mode 100644 index 0000000000000..0d7e1f69a3c1e --- /dev/null +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_multiple.cpp @@ -0,0 +1,18 @@ +// Purpose: +// Check that \DexExpectWatchValue float_range=0.5 considers a range +// difference of 0.49999 to be an expected watch value for multple values. +// +// UNSUPPORTED: system-darwin +// +// RUN: %dexter_regression_test -- %s | FileCheck %s +// CHECK: float_range_multiple.cpp: + +int main() { + float a = 1.0f; + float b = 100.f; + a = a + 0.4999f; + a = a + b; // DexLabel('check1') + return a; //DexLabel('check2') +} + +// DexExpectWatchValue('a', '1.0', '101.0', from_line=ref('check1'), to_line=ref('check2'), float_range=0.5) diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_no_arg.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_no_arg.cpp new file mode 100644 index 0000000000000..c23fe09244d5f --- /dev/null +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_no_arg.cpp @@ -0,0 +1,18 @@ +// Purpose: +// Check that omitted float_range from \DexExpectWatchValue turns off +// the floating point range evalution and defaults back to +// pre-float evalution. +// +// Since this test involves string comparison to the debugger output, it cannot +// work for both dbgeng and lldb, which output floats differently. +// UNSUPPORTED: system-darwin, system-windows +// +// RUN: %dexter_regression_test -- %s | FileCheck %s +// CHECK: float_range_no_arg.cpp: + +int main() { + float a = 1.0f; + return a; //DexLabel('check') +} + +// DexExpectWatchValue('a', '1', on_line=ref('check')) diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_small.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_small.cpp new file mode 100644 index 0000000000000..6a844e7da2cd1 --- /dev/null +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_small.cpp @@ -0,0 +1,16 @@ +// Purpose: +// Check that \DexExpectWatchValue float_range=0.5 considers a range +// difference of 0.49999 to be an expected watch value. +// +// UNSUPPORTED: system-darwin +// +// RUN: %dexter_regression_test -- %s | FileCheck %s +// CHECK: float_range_small.cpp: + +int main() { + float a = 1.0f; + a = a - 0.49999f; + return a; //DexLabel('check') +} + +// DexExpectWatchValue('a', '1.0', on_line=ref('check'), float_range=0.5) diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_zero_match.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_zero_match.cpp new file mode 100644 index 0000000000000..7dbd515e717bb --- /dev/null +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_zero_match.cpp @@ -0,0 +1,14 @@ +// Purpose: +// Check that \DexExpectWatchValue float_range=0.0 matches exact values. +// +// UNSUPPORTED: system-darwin +// +// RUN: %dexter_regression_test -- %s | FileCheck %s +// CHECK: float_range_zero_match.cpp: + +int main() { + float a = 1.0f; + return a; //DexLabel('check') +} + +// DexExpectWatchValue('a', '1.0000000', on_line=ref('check'), float_range=0.0) diff --git a/flang/README.md b/flang/README.md index 604049a5ebee9..d593ac4371d34 100644 --- a/flang/README.md +++ b/flang/README.md @@ -150,9 +150,6 @@ AArch64, x86\_64 and ppc64le servers with CentOS7, Ubuntu18.04, Rhel, MacOs, Mojave, XCode and Apple Clang version 10.0.1. -The code does not compile with Windows and a compiler that does not have -support for C++17. - ### Building flang with GCC By default, diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md index 484aee5cfcc20..6becaf3c96e94 100644 --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -233,6 +233,8 @@ end * Legacy names `AND`, `OR`, and `XOR` are accepted as aliases for the standard intrinsic functions `IAND`, `IOR`, and `IEOR` respectively. +* A digit count of d=0 is accepted in Ew.0, Dw.0, and Gw.0 output + editing if no nonzero scale factor (kP) is in effect. ### Extensions supported when enabled by options @@ -282,6 +284,8 @@ end * USE association of a procedure interface within that same procedure's definition * NULL() as a structure constructor expression for an ALLOCATABLE component (PGI). * Conversion of LOGICAL to INTEGER in expressions. +* Use of INTEGER data with the intrinsic logical operators `.NOT.`, `.AND.`, `.OR.`, + and `.XOR.`. * IF (integer expression) THEN ... END IF (PGI/Intel) * Comparsion of LOGICAL with ==/.EQ. rather than .EQV. (also .NEQV.) (PGI/Intel) * Procedure pointers in COMMON blocks (PGI/Intel) diff --git a/flang/docs/FlangDriver.md b/flang/docs/FlangDriver.md index ec75162741068..af1fddc8f750a 100644 --- a/flang/docs/FlangDriver.md +++ b/flang/docs/FlangDriver.md @@ -13,20 +13,13 @@ :local: ``` - -> **_NOTE:_** This document assumes that Flang's drivers can already generate code and -> produce executables. However, this is still work-in-progress. By making this -> assumption, we are able to prepare this document ahead-of-time and to provide -> an overview of the design that we are working towards. - There are two main drivers in Flang: * the compiler driver, `flang-new` * the frontend driver, `flang-new -fc1` > **_NOTE:_** The diagrams in this document refer to `flang` as opposed to -> `flang-new`. This is because the diagrams reflect the final design that we -> are still working towards. See the note on [the flang script](https://github.com/llvm/llvm-project/blob/main/flang/docs/FlangDriver.md#the-flang-script) -> below for more context. +> `flang-new`. Eventually, `flang-new` will be renamed as `flang` and the +> diagrams reflect the final design that we are still working towards. The **compiler driver** will allow you to control all compilation phases (e.g. preprocessing, semantic checks, code-generation, code-optimisation, lowering @@ -212,32 +205,25 @@ is `ParseSyntaxOnlyAction`, which corresponds to `-fsyntax-only`. In other words, `flang-new -fc1 ` is equivalent to `flang-new -fc1 -fsyntax-only `. -## The `flang` script -The `flang` wrapper script for `flang-new` was introduced as a development tool -and to facilitate testing. While code-generation is not available in Flang, you -can use it as a drop-in replacement for other Fortran compilers in your build -scripts. - -The `flang` wrapper script will: +## The `flang-to-external-fc` script +The `flang-to-external-fc` wrapper script for `flang-new` was introduced as a +development tool and to facilitate testing. The `flang-to-external-fc` wrapper +script will: * use `flang-new` to unparse the input source file (i.e. it will run `flang-new -fc1 -fdebug-unparse `), and then * call a host Fortran compiler, e.g. `gfortran`, to compile the unparsed file. -Here's a basic breakdown of what happens inside `flang` when you run `flang -file.f90`: +Here's a basic breakdown of what happens inside `flang-to-external-fc` when you +run `flang-to-external-fc file.f90`: ```bash flang-new -fc1 -fdebug-unparse file.f90 -o file-unparsed.f90 gfortran file-unparsed.f90 ``` This is a simplified version for illustration purposes only. In practice, -`flang` adds a few more frontend options and it also supports various other use -cases (e.g. compiling C files, linking existing object files). `gfortran` is -the default host compiler used by `flang`. You can change it by setting the -`FLANG_FC` environment variable. - -Our intention is to replace `flang` with `flang-new`. Please consider `flang` -as a temporary substitute for Flang's compiler driver while the actual driver -is in development. +`flang-to-external-fc` adds a few more frontend options and it also supports +various other use cases (e.g. compiling C files, linking existing object +files). `gfortran` is the default host compiler used by `flang-to-external-fc`. +You can change it by setting the `FLANG_FC` environment variable. ## Adding new Compiler Options Adding a new compiler option in Flang consists of two steps: @@ -337,6 +323,24 @@ the `ExecuteCompilerInvocation.cpp` file. Here's an example for At this point you should be able to trigger that frontend action that you have just added using your new frontend option. + +# CMake Support +As of [#7246](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/7246) +(and soon to be released CMake 3.24.0), `cmake` can detect `flang-new` as a +supported Fortran compiler. You can configure your CMake projects to use +`flang-new` as follows: +```bash +cmake -DCMAKE_Fortran_FLAGS="-flang-experimental-exec" -DCMAKE_Fortran_COMPILER= +``` +You should see the following in the output: +``` +-- The Fortran compiler identification is LLVMFlang +``` +where `` corresponds to the LLVM Flang version. Note that while +generating executables remains experimental, you will need to inform CMake to +use the `-flang-experimental-exec` flag when invoking `flang-new` as in the +example above. + # Testing In LIT, we define two variables that you can use to invoke Flang's drivers: * `%flang` is expanded as `flang-new` (i.e. the compiler driver) diff --git a/flang/docs/FortranLLVMTestSuite.md b/flang/docs/FortranLLVMTestSuite.md index 46a8fe4f63424..a6fffc8937ed8 100644 --- a/flang/docs/FortranLLVMTestSuite.md +++ b/flang/docs/FortranLLVMTestSuite.md @@ -34,6 +34,10 @@ are found in the Fortran subdirectory. To run the C/C++ tests alongside the Fortran tests omit the `-DTEST_SUITE_SUBDIRS` CMake variable. +If your Fortran compiler is Flang, you may want to set the `NO_STOP_MESSAGE` +environment variable to `1` in order to avoid test failures due to warnings +about INEXACT signaling exceptions. + ## Running the SPEC CPU 2017 diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md index d5fdee8f4ff79..f8a12df8d4f24 100644 --- a/flang/docs/Intrinsics.md +++ b/flang/docs/Intrinsics.md @@ -746,7 +746,7 @@ This phase currently supports all the intrinsic procedures listed above but the | Intrinsic Category | Intrinsic Procedures Lacking Support | | --- | --- | -| Coarray intrinsic functions | LCOBOUND, UCOBOUND, FAILED_IMAGES, IMAGE_INDEX, STOPPED_IMAGES, COSHAPE | +| Coarray intrinsic functions | LCOBOUND, UCOBOUND, IMAGE_INDEX, STOPPED_IMAGES, COSHAPE | | Object characteristic inquiry functions | ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS, PRESENT, RANK, SAME_TYPE, STORAGE_SIZE | | Type inquiry intrinsic functions | BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT, NEW_LINE, PRECISION, RADIX, RANGE, TINY| | Non-standard intrinsic functions | AND, OR, XOR, LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT, COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL, DCMPLX, EQV, NEQV, INT8, JINT, JNINT, KNINT, LOC, QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM, NUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF, MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR, IARG, IARGC, NARGS, NUMARG, BADDRESS, IADDR, CACHESIZE, EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC | diff --git a/flang/docs/ReleaseNotes.md b/flang/docs/ReleaseNotes.md index b4b00ee65ffb2..7696f423b8c1d 100644 --- a/flang/docs/ReleaseNotes.md +++ b/flang/docs/ReleaseNotes.md @@ -1,15 +1,15 @@ -# Flang 12.0.0 (In-Progress) Release Notes +# Flang 15.0.0 (In-Progress) Release Notes > **warning** > -> These are in-progress notes for the upcoming LLVM 12.0.0 release. +> These are in-progress notes for the upcoming LLVM 15.0.0 release. > Release notes for previous releases can be found on [the Download > Page](https://releases.llvm.org/download.html). ## Introduction This document contains the release notes for the Flang Fortran frontend, -part of the LLVM Compiler Infrastructure, release 12.0.0. Here we +part of the LLVM Compiler Infrastructure, release 15.0.0. Here we describe the status of Flang in some detail, including major improvements from the previous release and new feature work. For the general LLVM release notes, see [the LLVM @@ -22,60 +22,23 @@ document applies to the *next* release, not the current one. To see the release notes for a specific release, please see the [releases page](https://llvm.org/releases/). -## Known Issues +## Major New Features -These are issues that couldn't be fixed before the release. See the bug -reports for the latest status. +## Bug Fixes - * ... +## Non-comprehensive list of changes in this release +* The bash wrapper script, `flang`, is renamed as `flang-to-external-fc`. -## Introducing Flang +## New Compiler Flags -Flang is LLVM's Fortran front end and is new for the LLVM 11 release. +## Windows Support -Flang is still a work in progress for this release and is included for -experimentation and feedback. +## Fortran Language Changes in Flang -Flang is able to parse a comprehensive subset of the Fortran language -and check it for correctness. Flang is not yet able to generate LLVM IR -for the source code and thus is unable to compile a running binary. +## Build System Changes -Flang is able to unparse the input source code into a canonical form and -emit it to allow testing. Flang can also invoke an external Fortran -compiler on this canonical input. +## New Issues Found -Flang's parser has comprehensive support for: - * Fortran 2018 - * OpenMP 4.5 - * OpenACC 3.0 - -Interested users are invited to try to compile their Fortran codes with -flang in and report any issues in parsing or semantic checking in -[bugzilla](https://bugs.llvm.org/enter_bug.cgi?product=flang). - -### Major missing features - - * Flang is not supported on Windows platforms. - -## Using Flang - -Usage: `flang hello.f90 -o hello.bin` - -By default, Flang will parse the Fortran file `hello.f90` then unparse it to a -canonical Fortran source file. Flang will then invoke an external -Fortran compiler to compile this source file and link it, placing the -resulting executable in `hello.bin`. - -To specify the external Fortran compiler, set the `F18_FC` environment -variable to the name of the compiler binary and ensure that it is on your -`PATH`. The default value for `F18_FC` is `gfortran`. - -When invoked with no source input, Flang will wait for input on stdin. -When invoked in this way, Flang performs the same actions as if -called with `-fdebug-measure-parse-tree -funparse` and does not invoke -`F18_FC`. - -For a full list of options that Flang supports, run `flang --help`. ## Additional Information diff --git a/flang/include/flang/Common/long-double.h b/flang/include/flang/Common/long-double.h deleted file mode 100644 index b1d39a982bd52..0000000000000 --- a/flang/include/flang/Common/long-double.h +++ /dev/null @@ -1,23 +0,0 @@ -/*===-- include/flang/Common/config.h -------------------------------*- C -*-=== - * - * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - * See https://llvm.org/LICENSE.txt for license information. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - * - * ===-----------------------------------------------------------------------=== - */ - -/* This header can be used by both C and C++. */ - -#ifndef FORTRAN_COMMON_LONG_DOUBLE_H -#define FORTRAN_COMMON_LONG_DOUBLE_H - -#ifdef _MSC_VER /* no long double */ -#undef LONG_DOUBLE -#elif __x86_64__ /* x87 extended precision */ -#define LONG_DOUBLE 80 -#else -#define LONG_DOUBLE 128 -#endif - -#endif /* FORTRAN_COMMON_LONG_DOUBLE_H */ diff --git a/flang/include/flang/Evaluate/initial-image.h b/flang/include/flang/Evaluate/initial-image.h index fcc18835418a8..90a781ba091fc 100644 --- a/flang/include/flang/Evaluate/initial-image.h +++ b/flang/include/flang/Evaluate/initial-image.h @@ -49,6 +49,8 @@ class InitialImage { bytes != x.values().size() * static_cast(*elementBytes)) { return SizeMismatch; + } else if (bytes == 0) { + return Ok; } else { std::memcpy(&data_.at(offset), &x.values().at(0), bytes); return Ok; @@ -66,6 +68,8 @@ class InitialImage { auto elementBytes{bytes > 0 ? bytes / elements : 0}; if (elements * elementBytes != bytes) { return SizeMismatch; + } else if (bytes == 0) { + return Ok; } else { for (auto at{x.lbounds()}; elements-- > 0; x.IncrementSubscripts(at)) { auto scalar{x.At(at)}; // this is a std string; size() in chars @@ -76,7 +80,7 @@ class InitialImage { (scalarBytes > elementBytes && elements != 0)) { return SizeMismatch; } - std::memcpy(&data_[offset], scalar.data(), elementBytes); + std::memcpy(&data_.at(offset), scalar.data(), elementBytes); offset += elementBytes; } return Ok; diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h index 2b56da846dd92..c96bc364e3433 100644 --- a/flang/include/flang/Evaluate/tools.h +++ b/flang/include/flang/Evaluate/tools.h @@ -260,17 +260,17 @@ template const Symbol *ExtractBareLenParameter(const A &expr) { } // If an expression simply wraps a DataRef, extract and return it. -// The Boolean argument controls the handling of Substring +// The Boolean argument controls the handling of Substring and ComplexPart // references: when true (not default), it extracts the base DataRef -// of a substring, if it has one. +// of a substring or complex part, if it has one. template common::IfNoLvalue, A> ExtractDataRef( - const A &, bool intoSubstring) { + const A &, bool intoSubstring, bool intoComplexPart) { return std::nullopt; // default base case } template -std::optional ExtractDataRef( - const Designator &d, bool intoSubstring = false) { +std::optional ExtractDataRef(const Designator &d, + bool intoSubstring = false, bool intoComplexPart = false) { return common::visit( [=](const auto &x) -> std::optional { if constexpr (common::HasMember) { @@ -281,29 +281,38 @@ std::optional ExtractDataRef( return ExtractSubstringBase(x); } } + if constexpr (std::is_same_v, ComplexPart>) { + if (intoComplexPart) { + return x.complex(); + } + } return std::nullopt; // w/o "else" to dodge bogus g++ 8.1 warning }, d.u); } template -std::optional ExtractDataRef( - const Expr &expr, bool intoSubstring = false) { +std::optional ExtractDataRef(const Expr &expr, + bool intoSubstring = false, bool intoComplexPart = false) { return common::visit( - [=](const auto &x) { return ExtractDataRef(x, intoSubstring); }, expr.u); + [=](const auto &x) { + return ExtractDataRef(x, intoSubstring, intoComplexPart); + }, + expr.u); } template -std::optional ExtractDataRef( - const std::optional &x, bool intoSubstring = false) { +std::optional ExtractDataRef(const std::optional &x, + bool intoSubstring = false, bool intoComplexPart = false) { if (x) { - return ExtractDataRef(*x, intoSubstring); + return ExtractDataRef(*x, intoSubstring, intoComplexPart); } else { return std::nullopt; } } template -std::optional ExtractDataRef(const A *p, bool intoSubstring = false) { +std::optional ExtractDataRef( + const A *p, bool intoSubstring = false, bool intoComplexPart = false) { if (p) { - return ExtractDataRef(*p, intoSubstring); + return ExtractDataRef(*p, intoSubstring, intoComplexPart); } else { return std::nullopt; } diff --git a/flang/include/flang/Evaluate/type.h b/flang/include/flang/Evaluate/type.h index b7270b2682ff6..54cb50fc7898e 100644 --- a/flang/include/flang/Evaluate/type.h +++ b/flang/include/flang/Evaluate/type.h @@ -452,6 +452,12 @@ int SelectedIntKind(std::int64_t precision = 0); int SelectedRealKind( std::int64_t precision = 0, std::int64_t range = 0, std::int64_t radix = 2); +// Given the dynamic types and kinds of two operands, determine the common +// type to which they must be converted in order to be compared with +// intrinsic OPERATOR(==) or .EQV. +std::optional ComparisonType( + const DynamicType &, const DynamicType &); + // For generating "[extern] template class", &c. boilerplate #define EXPAND_FOR_EACH_INTEGER_KIND(M, P, S) \ M(P, S, 1) M(P, S, 2) M(P, S, 4) M(P, S, 8) M(P, S, 16) diff --git a/flang/include/flang/Frontend/FrontendOptions.h b/flang/include/flang/Frontend/FrontendOptions.h index c8f74e31de432..3be87b6f5218d 100644 --- a/flang/include/flang/Frontend/FrontendOptions.h +++ b/flang/include/flang/Frontend/FrontendOptions.h @@ -115,12 +115,17 @@ bool isToBePreprocessed(llvm::StringRef suffix); enum class Language : uint8_t { Unknown, + /// MLIR: we accept this so that we can run the optimizer on it, and compile + /// it to LLVM IR, assembly or object code. + MLIR, + /// LLVM IR: we accept this so that we can run the optimizer on it, /// and compile it to assembly or object code. LLVM_IR, /// @{ Languages that the frontend can parse and compile. Fortran, + /// @} }; // Source file layout diff --git a/flang/include/flang/Lower/AbstractConverter.h b/flang/include/flang/Lower/AbstractConverter.h index 52c9c282192a6..525d4e4473639 100644 --- a/flang/include/flang/Lower/AbstractConverter.h +++ b/flang/include/flang/Lower/AbstractConverter.h @@ -16,6 +16,7 @@ #include "flang/Common/Fortran.h" #include "flang/Lower/PFTDefs.h" #include "flang/Optimizer/Builder/BoxValue.h" +#include "flang/Semantics/symbol.h" #include "mlir/IR/BuiltinOps.h" #include "llvm/ADT/ArrayRef.h" @@ -76,6 +77,9 @@ class AbstractConverter { /// Get the mlir instance of a symbol. virtual mlir::Value getSymbolAddress(SymbolRef sym) = 0; + virtual fir::ExtendedValue + getSymbolExtendedValue(const Fortran::semantics::Symbol &sym) = 0; + /// Get the binding of an implied do variable by name. virtual mlir::Value impliedDoBinding(llvm::StringRef name) = 0; @@ -99,6 +103,12 @@ class AbstractConverter { virtual void copyHostAssociateVar(const Fortran::semantics::Symbol &sym) = 0; + /// Collect the set of symbols flagged as \p flag in \p eval region. + virtual void collectSymbolSet( + pft::Evaluation &eval, + llvm::SetVector &symbolSet, + Fortran::semantics::Symbol::Flag flag) = 0; + //===--------------------------------------------------------------------===// // Expressions //===--------------------------------------------------------------------===// diff --git a/flang/include/flang/Lower/ConvertExpr.h b/flang/include/flang/Lower/ConvertExpr.h index 66f43904ead8c..c8dd645aa6d98 100644 --- a/flang/include/flang/Lower/ConvertExpr.h +++ b/flang/include/flang/Lower/ConvertExpr.h @@ -232,10 +232,6 @@ inline mlir::NamedAttribute getAdaptToByRefAttr(fir::FirOpBuilder &builder) { builder.getUnitAttr()}; } -/// Generate max(\p value, 0) where \p value is a scalar integer. -mlir::Value genMaxWithZero(fir::FirOpBuilder &builder, mlir::Location loc, - mlir::Value value); - } // namespace Fortran::lower #endif // FORTRAN_LOWER_CONVERTEXPR_H diff --git a/flang/include/flang/Lower/OpenMP.h b/flang/include/flang/Lower/OpenMP.h index c666376c2030f..12cb5f600e414 100644 --- a/flang/include/flang/Lower/OpenMP.h +++ b/flang/include/flang/Lower/OpenMP.h @@ -29,6 +29,7 @@ class AbstractConverter; namespace pft { struct Evaluation; +struct Variable; } // namespace pft void genOpenMPConstruct(AbstractConverter &, pft::Evaluation &, @@ -36,6 +37,7 @@ void genOpenMPConstruct(AbstractConverter &, pft::Evaluation &, void genOpenMPDeclarativeConstruct(AbstractConverter &, pft::Evaluation &, const parser::OpenMPDeclarativeConstruct &); int64_t getCollapseValue(const Fortran::parser::OmpClauseList &clauseList); +void genThreadprivateOp(AbstractConverter &, const pft::Variable &); } // namespace lower } // namespace Fortran diff --git a/flang/include/flang/Lower/PFTBuilder.h b/flang/include/flang/Lower/PFTBuilder.h index 2fcbdcadeea1e..933d50a0c015b 100644 --- a/flang/include/flang/Lower/PFTBuilder.h +++ b/flang/include/flang/Lower/PFTBuilder.h @@ -782,6 +782,11 @@ ParentType *getAncestor(A &node) { void visitAllSymbols(const FunctionLikeUnit &funit, std::function callBack); +/// Call the provided \p callBack on all symbols that are referenced inside \p +/// eval region. +void visitAllSymbols(const Evaluation &eval, + std::function callBack); + } // namespace Fortran::lower::pft namespace Fortran::lower { diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h index ab5b9317f71df..ec9da6b714572 100644 --- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h +++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h @@ -377,10 +377,10 @@ class FirOpBuilder : public mlir::OpBuilder { } /// Generate code testing \p addr is not a null address. - mlir::Value genIsNotNull(mlir::Location loc, mlir::Value addr); + mlir::Value genIsNotNullAddr(mlir::Location loc, mlir::Value addr); /// Generate code testing \p addr is a null address. - mlir::Value genIsNull(mlir::Location loc, mlir::Value addr); + mlir::Value genIsNullAddr(mlir::Location loc, mlir::Value addr); /// Compute the extent of (lb:ub:step) as max((ub-lb+step)/step, 0). See /// Fortran 2018 9.5.3.3.2 section for more details. @@ -542,6 +542,10 @@ mlir::Value createZeroValue(fir::FirOpBuilder &builder, mlir::Location loc, /// Unwrap integer constant from an mlir::Value. llvm::Optional getIntIfConstant(mlir::Value value); +/// Generate max(\p value, 0) where \p value is a scalar integer. +mlir::Value genMaxWithZero(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value value); + } // namespace fir::factory #endif // FORTRAN_OPTIMIZER_BUILDER_FIRBUILDER_H diff --git a/flang/include/flang/Lower/Todo.h b/flang/include/flang/Optimizer/Builder/Todo.h similarity index 97% rename from flang/include/flang/Lower/Todo.h rename to flang/include/flang/Optimizer/Builder/Todo.h index e18bab4ea31fc..0ffbdc59a259c 100644 --- a/flang/include/flang/Lower/Todo.h +++ b/flang/include/flang/Optimizer/Builder/Todo.h @@ -1,4 +1,4 @@ -//===-- Lower/Todo.h --------------------------------------------*- C++ -*-===// +//===-- Optimizer/Builder/Todo.h --------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h index 956ec218ec532..4c0085eab1cfd 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRType.h +++ b/flang/include/flang/Optimizer/Dialect/FIRType.h @@ -16,6 +16,13 @@ #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/BuiltinTypes.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Type.h" + +namespace fir { +class FIROpsDialect; +class KindMapping; +using KindTy = unsigned; +} // namespace fir #define GET_TYPEDEF_CLASSES #include "flang/Optimizer/Dialect/FIROpsTypes.h.inc" @@ -37,11 +44,6 @@ class ValueRange; } // namespace mlir namespace fir { - -class FIROpsDialect; - -using KindTy = unsigned; - namespace detail { struct RecordTypeStorage; } // namespace detail @@ -257,6 +259,14 @@ bool isCharacterProcedureTuple(mlir::Type type, bool acceptRawFunc = true); /// Returns null on error. mlir::Type applyPathToType(mlir::Type rootTy, mlir::ValueRange path); +/// Does this function type have a result that requires binding the result value +/// with storage in a fir.save_result operation in order to use the result? +bool hasAbstractResult(mlir::FunctionType ty); + +/// Convert llvm::Type::TypeID to mlir::Type +mlir::Type fromRealTypeID(mlir::MLIRContext *context, llvm::Type::TypeID typeID, + fir::KindTy kind); + } // namespace fir #endif // FORTRAN_OPTIMIZER_DIALECT_FIRTYPE_H diff --git a/flang/include/flang/Optimizer/Dialect/FIRTypes.td b/flang/include/flang/Optimizer/Dialect/FIRTypes.td index 2152a056f0d53..165a3a614a5dd 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRTypes.td +++ b/flang/include/flang/Optimizer/Dialect/FIRTypes.td @@ -153,6 +153,7 @@ def fir_ComplexType : FIR_Type<"Complex", "complex"> { using KindTy = unsigned; mlir::Type getElementType() const; + mlir::Type getEleType(const fir::KindMapping &kindMap) const; }]; } diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 3ed00dd5e9133..a81125e19e6dc 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -514,6 +514,7 @@ class ParseTreeDumper { NODE(parser, OmpProcBindClause) NODE_ENUM(OmpProcBindClause, Type) NODE(parser, OmpReductionClause) + NODE(parser, OmpInReductionClause) NODE(parser, OmpReductionCombiner) NODE(OmpReductionCombiner, FunctionCombiner) NODE(parser, OmpReductionInitializerClause) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 23c572c2a6b73..e1521f00ff0f8 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3346,8 +3346,9 @@ struct OmpMapClause { // 2.15.5.2 defaultmap -> DEFAULTMAP (implicit-behavior[:variable-category]) struct OmpDefaultmapClause { TUPLE_CLASS_BOILERPLATE(OmpDefaultmapClause); - ENUM_CLASS(ImplicitBehavior, Tofrom) - ENUM_CLASS(VariableCategory, Scalar) + ENUM_CLASS( + ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None, Default) + ENUM_CLASS(VariableCategory, Scalar, Aggregate, Allocatable, Pointer) std::tuple> t; }; @@ -3433,6 +3434,13 @@ struct OmpReductionClause { std::tuple t; }; +// OMP 5.0 2.19.5.6 in_reduction-clause -> IN_REDUCTION (reduction-identifier: +// variable-name-list) +struct OmpInReductionClause { + TUPLE_CLASS_BOILERPLATE(OmpInReductionClause); + std::tuple t; +}; + // OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list) struct OmpAllocateClause { TUPLE_CLASS_BOILERPLATE(OmpAllocateClause); @@ -3754,7 +3762,6 @@ struct OpenMPCancelConstruct { std::tuple> t; }; - // 2.17.8 flush -> FLUSH [memory-order-clause] [(variable-name-list)] struct OpenMPFlushConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct); diff --git a/flang/include/flang/Runtime/cpp-type.h b/flang/include/flang/Runtime/cpp-type.h index 38a8cf7e7e6cb..aa4b6f360124e 100644 --- a/flang/include/flang/Runtime/cpp-type.h +++ b/flang/include/flang/Runtime/cpp-type.h @@ -13,8 +13,11 @@ #include "flang/Common/Fortran.h" #include "flang/Common/uint128.h" +#include "flang/Runtime/float128.h" +#include #include #include +#include namespace Fortran::runtime { @@ -24,6 +27,12 @@ template struct CppTypeForHelper {}; template using CppTypeFor = typename CppTypeForHelper::type; +template +constexpr bool HasCppTypeFor{false}; +template +constexpr bool HasCppTypeFor{ + !std::is_void_v::type>}; + template struct CppTypeForHelper { using type = common::HostSignedIntType<8 * KIND>; }; @@ -35,12 +44,21 @@ template <> struct CppTypeForHelper { template <> struct CppTypeForHelper { using type = double; }; +#if LDBL_MANT_DIG == 64 template <> struct CppTypeForHelper { using type = long double; }; +#endif +#if LDBL_MANT_DIG == 113 +using CppFloat128Type = long double; +#elif HAS_FLOAT128 +using CppFloat128Type = __float128; +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 template <> struct CppTypeForHelper { - using type = long double; + using type = CppFloat128Type; }; +#endif template struct CppTypeForHelper { using type = std::complex>; diff --git a/flang/include/flang/Runtime/float128.h b/flang/include/flang/Runtime/float128.h new file mode 100644 index 0000000000000..a5f96cae9febd --- /dev/null +++ b/flang/include/flang/Runtime/float128.h @@ -0,0 +1,32 @@ +/*===-- flang/Runtime/float128.h ----------------------------------*- C -*-=== + * + * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + * See https://llvm.org/LICENSE.txt for license information. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + *===----------------------------------------------------------------------===*/ + +/* This header is usable in both C and C++ code. + * Isolates build compiler checks to determine the presence of an IEEE-754 + * quad-precision type named __float128 type that isn't __ibm128 + * (double/double). We don't care whether the type has underlying hardware + * support or is emulated. + * + * 128-bit arithmetic may be available via "long double"; this can + * be determined by LDBL_MANT_DIG == 113. A machine may have both 128-bit + * long double and __float128; prefer long double by testing for it first. + */ + +#ifndef FORTRAN_RUNTIME_FLOAT128_H_ +#define FORTRAN_RUNTIME_FLOAT128_H_ + +#undef HAS_FLOAT128 +#if __x86_64__ +#if __GNUC__ >= 7 || __clang_major >= 7 +#define HAS_FLOAT128 1 +#endif +#elif defined __PPC__ && __GNUC__ >= 8 +#define HAS_FLOAT128 1 +#endif + +#endif /* FORTRAN_RUNTIME_FLOAT128_H_ */ diff --git a/flang/include/flang/Runtime/io-api.h b/flang/include/flang/Runtime/io-api.h index 66dd1a7a18b7b..27cffdad42c13 100644 --- a/flang/include/flang/Runtime/io-api.h +++ b/flang/include/flang/Runtime/io-api.h @@ -144,9 +144,11 @@ Cookie IONAME(BeginUnformattedInput)(ExternalUnit = DefaultUnit, const char *sourceFile = nullptr, int sourceLine = 0); // WAIT(ID=) -Cookie IONAME(BeginWait)(ExternalUnit, AsynchronousId); +Cookie IONAME(BeginWait)(ExternalUnit, AsynchronousId, + const char *sourceFile = nullptr, int sourceLine = 0); // WAIT(no ID=) -Cookie IONAME(BeginWaitAll)(ExternalUnit); +Cookie IONAME(BeginWaitAll)( + ExternalUnit, const char *sourceFile = nullptr, int sourceLine = 0); // Other I/O statements Cookie IONAME(BeginClose)( @@ -194,7 +196,8 @@ Cookie IONAME(BeginInquireIoLength)( void IONAME(EnableHandlers)(Cookie, bool hasIoStat = false, bool hasErr = false, bool hasEnd = false, bool hasEor = false, bool hasIoMsg = false); -// ASYNCHRONOUS='YES' or 'NO' with no ID= on READ/WRITE/OPEN +// ASYNCHRONOUS='YES' or 'NO' on READ/WRITE/OPEN +// Use GetAsynchronousId() to handle ID=. bool IONAME(SetAsynchronous)(Cookie, const char *, std::size_t); // Control list options. These return false on a error that the @@ -306,8 +309,8 @@ std::size_t IONAME(GetIoLength)(Cookie); // end-of-record/file condition is present. void IONAME(GetIoMsg)(Cookie, char *, std::size_t); // IOMSG= -// TODO: for ID= on READ/WRITE(ASYNCHRONOUS='YES') -// int IONAME(GetAsynchronousId)(Cookie); +// Defines ID= on READ/WRITE(ASYNCHRONOUS='YES') +int IONAME(GetAsynchronousId)(Cookie); // INQUIRE() specifiers are mostly identified by their NUL-terminated // case-insensitive names. diff --git a/flang/include/flang/Runtime/iostat.h b/flang/include/flang/Runtime/iostat.h index 562efb73f96c9..cfde0448fbf28 100644 --- a/flang/include/flang/Runtime/iostat.h +++ b/flang/include/flang/Runtime/iostat.h @@ -74,6 +74,11 @@ enum Iostat { IostatBadWaitUnit, IostatBOZInputOverflow, IostatIntegerInputOverflow, + IostatRealInputOverflow, + IostatOpenAlreadyConnected, + IostatCannotReposition, + IostatBadWaitId, + IostatTooManyAsyncOps, }; const char *IostatErrorString(int); diff --git a/flang/include/flang/Runtime/numeric.h b/flang/include/flang/Runtime/numeric.h index 6130a25e401c3..d68c5b4a96047 100644 --- a/flang/include/flang/Runtime/numeric.h +++ b/flang/include/flang/Runtime/numeric.h @@ -23,60 +23,84 @@ CppTypeFor RTNAME(Aint4_4)( CppTypeFor); CppTypeFor RTNAME(Aint4_8)( CppTypeFor); +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Aint4_10)( CppTypeFor); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(Aint4_16)( CppTypeFor); +#endif CppTypeFor RTNAME(Aint8_4)( CppTypeFor); CppTypeFor RTNAME(Aint8_8)( CppTypeFor); +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Aint8_10)( CppTypeFor); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(Aint8_16)( CppTypeFor); +#endif +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Aint10_4)( CppTypeFor); CppTypeFor RTNAME(Aint10_8)( CppTypeFor); CppTypeFor RTNAME(Aint10_10)( CppTypeFor); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(Aint16_4)( CppTypeFor); CppTypeFor RTNAME(Aint16_8)( CppTypeFor); CppTypeFor RTNAME(Aint16_16)( CppTypeFor); +#endif // ANINT CppTypeFor RTNAME(Anint4_4)( CppTypeFor); CppTypeFor RTNAME(Anint4_8)( CppTypeFor); +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Anint4_10)( CppTypeFor); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(Anint4_16)( CppTypeFor); +#endif CppTypeFor RTNAME(Anint8_4)( CppTypeFor); CppTypeFor RTNAME(Anint8_8)( CppTypeFor); +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Anint8_10)( CppTypeFor); +#endif +#if LDBL_MANT_DIG == 113 CppTypeFor RTNAME(Anint8_16)( CppTypeFor); +#endif +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Anint10_4)( CppTypeFor); CppTypeFor RTNAME(Anint10_8)( CppTypeFor); CppTypeFor RTNAME(Anint10_10)( CppTypeFor); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(Anint16_4)( CppTypeFor); CppTypeFor RTNAME(Anint16_8)( CppTypeFor); CppTypeFor RTNAME(Anint16_16)( CppTypeFor); +#endif // CEILING CppTypeFor RTNAME(Ceiling4_1)( @@ -103,6 +127,7 @@ CppTypeFor RTNAME(Ceiling8_8)( CppTypeFor RTNAME(Ceiling8_16)( CppTypeFor); #endif +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Ceiling10_1)( CppTypeFor); CppTypeFor RTNAME(Ceiling10_2)( @@ -115,6 +140,8 @@ CppTypeFor RTNAME(Ceiling10_8)( CppTypeFor RTNAME(Ceiling10_16)( CppTypeFor); #endif +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(Ceiling16_1)( CppTypeFor); CppTypeFor RTNAME(Ceiling16_2)( @@ -127,6 +154,7 @@ CppTypeFor RTNAME(Ceiling16_8)( CppTypeFor RTNAME(Ceiling16_16)( CppTypeFor); #endif +#endif // EXPONENT is defined to return default INTEGER; support INTEGER(4 & 8) CppTypeFor RTNAME(Exponent4_4)( @@ -137,14 +165,18 @@ CppTypeFor RTNAME(Exponent8_4)( CppTypeFor); CppTypeFor RTNAME(Exponent8_8)( CppTypeFor); +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Exponent10_4)( CppTypeFor); CppTypeFor RTNAME(Exponent10_8)( CppTypeFor); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT CppTypeFor RTNAME(Exponent16_4)( CppTypeFor); CppTypeFor RTNAME(Exponent16_8)( CppTypeFor); +#endif // FLOOR CppTypeFor RTNAME(Floor4_1)( @@ -171,6 +203,7 @@ CppTypeFor RTNAME(Floor8_8)( CppTypeFor RTNAME(Floor8_16)( CppTypeFor); #endif +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Floor10_1)( CppTypeFor); CppTypeFor RTNAME(Floor10_2)( @@ -183,6 +216,8 @@ CppTypeFor RTNAME(Floor10_8)( CppTypeFor RTNAME(Floor10_16)( CppTypeFor); #endif +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(Floor16_1)( CppTypeFor); CppTypeFor RTNAME(Floor16_2)( @@ -195,67 +230,102 @@ CppTypeFor RTNAME(Floor16_8)( CppTypeFor RTNAME(Floor16_16)( CppTypeFor); #endif +#endif // FRACTION CppTypeFor RTNAME(Fraction4)( CppTypeFor); CppTypeFor RTNAME(Fraction8)( CppTypeFor); +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Fraction10)( CppTypeFor); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(Fraction16)( CppTypeFor); +#endif // ISNAN / IEEE_IS_NAN bool RTNAME(IsNaN4)(CppTypeFor); bool RTNAME(IsNaN8)(CppTypeFor); +#if LDBL_MANT_DIG == 64 bool RTNAME(IsNaN10)(CppTypeFor); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 bool RTNAME(IsNaN16)(CppTypeFor); +#endif // MOD & MODULO CppTypeFor RTNAME(ModInteger1)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModInteger2)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModInteger4)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModInteger8)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); #ifdef __SIZEOF_INT128__ CppTypeFor RTNAME(ModInteger16)( CppTypeFor, - CppTypeFor); + CppTypeFor, const char *sourceFile = nullptr, + int sourceLine = 0); #endif CppTypeFor RTNAME(ModReal4)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModReal8)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(ModReal10)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(ModReal16)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); +#endif CppTypeFor RTNAME(ModuloInteger1)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModuloInteger2)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModuloInteger4)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModuloInteger8)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); #ifdef __SIZEOF_INT128__ CppTypeFor RTNAME(ModuloInteger16)( CppTypeFor, - CppTypeFor); + CppTypeFor, const char *sourceFile = nullptr, + int sourceLine = 0); #endif CppTypeFor RTNAME(ModuloReal4)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModuloReal8)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(ModuloReal10)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(ModuloReal16)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); +#endif // NINT CppTypeFor RTNAME(Nint4_1)( @@ -282,6 +352,7 @@ CppTypeFor RTNAME(Nint8_8)( CppTypeFor RTNAME(Nint8_16)( CppTypeFor); #endif +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Nint10_1)( CppTypeFor); CppTypeFor RTNAME(Nint10_2)( @@ -294,6 +365,8 @@ CppTypeFor RTNAME(Nint10_8)( CppTypeFor RTNAME(Nint10_16)( CppTypeFor); #endif +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(Nint16_1)( CppTypeFor); CppTypeFor RTNAME(Nint16_2)( @@ -302,10 +375,11 @@ CppTypeFor RTNAME(Nint16_4)( CppTypeFor); CppTypeFor RTNAME(Nint16_8)( CppTypeFor); -#ifdef __SIZEOF_INT128__ +#if defined __SIZEOF_INT128__ CppTypeFor RTNAME(Nint16_16)( CppTypeFor); #endif +#endif // NEAREST // The second argument to NEAREST is the result of a comparison @@ -314,50 +388,71 @@ CppTypeFor RTNAME(Nearest4)( CppTypeFor, bool positive); CppTypeFor RTNAME(Nearest8)( CppTypeFor, bool positive); +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Nearest10)( CppTypeFor, bool positive); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(Nearest16)( CppTypeFor, bool positive); +#endif // RRSPACING CppTypeFor RTNAME(RRSpacing4)( CppTypeFor); CppTypeFor RTNAME(RRSpacing8)( CppTypeFor); +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(RRSpacing10)( CppTypeFor); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(RRSpacing16)( CppTypeFor); +#endif // SET_EXPONENT's I= argument can be any INTEGER kind; upcast it to 64-bit CppTypeFor RTNAME(SetExponent4)( CppTypeFor, std::int64_t); CppTypeFor RTNAME(SetExponent8)( CppTypeFor, std::int64_t); +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(SetExponent10)( CppTypeFor, std::int64_t); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(SetExponent16)( CppTypeFor, std::int64_t); +#endif // SCALE CppTypeFor RTNAME(Scale4)( CppTypeFor, std::int64_t); CppTypeFor RTNAME(Scale8)( CppTypeFor, std::int64_t); +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Scale10)( CppTypeFor, std::int64_t); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(Scale16)( CppTypeFor, std::int64_t); +#endif // SPACING CppTypeFor RTNAME(Spacing4)( CppTypeFor); CppTypeFor RTNAME(Spacing8)( CppTypeFor); +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Spacing10)( CppTypeFor); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(Spacing16)( CppTypeFor); +#endif + } // extern "C" } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_NUMERIC_H_ diff --git a/flang/include/flang/Runtime/reduction.h b/flang/include/flang/Runtime/reduction.h index b4aeaad6fe170..411b90432a1c0 100644 --- a/flang/include/flang/Runtime/reduction.h +++ b/flang/include/flang/Runtime/reduction.h @@ -12,7 +12,10 @@ #define FORTRAN_RUNTIME_REDUCTION_H_ #include "flang/Common/uint128.h" +#include "flang/Runtime/cpp-type.h" #include "flang/Runtime/entry-names.h" +#include "flang/Runtime/float128.h" +#include #include #include #include @@ -65,10 +68,14 @@ float RTNAME(SumReal4)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); double RTNAME(SumReal8)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); +#if LDBL_MANT_DIG == 64 long double RTNAME(SumReal10)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); -long double RTNAME(SumReal16)(const Descriptor &, const char *source, int line, - int dim = 0, const Descriptor *mask = nullptr); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +CppFloat128Type RTNAME(SumReal16)(const Descriptor &, const char *source, + int line, int dim = 0, const Descriptor *mask = nullptr); +#endif void RTNAME(CppSumComplex2)(std::complex &, const Descriptor &, const char *source, int line, int dim = 0, @@ -117,10 +124,14 @@ float RTNAME(ProductReal4)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); double RTNAME(ProductReal8)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); +#if LDBL_MANT_DIG == 64 long double RTNAME(ProductReal10)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); -long double RTNAME(ProductReal16)(const Descriptor &, const char *source, +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +CppFloat128Type RTNAME(ProductReal16)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); +#endif void RTNAME(CppProductComplex2)(std::complex &, const Descriptor &, const char *source, int line, int dim = 0, @@ -234,10 +245,14 @@ float RTNAME(MaxvalReal4)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); double RTNAME(MaxvalReal8)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); +#if LDBL_MANT_DIG == 64 long double RTNAME(MaxvalReal10)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); -long double RTNAME(MaxvalReal16)(const Descriptor &, const char *source, +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +CppFloat128Type RTNAME(MaxvalReal16)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); +#endif void RTNAME(MaxvalCharacter)(Descriptor &, const Descriptor &, const char *source, int line, const Descriptor *mask = nullptr); @@ -261,10 +276,14 @@ float RTNAME(MinvalReal4)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); double RTNAME(MinvalReal8)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); +#if LDBL_MANT_DIG == 64 long double RTNAME(MinvalReal10)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); -long double RTNAME(MinvalReal16)(const Descriptor &, const char *source, +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +CppFloat128Type RTNAME(MinvalReal16)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); +#endif void RTNAME(MinvalCharacter)(Descriptor &, const Descriptor &, const char *source, int line, const Descriptor *mask = nullptr); @@ -282,10 +301,13 @@ float RTNAME(Norm2_4)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); double RTNAME(Norm2_8)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); +#if LDBL_MANT_DIG == 64 long double RTNAME(Norm2_10)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); +#elif LDBL_MANT_DIG == 113 long double RTNAME(Norm2_16)(const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); +#endif void RTNAME(Norm2Dim)(Descriptor &, const Descriptor &, int dim, const char *source, int line, const Descriptor *mask = nullptr); @@ -326,10 +348,14 @@ float RTNAME(DotProductReal4)(const Descriptor &, const Descriptor &, const char *source = nullptr, int line = 0); double RTNAME(DotProductReal8)(const Descriptor &, const Descriptor &, const char *source = nullptr, int line = 0); +#if LDBL_MANT_DIG == 64 long double RTNAME(DotProductReal10)(const Descriptor &, const Descriptor &, const char *source = nullptr, int line = 0); -long double RTNAME(DotProductReal16)(const Descriptor &, const Descriptor &, +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +CppFloat128Type RTNAME(DotProductReal16)(const Descriptor &, const Descriptor &, const char *source = nullptr, int line = 0); +#endif void RTNAME(CppDotProductComplex2)(std::complex &, const Descriptor &, const Descriptor &, const char *source = nullptr, int line = 0); void RTNAME(CppDotProductComplex3)(std::complex &, const Descriptor &, @@ -338,12 +364,16 @@ void RTNAME(CppDotProductComplex4)(std::complex &, const Descriptor &, const Descriptor &, const char *source = nullptr, int line = 0); void RTNAME(CppDotProductComplex8)(std::complex &, const Descriptor &, const Descriptor &, const char *source = nullptr, int line = 0); +#if LDBL_MANT_DIG == 64 void RTNAME(CppDotProductComplex10)(std::complex &, const Descriptor &, const Descriptor &, const char *source = nullptr, int line = 0); -void RTNAME(CppDotProductComplex16)(std::complex &, +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +void RTNAME(CppDotProductComplex16)(std::complex &, const Descriptor &, const Descriptor &, const char *source = nullptr, int line = 0); +#endif bool RTNAME(DotProductLogical)(const Descriptor &, const Descriptor &, const char *source = nullptr, int line = 0); diff --git a/flang/include/flang/Semantics/expression.h b/flang/include/flang/Semantics/expression.h index 6c0d385a266bc..70e67bc237373 100644 --- a/flang/include/flang/Semantics/expression.h +++ b/flang/include/flang/Semantics/expression.h @@ -322,7 +322,7 @@ class ExpressionAnalyzer { DataRef &&, const Symbol &, const semantics::Scope &); MaybeExpr CompleteSubscripts(ArrayRef &&); MaybeExpr ApplySubscripts(DataRef &&, std::vector &&); - MaybeExpr TopLevelChecks(DataRef &&); + bool CheckRanks(const DataRef &); // Return false if error exists. std::optional> GetSubstringBound( const std::optional &); MaybeExpr AnalyzeDefinedOp(const parser::Name &, ActualArguments &&); diff --git a/flang/lib/Decimal/binary-to-decimal.cpp b/flang/lib/Decimal/binary-to-decimal.cpp index c9efb3485798d..7b31d02b292e4 100644 --- a/flang/lib/Decimal/binary-to-decimal.cpp +++ b/flang/lib/Decimal/binary-to-decimal.cpp @@ -9,6 +9,7 @@ #include "big-radix-floating-point.h" #include "flang/Decimal/decimal.h" #include +#include #include namespace Fortran::decimal { @@ -349,14 +350,14 @@ ConversionToDecimalResult ConvertDoubleToDecimal(char *buffer, std::size_t size, rounding, Fortran::decimal::BinaryFloatingPointNumber<53>(x)); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 ConversionToDecimalResult ConvertLongDoubleToDecimal(char *buffer, std::size_t size, enum DecimalConversionFlags flags, int digits, enum FortranRounding rounding, long double x) { return Fortran::decimal::ConvertToDecimal(buffer, size, flags, digits, rounding, Fortran::decimal::BinaryFloatingPointNumber<64>(x)); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 ConversionToDecimalResult ConvertLongDoubleToDecimal(char *buffer, std::size_t size, enum DecimalConversionFlags flags, int digits, enum FortranRounding rounding, long double x) { diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp index 789e0a2de7d2e..2071b12b1dcf9 100644 --- a/flang/lib/Evaluate/check-expression.cpp +++ b/flang/lib/Evaluate/check-expression.cpp @@ -418,7 +418,10 @@ std::optional> NonPointerInitializationExpr(const Symbol &symbol, int symRank{GetRank(symTS->shape())}; if (IsImpliedShape(symbol)) { if (folded.Rank() == symRank) { - return {std::move(folded)}; + return ArrayConstantBoundChanger{ + std::move(*AsConstantExtents( + context, GetRawLowerBounds(context, NamedEntity{symbol})))} + .ChangeLbounds(std::move(folded)); } else { context.messages().Say( "Implied-shape parameter '%s' has rank %d but its initializer has rank %d"_err_en_US, diff --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h index 97abfc688d639..c0dee020f8fb8 100644 --- a/flang/lib/Evaluate/fold-implementation.h +++ b/flang/lib/Evaluate/fold-implementation.h @@ -613,26 +613,33 @@ template Expr Folder::CSHIFT(FunctionRef &&funcRef) { } if (ok) { std::vector> resultElements; - ConstantSubscripts arrayAt{array->lbounds()}; - ConstantSubscript dimLB{arrayAt[zbDim]}; + ConstantSubscripts arrayLB{array->lbounds()}; + ConstantSubscripts arrayAt{arrayLB}; + ConstantSubscript &dimIndex{arrayAt[zbDim]}; + ConstantSubscript dimLB{dimIndex}; // initial value ConstantSubscript dimExtent{array->shape()[zbDim]}; - ConstantSubscripts shiftAt{shift->lbounds()}; - for (auto n{GetSize(array->shape())}; n > 0; n -= dimExtent) { - ConstantSubscript shiftCount{shift->At(shiftAt).ToInt64()}; - ConstantSubscript zbDimIndex{shiftCount % dimExtent}; - if (zbDimIndex < 0) { - zbDimIndex += dimExtent; - } - for (ConstantSubscript j{0}; j < dimExtent; ++j) { - arrayAt[zbDim] = dimLB + zbDimIndex; - resultElements.push_back(array->At(arrayAt)); - if (++zbDimIndex == dimExtent) { - zbDimIndex = 0; + ConstantSubscripts shiftLB{shift->lbounds()}; + for (auto n{GetSize(array->shape())}; n > 0; --n) { + ConstantSubscript origDimIndex{dimIndex}; + ConstantSubscripts shiftAt; + if (shift->Rank() > 0) { + int k{0}; + for (int j{0}; j < rank; ++j) { + if (j != zbDim) { + shiftAt.emplace_back(shiftLB[k++] + arrayAt[j] - arrayLB[j]); + } } } - arrayAt[zbDim] = dimLB + std::max(dimExtent, 1) - 1; + ConstantSubscript shiftCount{shift->At(shiftAt).ToInt64()}; + dimIndex = dimLB + ((dimIndex - dimLB + shiftCount) % dimExtent); + if (dimIndex < dimLB) { + dimIndex += dimExtent; + } else if (dimIndex >= dimLB + dimExtent) { + dimIndex -= dimExtent; + } + resultElements.push_back(array->At(arrayAt)); + dimIndex = origDimIndex; array->IncrementSubscripts(arrayAt); - shift->IncrementSubscripts(shiftAt); } return Expr{PackageConstant( std::move(resultElements), *array, array->shape())}; @@ -714,42 +721,57 @@ template Expr Folder::EOSHIFT(FunctionRef &&funcRef) { } if (ok) { std::vector> resultElements; - ConstantSubscripts arrayAt{array->lbounds()}; - ConstantSubscript dimLB{arrayAt[zbDim]}; + ConstantSubscripts arrayLB{array->lbounds()}; + ConstantSubscripts arrayAt{arrayLB}; + ConstantSubscript &dimIndex{arrayAt[zbDim]}; + ConstantSubscript dimLB{dimIndex}; // initial value ConstantSubscript dimExtent{array->shape()[zbDim]}; - ConstantSubscripts shiftAt{shift->lbounds()}; - ConstantSubscripts boundaryAt; + ConstantSubscripts shiftLB{shift->lbounds()}; + ConstantSubscripts boundaryLB; if (boundary) { - boundaryAt = boundary->lbounds(); + boundaryLB = boundary->lbounds(); } - for (auto n{GetSize(array->shape())}; n > 0; n -= dimExtent) { + for (auto n{GetSize(array->shape())}; n > 0; --n) { + ConstantSubscript origDimIndex{dimIndex}; + ConstantSubscripts shiftAt; + if (shift->Rank() > 0) { + int k{0}; + for (int j{0}; j < rank; ++j) { + if (j != zbDim) { + shiftAt.emplace_back(shiftLB[k++] + arrayAt[j] - arrayLB[j]); + } + } + } ConstantSubscript shiftCount{shift->At(shiftAt).ToInt64()}; - for (ConstantSubscript j{0}; j < dimExtent; ++j) { - ConstantSubscript zbAt{shiftCount + j}; - if (zbAt >= 0 && zbAt < dimExtent) { - arrayAt[zbDim] = dimLB + zbAt; - resultElements.push_back(array->At(arrayAt)); - } else if (boundary) { - resultElements.push_back(boundary->At(boundaryAt)); - } else if constexpr (T::category == TypeCategory::Integer || - T::category == TypeCategory::Real || - T::category == TypeCategory::Complex || - T::category == TypeCategory::Logical) { - resultElements.emplace_back(); - } else if constexpr (T::category == TypeCategory::Character) { - auto len{static_cast(array->LEN())}; - typename Scalar::value_type space{' '}; - resultElements.emplace_back(len, space); - } else { - DIE("no derived type boundary"); + dimIndex += shiftCount; + if (dimIndex >= dimLB && dimIndex < dimLB + dimExtent) { + resultElements.push_back(array->At(arrayAt)); + } else if (boundary) { + ConstantSubscripts boundaryAt; + if (boundary->Rank() > 0) { + for (int j{0}; j < rank; ++j) { + int k{0}; + if (j != zbDim) { + boundaryAt.emplace_back( + boundaryLB[k++] + arrayAt[j] - arrayLB[j]); + } + } } + resultElements.push_back(boundary->At(boundaryAt)); + } else if constexpr (T::category == TypeCategory::Integer || + T::category == TypeCategory::Real || + T::category == TypeCategory::Complex || + T::category == TypeCategory::Logical) { + resultElements.emplace_back(); + } else if constexpr (T::category == TypeCategory::Character) { + auto len{static_cast(array->LEN())}; + typename Scalar::value_type space{' '}; + resultElements.emplace_back(len, space); + } else { + DIE("no derived type boundary"); } - arrayAt[zbDim] = dimLB + std::max(dimExtent, 1) - 1; + dimIndex = origDimIndex; array->IncrementSubscripts(arrayAt); - shift->IncrementSubscripts(shiftAt); - if (boundary) { - boundary->IncrementSubscripts(boundaryAt); - } } return Expr{PackageConstant( std::move(resultElements), *array, array->shape())}; diff --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp index a1dbcd144c519..8c1f2122a7ac9 100644 --- a/flang/lib/Evaluate/fold-integer.cpp +++ b/flang/lib/Evaluate/fold-integer.cpp @@ -436,6 +436,17 @@ static std::optional> FoldLocationCall( ActualArguments &arg, FoldingContext &context) { if (arg[0]) { if (auto type{arg[0]->GetType()}) { + if constexpr (which == WhichLocation::Findloc) { + // Both ARRAY and VALUE are susceptible to conversion to a common + // comparison type. + if (arg[1]) { + if (auto valType{arg[1]->GetType()}) { + if (auto compareType{ComparisonType(*type, *valType)}) { + type = compareType; + } + } + } + } return common::SearchTypes( LocationHelper{std::move(*type), arg, context}); } diff --git a/flang/lib/Evaluate/initial-image.cpp b/flang/lib/Evaluate/initial-image.cpp index 298c1f7c4f65f..4ff4adb146c1f 100644 --- a/flang/lib/Evaluate/initial-image.cpp +++ b/flang/lib/Evaluate/initial-image.cpp @@ -24,8 +24,7 @@ auto InitialImage::Add(ConstantSubscript offset, std::size_t bytes, return SizeMismatch; } else { auto at{x.lbounds()}; - for (auto elements{TotalElementCount(x.shape())}; elements-- > 0; - x.IncrementSubscripts(at)) { + for (; elements-- > 0; x.IncrementSubscripts(at)) { auto scalar{x.At(at)}; // TODO: length type parameter values? for (const auto &[symbolRef, indExpr] : scalar) { @@ -38,7 +37,7 @@ auto InitialImage::Add(ConstantSubscript offset, std::size_t bytes, Result added{Add(offset + component.offset(), component.size(), indExpr.value(), context)}; if (added != Ok) { - return Ok; + return added; } } } diff --git a/flang/lib/Evaluate/intrinsics-library.cpp b/flang/lib/Evaluate/intrinsics-library.cpp index 160a5894f38e7..e33c9fe525915 100644 --- a/flang/lib/Evaluate/intrinsics-library.cpp +++ b/flang/lib/Evaluate/intrinsics-library.cpp @@ -16,6 +16,7 @@ #include "host.h" #include "flang/Common/static-multimap-view.h" #include "flang/Evaluate/expression.h" +#include #include #include #include @@ -324,8 +325,7 @@ template <> struct HostRuntimeLibrary { static_assert(map.Verify(), "map must be sorted"); }; -#if !defined(__PPC__) || defined(__LONG_DOUBLE_IEEE128__) -// TODO: use HostTypeExists instead? +#if LDBL_MANT_DIG == 80 || LDBL_MANT_DIG == 113 template <> struct HostRuntimeLibrary { using F = FuncPointer; @@ -341,7 +341,7 @@ struct HostRuntimeLibrary { static constexpr HostRuntimeMap map{table}; static_assert(map.Verify(), "map must be sorted"); }; -#endif // !defined(__PPC__) || defined(__LONG_DOUBLE_IEEE128__) +#endif // LDBL_MANT_DIG == 80 || LDBL_MANT_DIG == 113 #endif /// Define pgmath description diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index 64aafe5e50832..241f008c6d89b 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -420,6 +420,8 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ {{"a", ExtensibleDerived, Rank::anyOrAssumedRank}, {"mold", ExtensibleDerived, Rank::anyOrAssumedRank}}, DefaultLogical, Rank::scalar, IntrinsicClass::inquiryFunction}, + {"failed_images", {OptionalTEAM, SizeDefaultKIND}, KINDInt, Rank::vector, + IntrinsicClass::transformationalFunction}, {"findloc", {{"array", AnyNumeric, Rank::array}, {"value", AnyNumeric, Rank::scalar}, RequiredDIM, OptionalMASK, @@ -629,6 +631,8 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ // NULL() is a special case handled in Probe() below {"num_images", {}, DefaultInt, Rank::scalar, IntrinsicClass::transformationalFunction}, + {"num_images", {{"team", TeamType, Rank::scalar}}, DefaultInt, Rank::scalar, + IntrinsicClass::transformationalFunction}, {"num_images", {{"team_number", AnyInt, Rank::scalar}}, DefaultInt, Rank::scalar, IntrinsicClass::transformationalFunction}, {"out_of_range", @@ -834,7 +838,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ }; // TODO: Coarray intrinsic functions -// LCOBOUND, UCOBOUND, FAILED_IMAGES, IMAGE_INDEX, +// LCOBOUND, UCOBOUND, IMAGE_INDEX, // STOPPED_IMAGES, COSHAPE // TODO: Non-standard intrinsic functions // LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT, diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp index 293c91b700502..68faac50cb4eb 100644 --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -1380,7 +1380,7 @@ bool IsSaved(const Symbol &original) { } else if (const auto *object{symbol.detailsIf()}; object && object->init()) { return true; - } else if (IsProcedurePointer(symbol) && + } else if (IsProcedurePointer(symbol) && symbol.has() && symbol.get().init()) { return true; } else if (scope.hasSAVE()) { diff --git a/flang/lib/Evaluate/type.cpp b/flang/lib/Evaluate/type.cpp index 626bfaa93cb65..4971f722aee4a 100644 --- a/flang/lib/Evaluate/type.cpp +++ b/flang/lib/Evaluate/type.cpp @@ -580,4 +580,58 @@ int SelectedRealKind( } } } + +std::optional ComparisonType( + const DynamicType &t1, const DynamicType &t2) { + switch (t1.category()) { + case TypeCategory::Integer: + switch (t2.category()) { + case TypeCategory::Integer: + return DynamicType{TypeCategory::Integer, std::max(t1.kind(), t2.kind())}; + case TypeCategory::Real: + case TypeCategory::Complex: + return t2; + default: + return std::nullopt; + } + case TypeCategory::Real: + switch (t2.category()) { + case TypeCategory::Integer: + return t1; + case TypeCategory::Real: + case TypeCategory::Complex: + return DynamicType{t2.category(), std::max(t1.kind(), t2.kind())}; + default: + return std::nullopt; + } + case TypeCategory::Complex: + switch (t2.category()) { + case TypeCategory::Integer: + return t1; + case TypeCategory::Real: + case TypeCategory::Complex: + return DynamicType{TypeCategory::Complex, std::max(t1.kind(), t2.kind())}; + default: + return std::nullopt; + } + case TypeCategory::Character: + switch (t2.category()) { + case TypeCategory::Character: + return DynamicType{ + TypeCategory::Character, std::max(t1.kind(), t2.kind())}; + default: + return std::nullopt; + } + case TypeCategory::Logical: + switch (t2.category()) { + case TypeCategory::Logical: + return DynamicType{TypeCategory::Logical, LogicalResult::kind}; + default: + return std::nullopt; + } + default: + return std::nullopt; + } +} + } // namespace Fortran::evaluate diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 9ea4810d64950..8f2167b14f0e6 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -263,13 +263,18 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, llvm::StringRef xValue = a->getValue(); // Principal languages. dashX = llvm::StringSwitch(xValue) - .Case("f90", Language::Fortran) + // Flang does not differentiate between pre-processed and not + // pre-processed inputs. + .Case("f95", Language::Fortran) + .Case("f95-cpp-input", Language::Fortran) .Default(Language::Unknown); - // Some special cases cannot be combined with suffixes. + // Flang's intermediate representations. if (dashX.isUnknown()) dashX = llvm::StringSwitch(xValue) .Case("ir", Language::LLVM_IR) + .Case("fir", Language::MLIR) + .Case("mlir", Language::MLIR) .Default(Language::Unknown); if (dashX.isUnknown()) diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 296c75b587971..a842420be887a 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -32,6 +32,7 @@ #include "flang/Semantics/unparse-with-symbols.h" #include "mlir/IR/Dialect.h" +#include "mlir/Parser/Parser.h" #include "mlir/Pass/PassManager.h" #include "mlir/Target/LLVMIR/ModuleTranslation.h" #include "clang/Basic/Diagnostic.h" @@ -41,6 +42,7 @@ #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Bitcode/BitcodeWriterPass.h" #include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Passes/PassBuilder.h" @@ -78,29 +80,63 @@ bool PrescanAndSemaDebugAction::beginSourceFileAction() { bool CodeGenAction::beginSourceFileAction() { llvmCtx = std::make_unique(); + CompilerInstance &ci = this->getInstance(); // If the input is an LLVM file, just parse it and return. if (this->getCurrentInput().getKind().getLanguage() == Language::LLVM_IR) { llvm::SMDiagnostic err; llvmModule = llvm::parseIRFile(getCurrentInput().getFile(), err, *llvmCtx); + if (!llvmModule || llvm::verifyModule(*llvmModule, &llvm::errs())) { + err.print("flang-new", llvm::errs()); + unsigned diagID = ci.getDiagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Error, "Could not parse IR"); + ci.getDiagnostics().Report(diagID); + return false; + } - return (nullptr != llvmModule); + return true; } - // Otherwise, generate an MLIR module from the input Fortran source - assert(getCurrentInput().getKind().getLanguage() == Language::Fortran && - "Invalid input type - expecting a Fortran file"); - bool res = runPrescan() && runParse() && runSemanticChecks(); - if (!res) - return res; - - CompilerInstance &ci = this->getInstance(); - // Load the MLIR dialects required by Flang mlir::DialectRegistry registry; mlirCtx = std::make_unique(registry); fir::support::registerNonCodegenDialects(registry); fir::support::loadNonCodegenDialects(*mlirCtx); + fir::support::loadDialects(*mlirCtx); + fir::support::registerLLVMTranslation(*mlirCtx); + + // If the input is an MLIR file, just parse it and return. + if (this->getCurrentInput().getKind().getLanguage() == Language::MLIR) { + llvm::SourceMgr sourceMgr; + llvm::ErrorOr> fileOrErr = + llvm::MemoryBuffer::getFileOrSTDIN(getCurrentInput().getFile()); + sourceMgr.AddNewSourceBuffer(std::move(*fileOrErr), llvm::SMLoc()); + mlir::OwningOpRef module = + mlir::parseSourceFile(sourceMgr, mlirCtx.get()); + + if (!module || mlir::failed(module->verifyInvariants())) { + unsigned diagID = ci.getDiagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Error, "Could not parse FIR"); + ci.getDiagnostics().Report(diagID); + return false; + } + + mlirModule = std::make_unique(module.release()); + return true; + } + + // Otherwise, generate an MLIR module from the input Fortran source + if (getCurrentInput().getKind().getLanguage() != Language::Fortran) { + unsigned diagID = ci.getDiagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Error, + "Invalid input type - expecting a Fortran file"); + ci.getDiagnostics().Report(diagID); + return false; + } + bool res = runPrescan() && runParse() && runSemanticChecks() && + generateRtTypeTables(); + if (!res) + return res; // Create a LoweringBridge const common::IntrinsicTypeDefaultKinds &defKinds = diff --git a/flang/lib/Frontend/FrontendOptions.cpp b/flang/lib/Frontend/FrontendOptions.cpp index 574e007278327..8353858ff5094 100644 --- a/flang/lib/Frontend/FrontendOptions.cpp +++ b/flang/lib/Frontend/FrontendOptions.cpp @@ -42,6 +42,8 @@ InputKind FrontendOptions::getInputKindForExtension(llvm::StringRef extension) { if (extension == "bc" || extension == "ll") return Language::LLVM_IR; + if (extension == "fir" || extension == "mlir") + return Language::MLIR; return Language::Unknown; } diff --git a/flang/lib/Lower/Allocatable.cpp b/flang/lib/Lower/Allocatable.cpp index 4023552c6a9cf..d8ae0a9c91f4c 100644 --- a/flang/lib/Lower/Allocatable.cpp +++ b/flang/lib/Lower/Allocatable.cpp @@ -17,9 +17,9 @@ #include "flang/Lower/PFTBuilder.h" #include "flang/Lower/Runtime.h" #include "flang/Lower/StatementContext.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Optimizer/Support/FatalError.h" diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index a33ddee64e198..6caea151c20e8 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -27,12 +27,12 @@ #include "flang/Lower/Runtime.h" #include "flang/Lower/StatementContext.h" #include "flang/Lower/Support/Utils.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/BoxValue.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Runtime/Character.h" #include "flang/Optimizer/Builder/Runtime/Ragged.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRAttr.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROps.h" @@ -87,7 +87,10 @@ struct IncrementLoopInfo { const Fortran::lower::SomeExpr *lowerExpr; const Fortran::lower::SomeExpr *upperExpr; const Fortran::lower::SomeExpr *stepExpr; + const Fortran::lower::SomeExpr *maskExpr = nullptr; bool isUnordered; // do concurrent, forall + llvm::SmallVector localInitSymList; + llvm::SmallVector sharedSymList; mlir::Value loopVariable = nullptr; mlir::Value stepValue = nullptr; // possible uses in multiple blocks @@ -95,8 +98,10 @@ struct IncrementLoopInfo { fir::DoLoopOp doLoop = nullptr; // Data members for unstructured loops. + bool hasRealControl = false; mlir::Value tripVariable = nullptr; mlir::Block *headerBlock = nullptr; // loop entry and test block + mlir::Block *maskBlock = nullptr; // concurrent loop mask block mlir::Block *bodyBlock = nullptr; // first loop body block mlir::Block *exitBlock = nullptr; // loop exit target block }; @@ -312,6 +317,13 @@ class FirConverter : public Fortran::lower::AbstractConverter { return lookupSymbol(sym).getAddr(); } + fir::ExtendedValue + getSymbolExtendedValue(const Fortran::semantics::Symbol &sym) override final { + Fortran::lower::SymbolBox sb = localSymbols.lookupSymbol(sym); + assert(sb && "symbol box not found"); + return sb.toExtendedValue(); + } + mlir::Value impliedDoBinding(llvm::StringRef name) override final { mlir::Value val = localSymbols.lookupImpliedDo(name); if (!val) @@ -499,6 +511,18 @@ class FirConverter : public Fortran::lower::AbstractConverter { // Utility methods //===--------------------------------------------------------------------===// + void collectSymbolSet( + Fortran::lower::pft::Evaluation &eval, + llvm::SetVector &symbolSet, + Fortran::semantics::Symbol::Flag flag) override final { + auto addToList = [&](const Fortran::semantics::Symbol &sym) { + const Fortran::semantics::Symbol &ultimate = sym.GetUltimate(); + if (ultimate.test(flag)) + symbolSet.insert(&ultimate); + }; + Fortran::lower::pft::visitAllSymbols(eval, addToList); + } + mlir::Location getCurrentLocation() override final { return toLocation(); } /// Generate a dummy location. @@ -616,9 +640,24 @@ class FirConverter : public Fortran::lower::AbstractConverter { } /// Generate the address of loop variable \p sym. + /// If \p sym is not mapped yet, allocate local storage for it. mlir::Value genLoopVariableAddress(mlir::Location loc, - const Fortran::semantics::Symbol &sym) { - assert(lookupSymbol(sym) && "loop control variable must already be in map"); + const Fortran::semantics::Symbol &sym, + bool isUnordered) { + if (isUnordered || sym.has() || + sym.has()) { + if (!shallowLookupSymbol(sym)) { + // Do concurrent loop variables are not mapped yet since they are local + // to the Do concurrent scope (same for OpenMP loops). + auto newVal = builder->createTemporary(loc, genType(sym), + toStringRef(sym.name())); + bindIfNewSymbol(sym, newVal); + return newVal; + } + } + auto entry = lookupSymbol(sym); + (void)entry; + assert(entry && "loop control variable must already be in map"); Fortran::lower::StatementContext stmtCtx; return fir::getBase( genExprAddr(Fortran::evaluate::AsGenericExpr(sym).value(), stmtCtx)); @@ -953,6 +992,34 @@ class FirConverter : public Fortran::lower::AbstractConverter { builder->create(loc, selectExpr, indexList, blockList); } + /// Collect DO CONCURRENT or FORALL loop control information. + IncrementLoopNestInfo getConcurrentControl( + const Fortran::parser::ConcurrentHeader &header, + const std::list &localityList = {}) { + IncrementLoopNestInfo incrementLoopNestInfo; + for (const Fortran::parser::ConcurrentControl &control : + std::get>(header.t)) + incrementLoopNestInfo.emplace_back( + *std::get<0>(control.t).symbol, std::get<1>(control.t), + std::get<2>(control.t), std::get<3>(control.t), /*isUnordered=*/true); + IncrementLoopInfo &info = incrementLoopNestInfo.back(); + info.maskExpr = Fortran::semantics::GetExpr( + std::get>(header.t)); + for (const Fortran::parser::LocalitySpec &x : localityList) { + if (const auto *localInitList = + std::get_if(&x.u)) + for (const Fortran::parser::Name &x : localInitList->v) + info.localInitSymList.push_back(x.symbol); + if (const auto *sharedList = + std::get_if(&x.u)) + for (const Fortran::parser::Name &x : sharedList->v) + info.sharedSymList.push_back(x.symbol); + if (std::get_if(&x.u)) + TODO(toLocation(), "do concurrent locality specs not implemented"); + } + return incrementLoopNestInfo; + } + /// Generate FIR for a DO construct. There are six variants: /// - unstructured infinite and while loops /// - structured and unstructured increment loops @@ -982,8 +1049,13 @@ class FirConverter : public Fortran::lower::AbstractConverter { mlir::Block *exitBlock = doStmtEval.parentConstruct->constructExit->block; IncrementLoopNestInfo incrementLoopNestInfo; const Fortran::parser::ScalarLogicalExpr *whileCondition = nullptr; - if ((whileCondition = std::get_if( - &loopControl->u))) { + bool infiniteLoop = !loopControl.has_value(); + if (infiniteLoop) { + assert(unstructuredContext && "infinite loop must be unstructured"); + startBlock(headerBlock); + } else if ((whileCondition = + std::get_if( + &loopControl->u))) { assert(unstructuredContext && "while loop must be unstructured"); maybeStartBlock(preheaderBlock); // no block or empty block startBlock(headerBlock); @@ -997,17 +1069,45 @@ class FirConverter : public Fortran::lower::AbstractConverter { bounds->step); if (unstructuredContext) { maybeStartBlock(preheaderBlock); + info.hasRealControl = info.loopVariableSym.GetType()->IsNumeric( + Fortran::common::TypeCategory::Real); info.headerBlock = headerBlock; info.bodyBlock = bodyBlock; info.exitBlock = exitBlock; } } else { - TODO(toLocation(), "infinite/unstructured loop/concurrent loop"); + const auto *concurrent = + std::get_if( + &loopControl->u); + assert(concurrent && "invalid DO loop variant"); + incrementLoopNestInfo = getConcurrentControl( + std::get(concurrent->t), + std::get>(concurrent->t)); + if (unstructuredContext) { + maybeStartBlock(preheaderBlock); + for (IncrementLoopInfo &info : incrementLoopNestInfo) { + // The original loop body provides the body and latch blocks of the + // innermost dimension. The (first) body block of a non-innermost + // dimension is the preheader block of the immediately enclosed + // dimension. The latch block of a non-innermost dimension is the + // exit block of the immediately enclosed dimension. + auto createNextExitBlock = [&]() { + // Create unstructured loop exit blocks, outermost to innermost. + return exitBlock = insertBlock(exitBlock); + }; + bool isInnermost = &info == &incrementLoopNestInfo.back(); + bool isOutermost = &info == &incrementLoopNestInfo.front(); + info.headerBlock = isOutermost ? headerBlock : createNextBeginBlock(); + info.bodyBlock = isInnermost ? bodyBlock : createNextBeginBlock(); + info.exitBlock = isOutermost ? exitBlock : createNextExitBlock(); + if (info.maskExpr) + info.maskBlock = createNextBeginBlock(); + } + } } - // Increment loop begin code. (TODO: Infinite/while code was already - // generated.) - if (!whileCondition) + // Increment loop begin code. (Infinite/while code was already generated.) + if (!infiniteLoop && !whileCondition) genFIRIncrementLoopBegin(incrementLoopNestInfo); // Loop body code - NonLabelDoStmt and EndDoStmt code is generated here. @@ -1015,8 +1115,8 @@ class FirConverter : public Fortran::lower::AbstractConverter { for (Fortran::lower::pft::Evaluation &e : eval.getNestedEvaluations()) genFIR(e, unstructuredContext); - // Loop end code. (TODO: infinite loop) - if (whileCondition) + // Loop end code. + if (infiniteLoop || whileCondition) genFIRBranch(headerBlock); else genFIRIncrementLoopEnd(incrementLoopNestInfo); @@ -1034,10 +1134,33 @@ class FirConverter : public Fortran::lower::AbstractConverter { if (expr) return builder->createConvert(loc, controlType, createFIRExpr(loc, expr, stmtCtx)); + + if (info.hasRealControl) + return builder->createRealConstant(loc, controlType, 1u); return builder->createIntegerConstant(loc, controlType, 1); // step }; + auto handleLocalitySpec = [&](IncrementLoopInfo &info) { + // Generate Local Init Assignments + for (const Fortran::semantics::Symbol *sym : info.localInitSymList) { + const auto *hostDetails = + sym->detailsIf(); + assert(hostDetails && "missing local_init variable host variable"); + const Fortran::semantics::Symbol &hostSym = hostDetails->symbol(); + (void)hostSym; + TODO(loc, "do concurrent locality specs not implemented"); + } + // Handle shared locality spec + for (const Fortran::semantics::Symbol *sym : info.sharedSymList) { + const auto *hostDetails = + sym->detailsIf(); + assert(hostDetails && "missing shared variable host variable"); + const Fortran::semantics::Symbol &hostSym = hostDetails->symbol(); + copySymbolBinding(hostSym, *sym); + } + }; for (IncrementLoopInfo &info : incrementLoopNestInfo) { - info.loopVariable = genLoopVariableAddress(loc, info.loopVariableSym); + info.loopVariable = + genLoopVariableAddress(loc, info.loopVariableSym, info.isUnordered); mlir::Value lowerValue = genControlValue(info.lowerExpr, info); mlir::Value upperValue = genControlValue(info.upperExpr, info); info.stepValue = genControlValue(info.stepExpr, info); @@ -1052,34 +1175,80 @@ class FirConverter : public Fortran::lower::AbstractConverter { mlir::Value value = builder->createConvert( loc, info.getLoopVariableType(), info.doLoop.getInductionVar()); builder->create(loc, value, info.loopVariable); - // TODO: Mask expr - // TODO: handle Locality Spec + if (info.maskExpr) { + Fortran::lower::StatementContext stmtCtx; + mlir::Value maskCond = createFIRExpr(loc, info.maskExpr, stmtCtx); + stmtCtx.finalize(); + mlir::Value maskCondCast = + builder->createConvert(loc, builder->getI1Type(), maskCond); + auto ifOp = builder->create(loc, maskCondCast, + /*withElseRegion=*/false); + builder->setInsertionPointToStart(&ifOp.getThenRegion().front()); + } + handleLocalitySpec(info); continue; } // Unstructured loop preheader - initialize tripVariable and loopVariable. mlir::Value tripCount; - auto diff1 = - builder->create(loc, upperValue, lowerValue); - auto diff2 = - builder->create(loc, diff1, info.stepValue); - tripCount = - builder->create(loc, diff2, info.stepValue); + if (info.hasRealControl) { + auto diff1 = + builder->create(loc, upperValue, lowerValue); + auto diff2 = + builder->create(loc, diff1, info.stepValue); + tripCount = + builder->create(loc, diff2, info.stepValue); + tripCount = + builder->createConvert(loc, builder->getIndexType(), tripCount); + + } else { + auto diff1 = + builder->create(loc, upperValue, lowerValue); + auto diff2 = + builder->create(loc, diff1, info.stepValue); + tripCount = + builder->create(loc, diff2, info.stepValue); + } + if (forceLoopToExecuteOnce) { // minimum tripCount is 1 + mlir::Value one = + builder->createIntegerConstant(loc, tripCount.getType(), 1); + auto cond = builder->create( + loc, mlir::arith::CmpIPredicate::slt, tripCount, one); + tripCount = + builder->create(loc, cond, one, tripCount); + } info.tripVariable = builder->createTemporary(loc, tripCount.getType()); builder->create(loc, tripCount, info.tripVariable); builder->create(loc, lowerValue, info.loopVariable); // Unstructured loop header - generate loop condition and mask. + // Note - Currently there is no way to tag a loop as a concurrent loop. startBlock(info.headerBlock); tripCount = builder->create(loc, info.tripVariable); mlir::Value zero = builder->createIntegerConstant(loc, tripCount.getType(), 0); auto cond = builder->create( loc, mlir::arith::CmpIPredicate::sgt, tripCount, zero); - // TODO: mask expression - genFIRConditionalBranch(cond, info.bodyBlock, info.exitBlock); - if (&info != &incrementLoopNestInfo.back()) // not innermost - startBlock(info.bodyBlock); // preheader block of enclosed dimension + if (info.maskExpr) { + genFIRConditionalBranch(cond, info.maskBlock, info.exitBlock); + startBlock(info.maskBlock); + mlir::Block *latchBlock = getEval().getLastNestedEvaluation().block; + assert(latchBlock && "missing masked concurrent loop latch block"); + Fortran::lower::StatementContext stmtCtx; + mlir::Value maskCond = createFIRExpr(loc, info.maskExpr, stmtCtx); + stmtCtx.finalize(); + genFIRConditionalBranch(maskCond, info.bodyBlock, latchBlock); + } else { + genFIRConditionalBranch(cond, info.bodyBlock, info.exitBlock); + if (&info != &incrementLoopNestInfo.back()) // not innermost + startBlock(info.bodyBlock); // preheader block of enclosed dimension + } + if (!info.localInitSymList.empty()) { + mlir::OpBuilder::InsertPoint insertPt = builder->saveInsertionPoint(); + builder->setInsertionPointToStart(info.bodyBlock); + handleLocalitySpec(info); + builder->restoreInsertionPoint(insertPt); + } } } @@ -1117,7 +1286,12 @@ class FirConverter : public Fortran::lower::AbstractConverter { tripCount = builder->create(loc, tripCount, one); builder->create(loc, tripCount, info.tripVariable); mlir::Value value = builder->create(loc, info.loopVariable); - value = builder->create(loc, value, info.stepValue); + if (info.hasRealControl) + value = + builder->create(loc, value, info.stepValue); + else + value = + builder->create(loc, value, info.stepValue); builder->create(loc, value, info.loopVariable); genFIRBranch(info.headerBlock); @@ -1391,7 +1565,7 @@ class FirConverter : public Fortran::lower::AbstractConverter { } void genFIR(const Fortran::parser::CompilerDirective &) { - TODO(toLocation(), "CompilerDirective lowering"); + mlir::emitWarning(toLocation(), "ignoring all compiler directives"); } void genFIR(const Fortran::parser::OpenACCConstruct &acc) { @@ -2420,6 +2594,10 @@ class FirConverter : public Fortran::lower::AbstractConverter { void instantiateVar(const Fortran::lower::pft::Variable &var, Fortran::lower::AggregateStoreMap &storeMap) { Fortran::lower::instantiateVariable(*this, var, localSymbols, storeMap); + if (var.hasSymbol() && + var.getSymbol().test( + Fortran::semantics::Symbol::Flag::OmpThreadprivate)) + Fortran::lower::genThreadprivateOp(*this, var); } /// Prepare to translate a new function diff --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt index 9309253f178ce..2874084e7e559 100644 --- a/flang/lib/Lower/CMakeLists.txt +++ b/flang/lib/Lower/CMakeLists.txt @@ -41,8 +41,8 @@ add_flang_library(FortranLower FortranEvaluate FortranSemantics MLIRAffineToStandard - MLIRFunc - MLIRLLVMIR + MLIRFuncDialect + MLIRLLVMDialect MLIRSCFToControlFlow LINK_COMPONENTS diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp index 9ff32315cd9a6..faec2916787d4 100644 --- a/flang/lib/Lower/CallInterface.cpp +++ b/flang/lib/Lower/CallInterface.cpp @@ -13,9 +13,9 @@ #include "flang/Lower/PFTBuilder.h" #include "flang/Lower/StatementContext.h" #include "flang/Lower/Support/Utils.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Optimizer/Support/InternalNames.h" diff --git a/flang/lib/Lower/Coarray.cpp b/flang/lib/Lower/Coarray.cpp index 97a420ad78751..b5ab7b51fb00a 100644 --- a/flang/lib/Lower/Coarray.cpp +++ b/flang/lib/Lower/Coarray.cpp @@ -14,8 +14,8 @@ #include "flang/Lower/Coarray.h" #include "flang/Lower/AbstractConverter.h" #include "flang/Lower/SymbolMap.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/expression.h" diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp index 0e196693b393f..660de0b88c02f 100644 --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -30,13 +30,13 @@ #include "flang/Lower/Mangler.h" #include "flang/Lower/Runtime.h" #include "flang/Lower/Support/Utils.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/Complex.h" #include "flang/Optimizer/Builder/Factory.h" #include "flang/Optimizer/Builder/Runtime/Character.h" #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" #include "flang/Optimizer/Builder/Runtime/Ragged.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRAttr.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROpsSupport.h" @@ -822,6 +822,13 @@ class ScalarExprLowering { std::string name = converter.mangleName(*symbol); mlir::func::FuncOp func = Fortran::lower::getOrDeclareFunction(name, proc, converter); + // Abstract results require later rewrite of the function type. + // This currently does not happen inside GloalOps, causing LLVM + // IR verification failure. This helper is only here to catch these + // cases and emit a TODOs for now. + if (inInitializer && fir::hasAbstractResult(func.getFunctionType())) + TODO(converter.genLocation(symbol->name()), + "static description of non trivial procedure bindings"); funcPtr = builder.create(loc, func.getFunctionType(), builder.getSymbolRefAttr(name)); } @@ -839,7 +846,7 @@ class ScalarExprLowering { mlir::Value rawLen = fir::getBase(genval(*lengthExpr)); // F2018 7.4.4.2 point 5. funcPtrResultLength = - Fortran::lower::genMaxWithZero(builder, getLoc(), rawLen); + fir::factory::genMaxWithZero(builder, getLoc(), rawLen); } } if (!funcPtrResultLength) @@ -2223,7 +2230,7 @@ class ScalarExprLowering { type->characterTypeSpec().length().GetExplicit()) { mlir::Value len = fir::getBase(genval(*lenExpr)); // F2018 7.4.4.2 point 5. - len = Fortran::lower::genMaxWithZero(builder, getLoc(), len); + len = fir::factory::genMaxWithZero(builder, getLoc(), len); symMap.addSymbol(*arg, replaceScalarCharacterLength(gen(*expr), len)); continue; @@ -7588,15 +7595,3 @@ void Fortran::lower::createArrayMergeStores( esp.resetBindings(); esp.incrementCounter(); } - -mlir::Value Fortran::lower::genMaxWithZero(fir::FirOpBuilder &builder, - mlir::Location loc, - mlir::Value value) { - mlir::Value zero = builder.createIntegerConstant(loc, value.getType(), 0); - if (mlir::Operation *definingOp = value.getDefiningOp()) - if (auto cst = mlir::dyn_cast(definingOp)) - if (auto intAttr = cst.getValue().dyn_cast()) - return intAttr.getInt() < 0 ? zero : value; - return Fortran::lower::genMax(builder, loc, - llvm::SmallVector{value, zero}); -} diff --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp index 389cb87d297f8..04c073bf8788e 100644 --- a/flang/lib/Lower/ConvertType.cpp +++ b/flang/lib/Lower/ConvertType.cpp @@ -13,7 +13,7 @@ #include "flang/Lower/Mangler.h" #include "flang/Lower/PFTBuilder.h" #include "flang/Lower/Support/Utils.h" -#include "flang/Lower/Todo.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Semantics/tools.h" #include "flang/Semantics/type.h" diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp index 86f7fac38c836..564a9603b05ea 100644 --- a/flang/lib/Lower/ConvertVariable.cpp +++ b/flang/lib/Lower/ConvertVariable.cpp @@ -22,10 +22,10 @@ #include "flang/Lower/StatementContext.h" #include "flang/Lower/Support/Utils.h" #include "flang/Lower/SymbolMap.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Runtime/Derived.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRAttr.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROps.h" @@ -1090,7 +1090,7 @@ static mlir::Value computeExtent(fir::FirOpBuilder &builder, mlir::Location loc, auto diff = builder.create(loc, idxTy, ub, lb); mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); auto rawExtent = builder.create(loc, idxTy, diff, one); - return Fortran::lower::genMaxWithZero(builder, loc, rawExtent); + return fir::factory::genMaxWithZero(builder, loc, rawExtent); } /// Lower explicit lower bounds into \p result. Does nothing if this is not an @@ -1145,7 +1145,7 @@ lowerExplicitExtents(Fortran::lower::AbstractConverter &converter, mlir::Value ub = builder.createConvert( loc, idxTy, genScalarValue(converter, loc, expr, symMap, stmtCtx)); if (lowerBounds.empty()) - result.emplace_back(Fortran::lower::genMaxWithZero(builder, loc, ub)); + result.emplace_back(fir::factory::genMaxWithZero(builder, loc, ub)); else result.emplace_back( computeExtent(builder, loc, lowerBounds[spec.index()], ub)); @@ -1173,7 +1173,7 @@ lowerExplicitCharLen(Fortran::lower::AbstractConverter &converter, if (llvm::Optional lenExpr = box.getCharLenExpr()) // If the length expression is negative, the length is zero. See F2018 // 7.4.4.2 point 5. - return Fortran::lower::genMaxWithZero( + return fir::factory::genMaxWithZero( builder, loc, genScalarValue(converter, loc, *lenExpr, symMap, stmtCtx)); return mlir::Value{}; @@ -1338,7 +1338,7 @@ void Fortran::lower::mapSymbolAttributes( Fortran::lower::SomeExpr highEx{*high}; mlir::Value ub = genValue(highEx); ub = builder.createConvert(loc, idxTy, ub); - shapes.emplace_back(genMaxWithZero(builder, loc, ub)); + shapes.emplace_back(fir::factory::genMaxWithZero(builder, loc, ub)); } else if (spec->ubound().isColon()) { assert(box && "assumed bounds require a descriptor"); mlir::Value dim = @@ -1409,7 +1409,7 @@ void Fortran::lower::mapSymbolAttributes( mlir::Value rawLen = genValue(*charLen); // If the length expression is negative, the length is zero. See // F2018 7.4.4.2 point 5. - return genMaxWithZero(builder, loc, rawLen); + return fir::factory::genMaxWithZero(builder, loc, rawLen); }; ba.match( diff --git a/flang/lib/Lower/CustomIntrinsicCall.cpp b/flang/lib/Lower/CustomIntrinsicCall.cpp index 4e3faa2ea79f5..8ab91ea70f8f5 100644 --- a/flang/lib/Lower/CustomIntrinsicCall.cpp +++ b/flang/lib/Lower/CustomIntrinsicCall.cpp @@ -15,7 +15,7 @@ #include "flang/Evaluate/fold.h" #include "flang/Evaluate/tools.h" #include "flang/Lower/IntrinsicCall.h" -#include "flang/Lower/Todo.h" +#include "flang/Optimizer/Builder/Todo.h" /// Is this a call to MIN or MAX intrinsic with arguments that may be absent at /// runtime? This is a special case because MIN and MAX can have any number of @@ -52,14 +52,14 @@ static bool isIshftcWithDynamicallyOptionalArg( Fortran::evaluate::MayBePassedAsAbsentOptional(*expr, foldingContex); } -/// Is this a call to SYSTEM_CLOCK or RANDOM_SEED intrinsic with arguments that -/// may be absent at runtime? This are special cases because that aspect cannot +/// Is this a call to the RANDOM_SEED intrinsic with arguments that may be +/// absent at runtime? This is a special case because that aspect cannot /// be delegated to the runtime via a null fir.box or address given the current /// runtime entry point. -static bool isSystemClockOrRandomSeedWithOptionalArg( +static bool isRandomSeedWithDynamicallyOptionalArg( llvm::StringRef name, const Fortran::evaluate::ProcedureRef &procRef, Fortran::evaluate::FoldingContext &foldingContex) { - if (name != "system_clock" && name != "random_seed") + if (name != "random_seed") return false; for (const auto &arg : procRef.arguments()) { auto *expr = Fortran::evaluate::UnwrapExpr(arg); @@ -78,7 +78,7 @@ bool Fortran::lower::intrinsicRequiresCustomOptionalHandling( Fortran::evaluate::FoldingContext &fldCtx = converter.getFoldingContext(); return isMinOrMaxWithDynamicallyOptionalArg(name, procRef, fldCtx) || isIshftcWithDynamicallyOptionalArg(name, procRef, fldCtx) || - isSystemClockOrRandomSeedWithOptionalArg(name, procRef, fldCtx); + isRandomSeedWithDynamicallyOptionalArg(name, procRef, fldCtx); } static void prepareMinOrMaxArguments( diff --git a/flang/lib/Lower/HostAssociations.cpp b/flang/lib/Lower/HostAssociations.cpp index 69d4336150c8f..b966b27d8846d 100644 --- a/flang/lib/Lower/HostAssociations.cpp +++ b/flang/lib/Lower/HostAssociations.cpp @@ -15,9 +15,9 @@ #include "flang/Lower/ConvertType.h" #include "flang/Lower/PFTBuilder.h" #include "flang/Lower/SymbolMap.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Support/FatalError.h" #include "flang/Semantics/tools.h" #include "llvm/ADT/TypeSwitch.h" @@ -402,7 +402,7 @@ class CapturedArrays : public CapturedSymbols { if (!fir::isa_ref_type(eleTy)) eleTy = builder.getRefType(eleTy); auto addr = builder.create(loc, eleTy, box); - mlir::Value isPresent = builder.genIsNotNull(loc, addr); + mlir::Value isPresent = builder.genIsNotNullAddr(loc, addr); auto absentBox = builder.create(loc, boxTy); box = builder.create(loc, isPresent, box, absentBox); diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp index b8f704d448f2e..a738f8b87a382 100644 --- a/flang/lib/Lower/IO.cpp +++ b/flang/lib/Lower/IO.cpp @@ -20,12 +20,12 @@ #include "flang/Lower/Runtime.h" #include "flang/Lower/StatementContext.h" #include "flang/Lower/Support/Utils.h" -#include "flang/Lower/Todo.h" #include "flang/Lower/VectorSubscripts.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/Complex.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Support/FIRContext.h" #include "flang/Parser/parse-tree.h" #include "flang/Runtime/io-api.h" diff --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp index 702e0cf849c2f..c061d593d7ce2 100644 --- a/flang/lib/Lower/IntrinsicCall.cpp +++ b/flang/lib/Lower/IntrinsicCall.cpp @@ -19,7 +19,6 @@ #include "flang/Lower/Runtime.h" #include "flang/Lower/StatementContext.h" #include "flang/Lower/SymbolMap.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/Complex.h" #include "flang/Optimizer/Builder/FIRBuilder.h" @@ -32,6 +31,7 @@ #include "flang/Optimizer/Builder/Runtime/Reduction.h" #include "flang/Optimizer/Builder/Runtime/Stop.h" #include "flang/Optimizer/Builder/Runtime/Transformational.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Optimizer/Support/FatalError.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" @@ -2426,7 +2426,8 @@ void IntrinsicLibrary::genGetCommandArgument( fir::runtime::genArgumentValue(builder, loc, number, valBox, errBox); if (isStaticallyPresent(status)) { mlir::Value statAddr = fir::getBase(status); - mlir::Value statIsPresentAtRuntime = builder.genIsNotNull(loc, statAddr); + mlir::Value statIsPresentAtRuntime = + builder.genIsNotNullAddr(loc, statAddr); builder.genIfThen(loc, statIsPresentAtRuntime) .genThen( [&]() { builder.createStoreWithConvert(loc, stat, statAddr); }) @@ -2435,7 +2436,7 @@ void IntrinsicLibrary::genGetCommandArgument( } if (isStaticallyPresent(length)) { mlir::Value lenAddr = fir::getBase(length); - mlir::Value lenIsPresentAtRuntime = builder.genIsNotNull(loc, lenAddr); + mlir::Value lenIsPresentAtRuntime = builder.genIsNotNullAddr(loc, lenAddr); builder.genIfThen(loc, lenIsPresentAtRuntime) .genThen([&]() { mlir::Value len = @@ -2465,7 +2466,7 @@ void IntrinsicLibrary::genGetEnvironmentVariable( mlir::Type i1Ty = builder.getI1Type(); mlir::Value trimNameAddr = fir::getBase(trimName); mlir::Value trimNameIsPresentAtRuntime = - builder.genIsNotNull(loc, trimNameAddr); + builder.genIsNotNullAddr(loc, trimNameAddr); trim = builder .genIfOp(loc, {i1Ty}, trimNameIsPresentAtRuntime, /*withElseRegion=*/true) @@ -2496,7 +2497,8 @@ void IntrinsicLibrary::genGetEnvironmentVariable( valBox, trim, errBox); if (isStaticallyPresent(status)) { mlir::Value statAddr = fir::getBase(status); - mlir::Value statIsPresentAtRuntime = builder.genIsNotNull(loc, statAddr); + mlir::Value statIsPresentAtRuntime = + builder.genIsNotNullAddr(loc, statAddr); builder.genIfThen(loc, statIsPresentAtRuntime) .genThen( [&]() { builder.createStoreWithConvert(loc, stat, statAddr); }) @@ -2506,7 +2508,7 @@ void IntrinsicLibrary::genGetEnvironmentVariable( if (isStaticallyPresent(length)) { mlir::Value lenAddr = fir::getBase(length); - mlir::Value lenIsPresentAtRuntime = builder.genIsNotNull(loc, lenAddr); + mlir::Value lenIsPresentAtRuntime = builder.genIsNotNullAddr(loc, lenAddr); builder.genIfThen(loc, lenIsPresentAtRuntime) .genThen([&]() { mlir::Value len = @@ -3311,7 +3313,7 @@ IntrinsicLibrary::genSize(mlir::Type resultType, return builder.createConvert( loc, resultType, fir::runtime::genSizeDim(builder, loc, array, dim)); - mlir::Value isDynamicallyAbsent = builder.genIsNull(loc, dim); + mlir::Value isDynamicallyAbsent = builder.genIsNullAddr(loc, dim); return builder .genIfOp(loc, {resultType}, isDynamicallyAbsent, /*withElseRegion=*/true) diff --git a/flang/lib/Lower/Mangler.cpp b/flang/lib/Lower/Mangler.cpp index 0f9b55ac749d9..27bef2dd447b0 100644 --- a/flang/lib/Lower/Mangler.cpp +++ b/flang/lib/Lower/Mangler.cpp @@ -9,7 +9,7 @@ #include "flang/Lower/Mangler.h" #include "flang/Common/reference.h" #include "flang/Lower/Support/Utils.h" -#include "flang/Lower/Todo.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Optimizer/Support/InternalNames.h" #include "flang/Semantics/tools.h" diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index 23f999ae73a45..533680e967db2 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -15,9 +15,9 @@ #include "flang/Lower/Bridge.h" #include "flang/Lower/PFTBuilder.h" #include "flang/Lower/StatementContext.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/BoxValue.h" #include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/tools.h" #include "mlir/Dialect/OpenACC/OpenACC.h" diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp index 85a54ebc412ca..bd893aaa6d3df 100644 --- a/flang/lib/Lower/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP.cpp @@ -13,11 +13,12 @@ #include "flang/Lower/OpenMP.h" #include "flang/Common/idioms.h" #include "flang/Lower/Bridge.h" +#include "flang/Lower/ConvertExpr.h" #include "flang/Lower/PFTBuilder.h" #include "flang/Lower/StatementContext.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/BoxValue.h" #include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/tools.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" @@ -43,25 +44,31 @@ getDesignatorNameIfDataRef(const Fortran::parser::Designator &designator) { return dataRef ? std::get_if(&dataRef->u) : nullptr; } +static Fortran::semantics::Symbol * +getOmpObjectSymbol(const Fortran::parser::OmpObject &ompObject) { + Fortran::semantics::Symbol *sym = nullptr; + std::visit(Fortran::common::visitors{ + [&](const Fortran::parser::Designator &designator) { + if (const Fortran::parser::Name *name = + getDesignatorNameIfDataRef(designator)) { + sym = name->symbol; + } + }, + [&](const Fortran::parser::Name &name) { sym = name.symbol; }}, + ompObject.u); + return sym; +} + template static void createPrivateVarSyms(Fortran::lower::AbstractConverter &converter, const T *clause) { - Fortran::semantics::Symbol *sym = nullptr; const Fortran::parser::OmpObjectList &ompObjectList = clause->v; for (const Fortran::parser::OmpObject &ompObject : ompObjectList.v) { - std::visit( - Fortran::common::visitors{ - [&](const Fortran::parser::Designator &designator) { - if (const Fortran::parser::Name *name = - getDesignatorNameIfDataRef(designator)) { - sym = name->symbol; - } - }, - [&](const Fortran::parser::Name &name) { sym = name.symbol; }}, - ompObject.u); - + Fortran::semantics::Symbol *sym = getOmpObjectSymbol(ompObject); // Privatization for symbols which are pre-determined (like loop index - // variables) happen separately, for everything else privatize here + // variables) happen separately, for everything else privatize here. + if (sym->test(Fortran::semantics::Symbol::Flag::OmpPreDetermined)) + continue; if constexpr (std::is_same_v) { converter.copyHostAssociateVar(*sym); } else { @@ -90,6 +97,103 @@ static void privatizeVars(Fortran::lower::AbstractConverter &converter, firOpBuilder.restoreInsertionPoint(insPt); } +/// The COMMON block is a global structure. \p commonValue is the base address +/// of the the COMMON block. As the offset from the symbol \p sym, generate the +/// COMMON block member value (commonValue + offset) for the symbol. +/// FIXME: Share the code with `instantiateCommon` in ConvertVariable.cpp. +static mlir::Value +genCommonBlockMember(Fortran::lower::AbstractConverter &converter, + const Fortran::semantics::Symbol &sym, + mlir::Value commonValue) { + auto &firOpBuilder = converter.getFirOpBuilder(); + mlir::Location currentLocation = converter.getCurrentLocation(); + mlir::IntegerType i8Ty = firOpBuilder.getIntegerType(8); + mlir::Type i8Ptr = firOpBuilder.getRefType(i8Ty); + mlir::Type seqTy = firOpBuilder.getRefType(firOpBuilder.getVarLenSeqTy(i8Ty)); + mlir::Value base = + firOpBuilder.createConvert(currentLocation, seqTy, commonValue); + std::size_t byteOffset = sym.GetUltimate().offset(); + mlir::Value offs = firOpBuilder.createIntegerConstant( + currentLocation, firOpBuilder.getIndexType(), byteOffset); + mlir::Value varAddr = firOpBuilder.create( + currentLocation, i8Ptr, base, mlir::ValueRange{offs}); + mlir::Type symType = converter.genType(sym); + return firOpBuilder.createConvert(currentLocation, + firOpBuilder.getRefType(symType), varAddr); +} + +// Get the extended value for \p val by extracting additional variable +// information from \p base. +static fir::ExtendedValue getExtendedValue(fir::ExtendedValue base, + mlir::Value val) { + return base.match( + [&](const fir::MutableBoxValue &box) -> fir::ExtendedValue { + return fir::MutableBoxValue(val, box.nonDeferredLenParams(), {}); + }, + [&](const auto &) -> fir::ExtendedValue { + return fir::substBase(base, val); + }); +} + +static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter, + Fortran::lower::pft::Evaluation &eval) { + auto &firOpBuilder = converter.getFirOpBuilder(); + mlir::Location currentLocation = converter.getCurrentLocation(); + auto insPt = firOpBuilder.saveInsertionPoint(); + firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock()); + + // Get the original ThreadprivateOp corresponding to the symbol and use the + // symbol value from that opeartion to create one ThreadprivateOp copy + // operation inside the parallel region. + auto genThreadprivateOp = [&](Fortran::lower::SymbolRef sym) -> mlir::Value { + mlir::Value symOriThreadprivateValue = converter.getSymbolAddress(sym); + mlir::Operation *op = symOriThreadprivateValue.getDefiningOp(); + assert(mlir::isa(op) && + "The threadprivate operation not created"); + mlir::Value symValue = + mlir::dyn_cast(op).sym_addr(); + return firOpBuilder.create( + currentLocation, symValue.getType(), symValue); + }; + + llvm::SetVector threadprivateSyms; + converter.collectSymbolSet( + eval, threadprivateSyms, + Fortran::semantics::Symbol::Flag::OmpThreadprivate); + + // For a COMMON block, the ThreadprivateOp is generated for itself instead of + // its members, so only bind the value of the new copied ThreadprivateOp + // inside the parallel region to the common block symbol only once for + // multiple members in one COMMON block. + llvm::SetVector commonSyms; + for (std::size_t i = 0; i < threadprivateSyms.size(); i++) { + auto sym = threadprivateSyms[i]; + mlir::Value symThreadprivateValue; + if (const Fortran::semantics::Symbol *common = + Fortran::semantics::FindCommonBlockContaining(sym->GetUltimate())) { + mlir::Value commonThreadprivateValue; + if (commonSyms.contains(common)) { + commonThreadprivateValue = converter.getSymbolAddress(*common); + } else { + commonThreadprivateValue = genThreadprivateOp(*common); + converter.bindSymbol(*common, commonThreadprivateValue); + commonSyms.insert(common); + } + symThreadprivateValue = + genCommonBlockMember(converter, *sym, commonThreadprivateValue); + } else { + symThreadprivateValue = genThreadprivateOp(*sym); + } + + fir::ExtendedValue sexv = converter.getSymbolExtendedValue(*sym); + fir::ExtendedValue symThreadprivateExv = + getExtendedValue(sexv, symThreadprivateValue); + converter.bindSymbol(*sym, symThreadprivateExv); + } + + firOpBuilder.restoreInsertionPoint(insPt); +} + static void genObjectList(const Fortran::parser::OmpObjectList &objectList, Fortran::lower::AbstractConverter &converter, llvm::SmallVectorImpl &operands) { @@ -106,17 +210,8 @@ static void genObjectList(const Fortran::parser::OmpObjectList &objectList, } }; for (const Fortran::parser::OmpObject &ompObject : objectList.v) { - std::visit(Fortran::common::visitors{ - [&](const Fortran::parser::Designator &designator) { - if (const Fortran::parser::Name *name = - getDesignatorNameIfDataRef(designator)) { - addOperands(*name->symbol); - } - }, - [&](const Fortran::parser::Name &name) { - addOperands(*name.symbol); - }}, - ompObject.u); + Fortran::semantics::Symbol *sym = getOmpObjectSymbol(ompObject); + addOperands(*sym); } } @@ -184,6 +279,7 @@ createBodyOfOp(Op &op, Fortran::lower::AbstractConverter &converter, // argument. Also update the symbol's address with the mlir argument value. // e.g. For loops the argument is the induction variable. And all further // uses of the induction variable should use this mlir value. + mlir::Operation *storeOp = nullptr; if (args.size()) { std::size_t loopVarTypeSize = 0; for (const Fortran::semantics::Symbol *arg : args) @@ -197,14 +293,25 @@ createBodyOfOp(Op &op, Fortran::lower::AbstractConverter &converter, } firOpBuilder.createBlock(&op.getRegion(), {}, tiv, locs); int argIndex = 0; + // The argument is not currently in memory, so make a temporary for the + // argument, and store it there, then bind that location to the argument. for (const Fortran::semantics::Symbol *arg : args) { - fir::ExtendedValue exval = op.getRegion().front().getArgument(argIndex); - converter.bindSymbol(*arg, exval); + mlir::Value val = + fir::getBase(op.getRegion().front().getArgument(argIndex)); + mlir::Value temp = firOpBuilder.createTemporary( + loc, loopVarType, + llvm::ArrayRef{ + Fortran::lower::getAdaptToByRefAttr(firOpBuilder)}); + storeOp = firOpBuilder.create(loc, val, temp); + converter.bindSymbol(*arg, temp); argIndex++; } } else { firOpBuilder.createBlock(&op.getRegion()); } + // Set the insert for the terminator operation to go at the end of the + // block - this is either empty or the block with the stores above, + // the end of the block works for both. mlir::Block &block = op.getRegion().back(); firOpBuilder.setInsertionPointToEnd(&block); @@ -214,19 +321,26 @@ createBodyOfOp(Op &op, Fortran::lower::AbstractConverter &converter, createEmptyRegionBlocks(firOpBuilder, eval.getNestedEvaluations()); // Insert the terminator. - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || + std::is_same_v) { mlir::ValueRange results; firOpBuilder.create(loc, results); } else { firOpBuilder.create(loc); } - // Reset the insertion point to the start of the first block. - firOpBuilder.setInsertionPointToStart(&block); + // Reset the insert point to before the terminator. + if (storeOp) + firOpBuilder.setInsertionPointAfter(storeOp); + else + firOpBuilder.setInsertionPointToStart(&block); // Handle privatization. Do not privatize if this is the outer operation. if (clauses && !outerCombined) privatizeVars(converter, *clauses); + + if (std::is_same_v) + threadPrivatizeVars(converter, eval); } static void genOMP(Fortran::lower::AbstractConverter &converter, @@ -517,6 +631,70 @@ genOMP(Fortran::lower::AbstractConverter &converter, } } +static mlir::omp::ScheduleModifier +translateModifier(const Fortran::parser::OmpScheduleModifierType &m) { + switch (m.v) { + case Fortran::parser::OmpScheduleModifierType::ModType::Monotonic: + return mlir::omp::ScheduleModifier::monotonic; + case Fortran::parser::OmpScheduleModifierType::ModType::Nonmonotonic: + return mlir::omp::ScheduleModifier::nonmonotonic; + case Fortran::parser::OmpScheduleModifierType::ModType::Simd: + return mlir::omp::ScheduleModifier::simd; + } + return mlir::omp::ScheduleModifier::none; +} + +static mlir::omp::ScheduleModifier +getScheduleModifier(const Fortran::parser::OmpScheduleClause &x) { + const auto &modifier = + std::get>(x.t); + // The input may have the modifier any order, so we look for one that isn't + // SIMD. If modifier is not set at all, fall down to the bottom and return + // "none". + if (modifier) { + const auto &modType1 = + std::get(modifier->t); + if (modType1.v.v == + Fortran::parser::OmpScheduleModifierType::ModType::Simd) { + const auto &modType2 = std::get< + std::optional>( + modifier->t); + if (modType2 && + modType2->v.v != + Fortran::parser::OmpScheduleModifierType::ModType::Simd) + return translateModifier(modType2->v); + + return mlir::omp::ScheduleModifier::none; + } + + return translateModifier(modType1.v); + } + return mlir::omp::ScheduleModifier::none; +} + +static mlir::omp::ScheduleModifier +getSIMDModifier(const Fortran::parser::OmpScheduleClause &x) { + const auto &modifier = + std::get>(x.t); + // Either of the two possible modifiers in the input can be the SIMD modifier, + // so look in either one, and return simd if we find one. Not found = return + // "none". + if (modifier) { + const auto &modType1 = + std::get(modifier->t); + if (modType1.v.v == Fortran::parser::OmpScheduleModifierType::ModType::Simd) + return mlir::omp::ScheduleModifier::simd; + + const auto &modType2 = std::get< + std::optional>( + modifier->t); + if (modType2 && modType2->v.v == + Fortran::parser::OmpScheduleModifierType::ModType::Simd) + return mlir::omp::ScheduleModifier::simd; + } + return mlir::omp::ScheduleModifier::none; +} + static void genOMP(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { @@ -528,7 +706,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, mlir::Value scheduleChunkClauseOperand; mlir::Attribute scheduleClauseOperand, collapseClauseOperand, noWaitClauseOperand, orderedClauseOperand, orderClauseOperand; - const auto &wsLoopOpClauseList = std::get( + const auto &loopOpClauseList = std::get( std::get(loopConstruct.t).t); const auto ompDirective = @@ -539,7 +717,8 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, createCombinedParallelOp( converter, eval, std::get(loopConstruct.t)); - } else if (llvm::omp::OMPD_do != ompDirective) { + } else if (llvm::omp::OMPD_do != ompDirective && + llvm::omp::OMPD_simd != ompDirective) { TODO(converter.getCurrentLocation(), "Construct enclosing do loop"); } @@ -547,7 +726,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, auto *doConstructEval = &eval.getFirstNestedEvaluation(); std::int64_t collapseValue = - Fortran::lower::getCollapseValue(wsLoopOpClauseList); + Fortran::lower::getCollapseValue(loopOpClauseList); std::size_t loopVarTypeSize = 0; SmallVector iv; do { @@ -580,7 +759,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, &*std::next(doConstructEval->getNestedEvaluations().begin()); } while (collapseValue > 0); - for (const auto &clause : wsLoopOpClauseList.v) { + for (const auto &clause : loopOpClauseList.v) { if (const auto &scheduleClause = std::get_if(&clause.u)) { if (const auto &chunkExpr = @@ -607,6 +786,17 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, firOpBuilder.createConvert(currentLocation, loopVarType, step[it]); } + // 2.9.3.1 SIMD construct + // TODO: Support all the clauses + if (llvm::omp::OMPD_simd == ompDirective) { + TypeRange resultType; + auto SimdLoopOp = firOpBuilder.create( + currentLocation, resultType, lowerBound, upperBound, step); + createBodyOfOp(SimdLoopOp, converter, currentLocation, + eval, &loopOpClauseList, iv); + return; + } + // FIXME: Add support for following clauses: // 1. linear // 2. order @@ -623,7 +813,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, /*inclusive=*/firOpBuilder.getUnitAttr()); // Handle attribute based clauses. - for (const Fortran::parser::OmpClause &clause : wsLoopOpClauseList.v) { + for (const Fortran::parser::OmpClause &clause : loopOpClauseList.v) { if (const auto &orderedClause = std::get_if(&clause.u)) { if (orderedClause->v.has_value()) { @@ -672,6 +862,14 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, context, omp::ClauseScheduleKind::Runtime)); break; } + mlir::omp::ScheduleModifier scheduleModifier = + getScheduleModifier(scheduleClause->v); + if (scheduleModifier != mlir::omp::ScheduleModifier::none) + wsLoopOp.schedule_modifierAttr( + omp::ScheduleModifierAttr::get(context, scheduleModifier)); + if (getSIMDModifier(scheduleClause->v) != + mlir::omp::ScheduleModifier::none) + wsLoopOp.simd_modifierAttr(firOpBuilder.getUnitAttr()); } } // In FORTRAN `nowait` clause occur at the end of `omp do` directive. @@ -690,7 +888,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, } createBodyOfOp(wsLoopOp, converter, currentLocation, eval, - &wsLoopOpClauseList, iv); + &loopOpClauseList, iv); } static void @@ -977,6 +1175,42 @@ void Fortran::lower::genOpenMPConstruct( ompConstruct.u); } +void Fortran::lower::genThreadprivateOp( + Fortran::lower::AbstractConverter &converter, + const Fortran::lower::pft::Variable &var) { + fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); + mlir::Location currentLocation = converter.getCurrentLocation(); + + const Fortran::semantics::Symbol &sym = var.getSymbol(); + mlir::Value symThreadprivateValue; + if (const Fortran::semantics::Symbol *common = + Fortran::semantics::FindCommonBlockContaining(sym.GetUltimate())) { + mlir::Value commonValue = converter.getSymbolAddress(*common); + if (mlir::isa(commonValue.getDefiningOp())) { + // Generate ThreadprivateOp for a common block instead of its members and + // only do it once for a common block. + return; + } + // Generate ThreadprivateOp and rebind the common block. + mlir::Value commonThreadprivateValue = + firOpBuilder.create( + currentLocation, commonValue.getType(), commonValue); + converter.bindSymbol(*common, commonThreadprivateValue); + // Generate the threadprivate value for the common block member. + symThreadprivateValue = + genCommonBlockMember(converter, sym, commonThreadprivateValue); + } else { + mlir::Value symValue = converter.getSymbolAddress(sym); + symThreadprivateValue = firOpBuilder.create( + currentLocation, symValue.getType(), symValue); + } + + fir::ExtendedValue sexv = converter.getSymbolExtendedValue(sym); + fir::ExtendedValue symThreadprivateExv = + getExtendedValue(sexv, symThreadprivateValue); + converter.bindSymbol(sym, symThreadprivateExv); +} + void Fortran::lower::genOpenMPDeclarativeConstruct( Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval, @@ -1003,7 +1237,8 @@ void Fortran::lower::genOpenMPDeclarativeConstruct( "OpenMPDeclareTargetConstruct"); }, [&](const Fortran::parser::OpenMPThreadprivate &threadprivate) { - TODO(converter.getCurrentLocation(), "OpenMPThreadprivate"); + // The directive is lowered when instantiating the variable to + // support the case of threadprivate variable declared in module. }, }, ompDeclConstruct.u); diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp index 70774425760a6..2e2e024880312 100644 --- a/flang/lib/Lower/PFTBuilder.cpp +++ b/flang/lib/Lower/PFTBuilder.cpp @@ -1768,7 +1768,9 @@ struct SymbolVisitor { template bool Pre(const A &x) { if constexpr (Fortran::parser::HasTypedExpr::value) - if (const auto *expr = Fortran::semantics::GetExpr(x)) + // Some parse tree Expr may legitimately be un-analyzed after semantics + // (for instance PDT component initial value in the PDT definition body). + if (const auto *expr = Fortran::semantics::GetExpr(nullptr, x)) visitExpr(*expr); return true; } @@ -1809,3 +1811,12 @@ void Fortran::lower::pft::visitAllSymbols( parser::Walk(functionParserNode, visitor); }); } + +void Fortran::lower::pft::visitAllSymbols( + const Fortran::lower::pft::Evaluation &eval, + const std::function callBack) { + SymbolVisitor visitor{callBack}; + eval.visit([&](const auto &functionParserNode) { + parser::Walk(functionParserNode, visitor); + }); +} diff --git a/flang/lib/Lower/Runtime.cpp b/flang/lib/Lower/Runtime.cpp index a6ccaa61aaa93..04d7e984a2e43 100644 --- a/flang/lib/Lower/Runtime.cpp +++ b/flang/lib/Lower/Runtime.cpp @@ -9,9 +9,10 @@ #include "flang/Lower/Runtime.h" #include "flang/Lower/Bridge.h" #include "flang/Lower/StatementContext.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" +#include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Parser/parse-tree.h" #include "flang/Runtime/misc-intrinsic.h" #include "flang/Runtime/pointer.h" @@ -332,18 +333,35 @@ void Fortran::lower::genSystemClock(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value count, mlir::Value rate, mlir::Value max) { auto makeCall = [&](mlir::func::FuncOp func, mlir::Value arg) { + mlir::Type type = arg.getType(); + fir::IfOp ifOp{}; + const bool isOptionalArg = + fir::valueHasFirAttribute(arg, fir::getOptionalAttrName()); + if (type.dyn_cast() || type.dyn_cast()) { + // Check for a disassociated pointer or an unallocated allocatable. + assert(!isOptionalArg && "invalid optional argument"); + ifOp = builder.create(loc, builder.genIsNotNullAddr(loc, arg), + /*withElseRegion=*/false); + } else if (isOptionalArg) { + ifOp = builder.create( + loc, builder.create(loc, builder.getI1Type(), arg), + /*withElseRegion=*/false); + } + if (ifOp) + builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); mlir::Type kindTy = func.getFunctionType().getInput(0); int integerKind = 8; - if (auto intType = - fir::unwrapRefType(arg.getType()).dyn_cast()) + if (auto intType = fir::unwrapRefType(type).dyn_cast()) integerKind = intType.getWidth() / 8; mlir::Value kind = builder.createIntegerConstant(loc, kindTy, integerKind); mlir::Value res = builder.create(loc, func, mlir::ValueRange{kind}) .getResult(0); mlir::Value castRes = - builder.createConvert(loc, fir::dyn_cast_ptrEleTy(arg.getType()), res); + builder.createConvert(loc, fir::dyn_cast_ptrEleTy(type), res); builder.create(loc, castRes, arg); + if (ifOp) + builder.setInsertionPointAfter(ifOp); }; using fir::runtime::getRuntimeFunc; if (count) diff --git a/flang/lib/Lower/VectorSubscripts.cpp b/flang/lib/Lower/VectorSubscripts.cpp index e4a7fdd7f0180..77ddc300d6418 100644 --- a/flang/lib/Lower/VectorSubscripts.cpp +++ b/flang/lib/Lower/VectorSubscripts.cpp @@ -13,10 +13,10 @@ #include "flang/Lower/VectorSubscripts.h" #include "flang/Lower/AbstractConverter.h" #include "flang/Lower/Support/Utils.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/Complex.h" #include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Semantics/expression.h" namespace { diff --git a/flang/lib/Optimizer/Builder/BoxValue.cpp b/flang/lib/Optimizer/Builder/BoxValue.cpp index 52c7fea058c11..cd7006788de38 100644 --- a/flang/lib/Optimizer/Builder/BoxValue.cpp +++ b/flang/lib/Optimizer/Builder/BoxValue.cpp @@ -12,6 +12,7 @@ #include "flang/Optimizer/Builder/BoxValue.h" #include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "mlir/IR/BuiltinTypes.h" #include "llvm/Support/Debug.h" @@ -42,7 +43,8 @@ fir::ExtendedValue fir::substBase(const fir::ExtendedValue &exv, [=](const auto &x) { return fir::ExtendedValue(x.clone(base)); }); } -llvm::SmallVector fir::getTypeParams(const ExtendedValue &exv) { +llvm::SmallVector +fir::getTypeParams(const fir::ExtendedValue &exv) { using RT = llvm::SmallVector; auto baseTy = fir::getBase(exv).getType(); if (auto t = fir::dyn_cast_ptrEleTy(baseTy)) @@ -55,15 +57,13 @@ llvm::SmallVector fir::getTypeParams(const ExtendedValue &exv) { [](const fir::CharBoxValue &x) -> RT { return {x.getLen()}; }, [](const fir::CharArrayBoxValue &x) -> RT { return {x.getLen()}; }, [&](const fir::BoxValue &) -> RT { - LLVM_DEBUG(mlir::emitWarning( - loc, "TODO: box value is missing type parameters")); + TODO(loc, "box value is missing type parameters"); return {}; }, [&](const fir::MutableBoxValue &) -> RT { // In this case, the type params may be bound to the variable in an // ALLOCATE statement as part of a type-spec. - LLVM_DEBUG(mlir::emitWarning( - loc, "TODO: mutable box value is missing type parameters")); + TODO(loc, "mutable box value is missing type parameters"); return {}; }, [](const auto &) -> RT { return {}; }); diff --git a/flang/lib/Optimizer/Builder/Character.cpp b/flang/lib/Optimizer/Builder/Character.cpp index c025270cf83ea..ba5b18e762e06 100644 --- a/flang/lib/Optimizer/Builder/Character.cpp +++ b/flang/lib/Optimizer/Builder/Character.cpp @@ -11,9 +11,9 @@ //===----------------------------------------------------------------------===// #include "flang/Optimizer/Builder/Character.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/DoLoopHelper.h" #include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "llvm/Support/Debug.h" #include diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp index 6f62b5413ccdf..f12d543999603 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -7,12 +7,12 @@ //===----------------------------------------------------------------------===// #include "flang/Optimizer/Builder/FIRBuilder.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/BoxValue.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/Complex.h" #include "flang/Optimizer/Builder/MutableBox.h" #include "flang/Optimizer/Builder/Runtime/Assign.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRAttr.h" #include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Optimizer/Support/FatalError.h" @@ -510,13 +510,14 @@ genNullPointerComparison(fir::FirOpBuilder &builder, mlir::Location loc, return builder.create(loc, condition, ptrToInt, c0); } -mlir::Value fir::FirOpBuilder::genIsNotNull(mlir::Location loc, - mlir::Value addr) { +mlir::Value fir::FirOpBuilder::genIsNotNullAddr(mlir::Location loc, + mlir::Value addr) { return genNullPointerComparison(*this, loc, addr, mlir::arith::CmpIPredicate::ne); } -mlir::Value fir::FirOpBuilder::genIsNull(mlir::Location loc, mlir::Value addr) { +mlir::Value fir::FirOpBuilder::genIsNullAddr(mlir::Location loc, + mlir::Value addr) { return genNullPointerComparison(*this, loc, addr, mlir::arith::CmpIPredicate::eq); } @@ -1005,21 +1006,30 @@ static void genComponentByComponentAssignment(fir::FirOpBuilder &builder, mlir::Location loc, const fir::ExtendedValue &lhs, const fir::ExtendedValue &rhs) { - auto baseType = fir::unwrapPassByRefType(fir::getBase(lhs).getType()); - auto lhsType = baseType.dyn_cast(); + auto lbaseType = fir::unwrapPassByRefType(fir::getBase(lhs).getType()); + auto lhsType = lbaseType.dyn_cast(); assert(lhsType && "lhs must be a scalar record type"); + auto rbaseType = fir::unwrapPassByRefType(fir::getBase(rhs).getType()); + auto rhsType = rbaseType.dyn_cast(); + assert(rhsType && "rhs must be a scalar record type"); auto fieldIndexType = fir::FieldType::get(lhsType.getContext()); - for (auto [fieldName, fieldType] : lhsType.getTypeList()) { - assert(!fir::hasDynamicSize(fieldType)); - mlir::Value field = builder.create( - loc, fieldIndexType, fieldName, lhsType, fir::getTypeParams(lhs)); - auto fieldRefType = builder.getRefType(fieldType); + for (auto [lhsPair, rhsPair] : + llvm::zip(lhsType.getTypeList(), rhsType.getTypeList())) { + auto &[lFieldName, lFieldTy] = lhsPair; + auto &[rFieldName, rFieldTy] = rhsPair; + assert(!fir::hasDynamicSize(lFieldTy) && !fir::hasDynamicSize(rFieldTy)); + mlir::Value rField = builder.create( + loc, fieldIndexType, rFieldName, rhsType, fir::getTypeParams(rhs)); + auto rFieldRefType = builder.getRefType(rFieldTy); mlir::Value fromCoor = builder.create( - loc, fieldRefType, fir::getBase(rhs), field); + loc, rFieldRefType, fir::getBase(rhs), rField); + mlir::Value field = builder.create( + loc, fieldIndexType, lFieldName, lhsType, fir::getTypeParams(lhs)); + auto fieldRefType = builder.getRefType(lFieldTy); mlir::Value toCoor = builder.create( loc, fieldRefType, fir::getBase(lhs), field); llvm::Optional outerLoop; - if (auto sequenceType = fieldType.dyn_cast()) { + if (auto sequenceType = lFieldTy.dyn_cast()) { // Create loops to assign array components elements by elements. // Note that, since these are components, they either do not overlap, // or are the same and exactly overlap. They also have compile time @@ -1045,14 +1055,14 @@ static void genComponentByComponentAssignment(fir::FirOpBuilder &builder, fromCoor = builder.create(loc, elementRefType, fromCoor, indices); } - auto fieldElementType = fir::unwrapSequenceType(fieldType); - if (fieldElementType.isa()) { - assert(fieldElementType.cast() - .getEleTy() - .isa() && - "allocatable require deep copy"); + if (auto fieldEleTy = fir::unwrapSequenceType(lFieldTy); + fieldEleTy.isa()) { + assert( + fieldEleTy.cast().getEleTy().isa() && + "allocatable members require deep copy"); auto fromPointerValue = builder.create(loc, fromCoor); - builder.create(loc, fromPointerValue, toCoor); + auto castTo = builder.createConvert(loc, fieldEleTy, fromPointerValue); + builder.create(loc, castTo, toCoor); } else { auto from = fir::factory::componentToExtendedValue(builder, loc, fromCoor); @@ -1216,3 +1226,17 @@ llvm::Optional fir::factory::getIntIfConstant(mlir::Value value) { return intAttr.getInt(); return {}; } + +mlir::Value fir::factory::genMaxWithZero(fir::FirOpBuilder &builder, + mlir::Location loc, + mlir::Value value) { + mlir::Value zero = builder.createIntegerConstant(loc, value.getType(), 0); + if (mlir::Operation *definingOp = value.getDefiningOp()) + if (auto cst = mlir::dyn_cast(definingOp)) + if (auto intAttr = cst.getValue().dyn_cast()) + return intAttr.getInt() > 0 ? value : zero; + mlir::Value valueIsGreater = builder.create( + loc, mlir::arith::CmpIPredicate::sgt, value, zero); + return builder.create(loc, valueIsGreater, value, + zero); +} diff --git a/flang/lib/Optimizer/Builder/LowLevelIntrinsics.cpp b/flang/lib/Optimizer/Builder/LowLevelIntrinsics.cpp index d6d5efb43b381..e7335aa194f01 100644 --- a/flang/lib/Optimizer/Builder/LowLevelIntrinsics.cpp +++ b/flang/lib/Optimizer/Builder/LowLevelIntrinsics.cpp @@ -28,7 +28,7 @@ mlir::func::FuncOp fir::factory::getLlvmMemcpy(fir::FirOpBuilder &builder) { auto memcpyTy = mlir::FunctionType::get(builder.getContext(), args, llvm::None); return builder.addNamedFunction(builder.getUnknownLoc(), - "llvm.memcpy.p0i8.p0i8.i64", memcpyTy); + "llvm.memcpy.p0.p0.i64", memcpyTy); } mlir::func::FuncOp fir::factory::getLlvmMemmove(fir::FirOpBuilder &builder) { @@ -38,7 +38,7 @@ mlir::func::FuncOp fir::factory::getLlvmMemmove(fir::FirOpBuilder &builder) { auto memmoveTy = mlir::FunctionType::get(builder.getContext(), args, llvm::None); return builder.addNamedFunction(builder.getUnknownLoc(), - "llvm.memmove.p0i8.p0i8.i64", memmoveTy); + "llvm.memmove.p0.p0.i64", memmoveTy); } mlir::func::FuncOp fir::factory::getLlvmMemset(fir::FirOpBuilder &builder) { @@ -48,7 +48,7 @@ mlir::func::FuncOp fir::factory::getLlvmMemset(fir::FirOpBuilder &builder) { auto memsetTy = mlir::FunctionType::get(builder.getContext(), args, llvm::None); return builder.addNamedFunction(builder.getUnknownLoc(), - "llvm.memset.p0i8.p0i8.i64", memsetTy); + "llvm.memset.p0.p0.i64", memsetTy); } mlir::func::FuncOp fir::factory::getRealloc(fir::FirOpBuilder &builder) { diff --git a/flang/lib/Optimizer/Builder/MutableBox.cpp b/flang/lib/Optimizer/Builder/MutableBox.cpp index c3eea0b59ab05..6d7eb2952fcdd 100644 --- a/flang/lib/Optimizer/Builder/MutableBox.cpp +++ b/flang/lib/Optimizer/Builder/MutableBox.cpp @@ -11,11 +11,11 @@ //===----------------------------------------------------------------------===// #include "flang/Optimizer/Builder/MutableBox.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Runtime/Derived.h" #include "flang/Optimizer/Builder/Runtime/Stop.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Optimizer/Support/FatalError.h" @@ -427,7 +427,7 @@ fir::factory::genIsAllocatedOrAssociatedTest(fir::FirOpBuilder &builder, mlir::Location loc, const fir::MutableBoxValue &box) { auto addr = MutablePropertyReader(builder, loc, box).readBaseAddress(); - return builder.genIsNotNull(loc, addr); + return builder.genIsNotNullAddr(loc, addr); } /// Generate finalizer call and inlined free. This does not check that the @@ -447,7 +447,7 @@ void fir::factory::genFinalization(fir::FirOpBuilder &builder, mlir::Location loc, const fir::MutableBoxValue &box) { auto addr = MutablePropertyReader(builder, loc, box).readBaseAddress(); - auto isAllocated = builder.genIsNotNull(loc, addr); + auto isAllocated = builder.genIsNotNullAddr(loc, addr); auto ifOp = builder.create(loc, isAllocated, /*withElseRegion=*/false); auto insPt = builder.saveInsertionPoint(); @@ -640,14 +640,17 @@ getNewLengths(fir::FirOpBuilder &builder, mlir::Location loc, auto idxTy = builder.getIndexType(); if (auto charTy = box.getEleTy().dyn_cast()) { if (charTy.getLen() == fir::CharacterType::unknownLen()) { - if (box.hasNonDeferredLenParams()) + if (box.hasNonDeferredLenParams()) { lengths.emplace_back( builder.createConvert(loc, idxTy, box.nonDeferredLenParams()[0])); - else if (!lenParams.empty()) - lengths.emplace_back(builder.createConvert(loc, idxTy, lenParams[0])); - else + } else if (!lenParams.empty()) { + mlir::Value len = + fir::factory::genMaxWithZero(builder, loc, lenParams[0]); + lengths.emplace_back(builder.createConvert(loc, idxTy, len)); + } else { fir::emitFatalError( loc, "could not deduce character lengths in character allocation"); + } } } return lengths; @@ -682,10 +685,13 @@ void fir::factory::genInlinedAllocation(fir::FirOpBuilder &builder, mlir::ValueRange lenParams, llvm::StringRef allocName) { auto lengths = getNewLengths(builder, loc, box, lenParams); + llvm::SmallVector safeExtents; + for (mlir::Value extent : extents) + safeExtents.push_back(fir::factory::genMaxWithZero(builder, loc, extent)); auto heap = builder.create(loc, box.getBaseTy(), allocName, - lengths, extents); - MutablePropertyWriter{builder, loc, box}.updateMutableBox(heap, lbounds, - extents, lengths); + lengths, safeExtents); + MutablePropertyWriter{builder, loc, box}.updateMutableBox( + heap, lbounds, safeExtents, lengths); if (box.getEleTy().isa()) { // TODO: skip runtime initialization if this is not required. Currently, // there is no way to know here if a derived type needs it or not. But the @@ -714,7 +720,7 @@ fir::factory::genReallocIfNeeded(fir::FirOpBuilder &builder, mlir::Location loc, auto addr = reader.readBaseAddress(); auto i1Type = builder.getI1Type(); auto addrType = addr.getType(); - auto isAllocated = builder.genIsNotNull(loc, addr); + auto isAllocated = builder.genIsNotNullAddr(loc, addr); auto ifOp = builder .genIfOp(loc, {i1Type, addrType}, isAllocated, diff --git a/flang/lib/Optimizer/Builder/Runtime/Character.cpp b/flang/lib/Optimizer/Builder/Runtime/Character.cpp index 947201c615f4a..f3663439fdd59 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Character.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Character.cpp @@ -7,11 +7,11 @@ //===----------------------------------------------------------------------===// #include "flang/Optimizer/Builder/Runtime/Character.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/BoxValue.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Runtime/character.h" #include "mlir/Dialect/Func/IR/FuncOps.h" diff --git a/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp b/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp index dc7ca80278f15..f8f88a8a31ffc 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp @@ -11,6 +11,7 @@ #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Runtime/numeric.h" #include "mlir/Dialect/Func/IR/FuncOps.h" @@ -212,7 +213,9 @@ mlir::Value fir::runtime::genExponent(fir::FirOpBuilder &builder, mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - if (fltTy.isF32()) { + if (fltTy.isF16()) { + TODO(loc, "support for REAL with KIND = 2 in EXPONENT"); + } else if (fltTy.isF32()) { if (resultType.isInteger(32)) func = fir::runtime::getRuntimeFunc(loc, builder); else if (resultType.isInteger(64)) @@ -233,7 +236,7 @@ mlir::Value fir::runtime::genExponent(fir::FirOpBuilder &builder, else if (resultType.isInteger(64)) func = fir::runtime::getRuntimeFunc(loc, builder); } else - fir::emitFatalError(loc, "unsupported real kind in Exponent lowering"); + fir::emitFatalError(loc, "unsupported REAL KIND in EXPONENT"); auto funcTy = func.getFunctionType(); llvm::SmallVector args = { @@ -247,8 +250,9 @@ mlir::Value fir::runtime::genFraction(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value x) { mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - - if (fltTy.isF32()) + if (fltTy.isF16()) + TODO(loc, "support for REAL with KIND = 2 in FRACTION"); + else if (fltTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -257,7 +261,7 @@ mlir::Value fir::runtime::genFraction(fir::FirOpBuilder &builder, else if (fltTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "unsupported real kind in Fraction lowering"); + fir::emitFatalError(loc, "unsupported real kind in FRACTION"); auto funcTy = func.getFunctionType(); llvm::SmallVector args = { @@ -273,7 +277,9 @@ mlir::Value fir::runtime::genNearest(fir::FirOpBuilder &builder, mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - if (fltTy.isF32()) + if (fltTy.isF16()) + TODO(loc, "support for REAL with KIND = 2 in NEAREST"); + else if (fltTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -282,7 +288,7 @@ mlir::Value fir::runtime::genNearest(fir::FirOpBuilder &builder, else if (fltTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "unsupported REAL kind in Nearest lowering"); + fir::emitFatalError(loc, "unsupported REAL kind in NEAREST"); auto funcTy = func.getFunctionType(); @@ -308,7 +314,9 @@ mlir::Value fir::runtime::genRRSpacing(fir::FirOpBuilder &builder, mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - if (fltTy.isF32()) + if (fltTy.isF16()) + TODO(loc, "support for REAL with KIND = 2 in RRSPACING"); + else if (fltTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -317,7 +325,7 @@ mlir::Value fir::runtime::genRRSpacing(fir::FirOpBuilder &builder, else if (fltTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "unsupported real kind in RRSpacing lowering"); + fir::emitFatalError(loc, "unsupported real kind in RRSPACING"); auto funcTy = func.getFunctionType(); llvm::SmallVector args = { @@ -333,7 +341,9 @@ mlir::Value fir::runtime::genScale(fir::FirOpBuilder &builder, mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - if (fltTy.isF32()) + if (fltTy.isF16()) + TODO(loc, "support for REAL with KIND = 2 in SCALE"); + else if (fltTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -342,7 +352,7 @@ mlir::Value fir::runtime::genScale(fir::FirOpBuilder &builder, else if (fltTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "unsupported REAL kind in Scale lowering"); + fir::emitFatalError(loc, "unsupported REAL kind in SCALE"); auto funcTy = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, funcTy, x, i); @@ -357,7 +367,9 @@ mlir::Value fir::runtime::genSetExponent(fir::FirOpBuilder &builder, mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - if (fltTy.isF32()) + if (fltTy.isF16()) + TODO(loc, "support for REAL with KIND = 2 in FRACTION"); + else if (fltTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -366,7 +378,7 @@ mlir::Value fir::runtime::genSetExponent(fir::FirOpBuilder &builder, else if (fltTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "unsupported real kind in Fraction lowering"); + fir::emitFatalError(loc, "unsupported real kind in FRACTION"); auto funcTy = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, funcTy, x, i); @@ -380,7 +392,9 @@ mlir::Value fir::runtime::genSpacing(fir::FirOpBuilder &builder, mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - if (fltTy.isF32()) + if (fltTy.isF16()) + TODO(loc, "support for REAL with KIND = 2 in SPACING"); + else if (fltTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -389,7 +403,7 @@ mlir::Value fir::runtime::genSpacing(fir::FirOpBuilder &builder, else if (fltTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "unsupported real kind in Spacing lowering"); + fir::emitFatalError(loc, "unsupported real kind in SPACING"); auto funcTy = func.getFunctionType(); llvm::SmallVector args = { diff --git a/flang/lib/Optimizer/Builder/Runtime/Ragged.cpp b/flang/lib/Optimizer/Builder/Runtime/Ragged.cpp index dc51bfa2b00ab..4d33282a35d9d 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Ragged.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Ragged.cpp @@ -35,7 +35,7 @@ void fir::runtime::genRaggedArrayAllocate(mlir::Location loc, auto ptrTy = builder.getRefType(eleTy.cast().getType(1)); auto ptr = builder.create(loc, ptrTy, header, one); auto heap = builder.create(loc, ptr); - auto cmp = builder.genIsNull(loc, heap); + auto cmp = builder.genIsNullAddr(loc, heap); builder.genIfThen(loc, cmp) .genThen([&]() { auto asHeadersVal = builder.createIntegerConstant(loc, i1Ty, asHeaders); diff --git a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp index 8b98228ac7039..579020acb8da5 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp @@ -7,11 +7,11 @@ //===----------------------------------------------------------------------===// #include "flang/Optimizer/Builder/Runtime/Reduction.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/BoxValue.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Runtime/reduction.h" #include "mlir/Dialect/Func/IR/FuncOps.h" @@ -545,7 +545,9 @@ mlir::Value fir::runtime::genMaxval(fir::FirOpBuilder &builder, auto eleTy = arrTy.cast().getEleTy(); auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); - if (eleTy.isF32()) + if (eleTy.isF16() || eleTy.isBF16()) + TODO(loc, "half-precision MAXVAL"); + else if (eleTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -553,23 +555,18 @@ mlir::Value fir::runtime::genMaxval(fir::FirOpBuilder &builder, func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(1))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(2))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(4))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(8))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(16))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "invalid type in Maxval lowering"); + fir::emitFatalError(loc, "invalid type in MAXVAL"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); @@ -664,7 +661,9 @@ mlir::Value fir::runtime::genMinval(fir::FirOpBuilder &builder, auto eleTy = arrTy.cast().getEleTy(); auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); - if (eleTy.isF32()) + if (eleTy.isF16() || eleTy.isBF16()) + TODO(loc, "half-precision MINVAL"); + else if (eleTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -672,23 +671,18 @@ mlir::Value fir::runtime::genMinval(fir::FirOpBuilder &builder, func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(1))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(2))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(4))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(8))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(16))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "invalid type in Minval lowering"); + fir::emitFatalError(loc, "invalid type in MINVAL"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); @@ -721,7 +715,9 @@ mlir::Value fir::runtime::genProduct(fir::FirOpBuilder &builder, auto eleTy = arrTy.cast().getEleTy(); auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); - if (eleTy.isF32()) + if (eleTy.isF16() || eleTy.isBF16()) + TODO(loc, "half-precision PRODUCT"); + else if (eleTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -729,20 +725,15 @@ mlir::Value fir::runtime::genProduct(fir::FirOpBuilder &builder, func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(1))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(2))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(4))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(8))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(16))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy == fir::ComplexType::get(builder.getContext(), 4)) func = @@ -754,8 +745,11 @@ mlir::Value fir::runtime::genProduct(fir::FirOpBuilder &builder, func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy == fir::ComplexType::get(builder.getContext(), 16)) func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy == fir::ComplexType::get(builder.getContext(), 2) || + eleTy == fir::ComplexType::get(builder.getContext(), 3)) + TODO(loc, "half-precision PRODUCT"); else - fir::emitFatalError(loc, "invalid type in Product lowering"); + fir::emitFatalError(loc, "invalid type in PRODUCT"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); @@ -788,7 +782,9 @@ mlir::Value fir::runtime::genDotProduct(fir::FirOpBuilder &builder, auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty); auto eleTy = arrTy.cast().getEleTy(); - if (eleTy.isF32()) + if (eleTy.isF16() || eleTy.isBF16()) + TODO(loc, "half-precision DOTPRODUCT"); + else if (eleTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -808,31 +804,29 @@ mlir::Value fir::runtime::genDotProduct(fir::FirOpBuilder &builder, else if (eleTy == fir::ComplexType::get(builder.getContext(), 16)) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(1))) + else if (eleTy == fir::ComplexType::get(builder.getContext(), 2) || + eleTy == fir::ComplexType::get(builder.getContext(), 3)) + TODO(loc, "half-precision DOTPRODUCT"); + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(2))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(4))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(8))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(16))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isa()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "invalid type in DotProduct lowering"); + fir::emitFatalError(loc, "invalid type in DOTPRODUCT"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); @@ -873,7 +867,9 @@ mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc, auto eleTy = arrTy.cast().getEleTy(); auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); - if (eleTy.isF32()) + if (eleTy.isF16() || eleTy.isBF16()) + TODO(loc, "half-precision SUM"); + else if (eleTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -881,20 +877,15 @@ mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc, func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(1))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(2))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(4))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(8))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == - builder.getIntegerType(builder.getKindMap().getIntegerBitsize(16))) + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy == fir::ComplexType::get(builder.getContext(), 4)) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -904,8 +895,11 @@ mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc, func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy == fir::ComplexType::get(builder.getContext(), 16)) func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy == fir::ComplexType::get(builder.getContext(), 2) || + eleTy == fir::ComplexType::get(builder.getContext(), 3)) + TODO(loc, "half-precision SUM"); else - fir::emitFatalError(loc, "invalid type in Sum lowering"); + fir::emitFatalError(loc, "invalid type in SUM"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); diff --git a/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp b/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp index 24a0e4b930dd0..0b8e14555d1da 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp @@ -8,11 +8,11 @@ //===----------------------------------------------------------------------===// #include "flang/Optimizer/Builder/Runtime/Transformational.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/BoxValue.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Runtime/matmul.h" #include "flang/Runtime/transformational.h" #include "mlir/Dialect/Func/IR/FuncOps.h" diff --git a/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp b/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp index b10079c9e13a4..1bc490aade3af 100644 --- a/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp +++ b/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp @@ -62,12 +62,12 @@ class BoxprocTypeRewriter : public mlir::TypeConverter { return false; } if (auto recTy = ty.dyn_cast()) { + if (llvm::any_of(visitedTypes, + [&](mlir::Type rt) { return rt == recTy; })) + return false; bool result = false; visitedTypes.push_back(recTy); for (auto t : recTy.getTypeList()) { - if (llvm::any_of(visitedTypes, - [&](mlir::Type rt) { return rt == recTy; })) - continue; if (needsConversion(t.second)) { result = true; break; @@ -85,9 +85,10 @@ class BoxprocTypeRewriter : public mlir::TypeConverter { return false; } - BoxprocTypeRewriter() { + BoxprocTypeRewriter(mlir::Location location) : loc{location} { addConversion([](mlir::Type ty) { return ty; }); - addConversion([](BoxProcType boxproc) { return boxproc.getEleTy(); }); + addConversion( + [&](BoxProcType boxproc) { return convertType(boxproc.getEleTy()); }); addConversion([&](mlir::TupleType tupTy) { llvm::SmallVector memTys; for (auto ty : tupTy.getTypes()) @@ -117,14 +118,21 @@ class BoxprocTypeRewriter : public mlir::TypeConverter { // TODO: add ty.getLayoutMap() as needed. return SequenceType::get(ty.getShape(), convertType(ty.getEleTy())); }); - addConversion([&](RecordType ty) { + addConversion([&](RecordType ty) -> mlir::Type { + if (!needsConversion(ty)) + return ty; // FIR record types can have recursive references, so conversion is a bit // more complex than the other types. This conversion is not needed // presently, so just emit a TODO message. Need to consider the uniqued - // name of the record, etc. + // name of the record, etc. Also, fir::RecordType::get returns the + // existing type being translated. So finalize() will not change it, and + // the translation would not do anything. So the type needs to be mutated, + // and this might require special care to comply with MLIR infrastructure. + + // TODO: this will be needed to support derived type containing procedure + // pointer components. fir::emitFatalError( - mlir::UnknownLoc::get(ty.getContext()), - "not yet implemented: record type with a boxproc type"); + loc, "not yet implemented: record type with a boxproc type"); return RecordType::get(ty.getContext(), "*fixme*"); }); addArgumentMaterialization(materializeProcedure); @@ -141,8 +149,11 @@ class BoxprocTypeRewriter : public mlir::TypeConverter { inputs[0]); } + void setLocation(mlir::Location location) { loc = location; } + private: llvm::SmallVector visitedTypes; + mlir::Location loc; }; /// A `boxproc` is an abstraction for a Fortran procedure reference. Typically, @@ -170,9 +181,10 @@ class BoxedProcedurePass : public BoxedProcedurePassBase { if (options.useThunks) { auto *context = &getContext(); mlir::IRRewriter rewriter(context); - BoxprocTypeRewriter typeConverter; + BoxprocTypeRewriter typeConverter(mlir::UnknownLoc::get(context)); mlir::Dialect *firDialect = context->getLoadedDialect("fir"); getModule().walk([&](mlir::Operation *op) { + typeConverter.setLocation(op->getLoc()); if (auto addr = mlir::dyn_cast(op)) { auto ty = addr.getVal().getType(); if (typeConverter.needsConversion(ty) || diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index edc0b33fa2d02..c5c14414041ad 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -246,7 +246,7 @@ class FIROpConversion : public mlir::ConvertOpToLLVMPattern { mlir::LLVM::GEPOp genGEP(mlir::Location loc, mlir::Type ty, mlir::ConversionPatternRewriter &rewriter, mlir::Value base, ARGS... args) const { - llvm::SmallVector cv{args...}; + llvm::SmallVector cv = {args...}; return rewriter.create(loc, ty, base, cv); } @@ -275,8 +275,10 @@ class FIROpAndTypeConversion : public FIROpConversion { doRewrite(FromOp addr, mlir::Type ty, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const = 0; }; +} // namespace -// Lower `fir.address_of` operation to `llvm.address_of` operation. +namespace { +/// Lower `fir.address_of` operation to `llvm.address_of` operation. struct AddrOfOpConversion : public FIROpConversion { using FIROpConversion::FIROpConversion; @@ -299,7 +301,9 @@ getDependentTypeMemSizeFn(fir::RecordType recTy, fir::AllocaOp op, mlir::ConversionPatternRewriter &rewriter) { auto module = op->getParentOfType(); std::string name = recTy.getName().str() + "P.mem.size"; - return module.lookupSymbol(name); + if (auto memSizeFunc = module.lookupSymbol(name)) + return memSizeFunc; + TODO(op.getLoc(), "did not find allocation function"); } // Compute the alloc scale size (constant factors encoded in the array type). @@ -366,8 +370,7 @@ struct AllocaOpConversion : public FIROpConversion { auto call = rewriter.create( loc, ity, lenParams, llvm::ArrayRef{attr}); size = call.getResult(0); - ty = mlir::LLVM::LLVMPointerType::get( - mlir::IntegerType::get(alloc.getContext(), 8)); + ty = ::getVoidPtrType(alloc.getContext()); } else { return emitError(loc, "unexpected type ") << scalarType << " with type parameters"; @@ -637,7 +640,7 @@ struct StringLitOpConversion : public FIROpConversion { } }; -// `fir.call` -> `llvm.call` +/// `fir.call` -> `llvm.call` struct CallOpConversion : public FIROpConversion { using FIROpConversion::FIROpConversion; @@ -678,7 +681,7 @@ struct CmpcOpConversion : public FIROpConversion { mlir::Type resTy = convertType(cmp.getType()); mlir::Location loc = cmp.getLoc(); auto pos0 = mlir::ArrayAttr::get(ctxt, rewriter.getI32IntegerAttr(0)); - llvm::SmallVector rp{ + llvm::SmallVector rp = { rewriter.create(loc, eleTy, operands[0], pos0), rewriter.create(loc, eleTy, operands[1], @@ -686,14 +689,14 @@ struct CmpcOpConversion : public FIROpConversion { auto rcp = rewriter.create(loc, resTy, rp, cmp->getAttrs()); auto pos1 = mlir::ArrayAttr::get(ctxt, rewriter.getI32IntegerAttr(1)); - llvm::SmallVector ip{ + llvm::SmallVector ip = { rewriter.create(loc, eleTy, operands[0], pos1), rewriter.create(loc, eleTy, operands[1], pos1)}; auto icp = rewriter.create(loc, resTy, ip, cmp->getAttrs()); - llvm::SmallVector cp{rcp, icp}; + llvm::SmallVector cp = {rcp, icp}; switch (cmp.getPredicate()) { case mlir::arith::CmpFPredicate::OEQ: // .EQ. rewriter.replaceOpWithNewOp(cmp, resTy, cp); @@ -992,7 +995,7 @@ computeDerivedTypeSize(mlir::Location loc, mlir::Type ptrTy, mlir::Type idxTy, mlir::ConversionPatternRewriter &rewriter) { auto nullPtr = rewriter.create(loc, ptrTy); mlir::Value one = genConstantIndex(loc, idxTy, rewriter, 1); - llvm::SmallVector args{one}; + llvm::SmallVector args = {one}; auto gep = rewriter.create(loc, ptrTy, nullPtr, args); return rewriter.create(loc, idxTy, gep); } @@ -1005,12 +1008,12 @@ struct AllocMemOpConversion : public FIROpConversion { mlir::LogicalResult matchAndRewrite(fir::AllocMemOp heap, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override { - auto heapTy = heap.getType(); - auto ty = convertType(heapTy); + mlir::Type heapTy = heap.getType(); + mlir::Type ty = convertType(heapTy); mlir::LLVM::LLVMFuncOp mallocFunc = getMalloc(heap, rewriter); mlir::Location loc = heap.getLoc(); auto ity = lowerTy().indexType(); - auto dataTy = fir::unwrapRefType(heapTy); + mlir::Type dataTy = fir::unwrapRefType(heapTy); if (fir::isRecordWithTypeParameters(fir::unwrapSequenceType(dataTy))) TODO(loc, "fir.allocmem codegen of derived type with length parameters"); mlir::Value size = genTypeSizeInBytes(loc, ity, rewriter, ty); @@ -1080,8 +1083,6 @@ struct FreeMemOpConversion : public FIROpConversion { }; } // namespace -namespace {} // namespace - /// Common base class for embox to descriptor conversion. template struct EmboxCommonConversion : public FIROpConversion { @@ -1130,7 +1131,7 @@ struct EmboxCommonConversion : public FIROpConversion { return recTy && recTy.getNumLenParams() > 0; } static bool isDerivedType(fir::BoxType boxTy) { - return unwrapIfDerived(boxTy) != nullptr; + return static_cast(unwrapIfDerived(boxTy)); } // Get the element size and CFI type code of the boxed value. @@ -2000,8 +2001,8 @@ struct InsertOnRangeOpConversion type = t.getElementType(); } - llvm::SmallVector lBounds; - llvm::SmallVector uBounds; + llvm::SmallVector lBounds; + llvm::SmallVector uBounds; // Unzip the upper and lower bound and convert to a row major format. mlir::DenseIntElementsAttr coor = range.getCoor(); @@ -2073,13 +2074,8 @@ struct XArrayCoorOpConversion const bool isSliced = !coor.slice().empty(); const bool baseIsBoxed = coor.memref().getType().isa(); - auto indexOps = coor.indices().begin(); - auto shapeOps = coor.shape().begin(); - auto shiftOps = coor.shift().begin(); - auto sliceOps = coor.slice().begin(); // For each dimension of the array, generate the offset calculation. - for (unsigned i = 0; i < rank; - ++i, ++indexOps, ++shapeOps, ++shiftOps, sliceOps += 3) { + for (unsigned i = 0; i < rank; ++i) { mlir::Value index = integerCast(loc, rewriter, idxTy, operands[coor.indicesOffset() + i]); mlir::Value lb = isShifted ? integerCast(loc, rewriter, idxTy, @@ -2090,10 +2086,11 @@ struct XArrayCoorOpConversion // Compute zero based index in dimension i of the element, applying // potential triplets and lower bounds. if (isSliced) { - mlir::Value ub = *(sliceOps + 1); + mlir::Value ub = operands[coor.sliceOffset() + i + 1]; normalSlice = !mlir::isa_and_nonnull(ub.getDefiningOp()); if (normalSlice) - step = integerCast(loc, rewriter, idxTy, *(sliceOps + 2)); + step = integerCast(loc, rewriter, idxTy, + operands[coor.sliceOffset() + i + 2]); } auto idx = rewriter.create(loc, idxTy, index, lb); mlir::Value diff = @@ -2395,7 +2392,7 @@ struct CoordinateOpConversion } auto voidPtrBase = rewriter.create(loc, voidPtrTy, resultAddr); - llvm::SmallVector args{off}; + llvm::SmallVector args = {off}; resultAddr = rewriter.create(loc, voidPtrTy, voidPtrBase, args); i += arrTy.getDimension() - 1; @@ -2622,7 +2619,7 @@ struct GlobalOpConversion : public FIROpConversion { if (global.getType().isa()) tyAttr = tyAttr.cast().getElementType(); auto loc = global.getLoc(); - mlir::Attribute initAttr{}; + mlir::Attribute initAttr; if (global.getInitVal()) initAttr = global.getInitVal().getValue(); auto linkage = convertLinkage(global.getLinkName()); @@ -3325,8 +3322,6 @@ namespace { /// /// This pass lowers all FIR dialect operations to LLVM IR dialect. An /// MLIR pass is used to lower residual Std dialect to LLVM IR dialect. -/// -/// This pass is not complete yet. We are upstreaming it in small patches. class FIRToLLVMLowering : public fir::FIRToLLVMLoweringBase { public: FIRToLLVMLowering() = default; diff --git a/flang/lib/Optimizer/CodeGen/Target.cpp b/flang/lib/Optimizer/CodeGen/Target.cpp index d3ca2d6371cd1..47e6b0d57ab27 100644 --- a/flang/lib/Optimizer/CodeGen/Target.cpp +++ b/flang/lib/Optimizer/CodeGen/Target.cpp @@ -11,7 +11,9 @@ //===----------------------------------------------------------------------===// #include "Target.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRType.h" +#include "flang/Optimizer/Support/FatalError.h" #include "flang/Optimizer/Support/KindMapping.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/TypeRange.h" @@ -79,7 +81,7 @@ struct TargetI386 : public GenericTarget { static constexpr int defaultWidth = 32; CodeGenSpecifics::Marshalling - complexArgumentType(mlir::Type eleTy) const override { + complexArgumentType(mlir::Location, mlir::Type eleTy) const override { assert(fir::isa_real(eleTy)); CodeGenSpecifics::Marshalling marshal; // Use a type that will be translated into LLVM as: @@ -92,7 +94,7 @@ struct TargetI386 : public GenericTarget { } CodeGenSpecifics::Marshalling - complexReturnType(mlir::Type eleTy) const override { + complexReturnType(mlir::Location loc, mlir::Type eleTy) const override { assert(fir::isa_real(eleTy)); CodeGenSpecifics::Marshalling marshal; const auto *sem = &floatToSemantics(kindMap, eleTy); @@ -108,7 +110,7 @@ struct TargetI386 : public GenericTarget { marshal.emplace_back(fir::ReferenceType::get(structTy), AT{/*alignment=*/4, /*byval=*/false, /*sret=*/true}); } else { - llvm::report_fatal_error("complex for this precision not implemented"); + TODO(loc, "complex for this precision"); } return marshal; } @@ -126,7 +128,7 @@ struct TargetX86_64 : public GenericTarget { static constexpr int defaultWidth = 64; CodeGenSpecifics::Marshalling - complexArgumentType(mlir::Type eleTy) const override { + complexArgumentType(mlir::Location loc, mlir::Type eleTy) const override { CodeGenSpecifics::Marshalling marshal; const auto *sem = &floatToSemantics(kindMap, eleTy); if (sem == &llvm::APFloat::IEEEsingle()) { @@ -137,13 +139,13 @@ struct TargetX86_64 : public GenericTarget { marshal.emplace_back(eleTy, AT{}); marshal.emplace_back(eleTy, AT{}); } else { - llvm::report_fatal_error("complex for this precision not implemented"); + TODO(loc, "complex for this precision"); } return marshal; } CodeGenSpecifics::Marshalling - complexReturnType(mlir::Type eleTy) const override { + complexReturnType(mlir::Location loc, mlir::Type eleTy) const override { CodeGenSpecifics::Marshalling marshal; const auto *sem = &floatToSemantics(kindMap, eleTy); if (sem == &llvm::APFloat::IEEEsingle()) { @@ -156,7 +158,7 @@ struct TargetX86_64 : public GenericTarget { marshal.emplace_back(mlir::TupleType::get(eleTy.getContext(), range), AT{}); } else { - llvm::report_fatal_error("complex for this precision not implemented"); + TODO(loc, "complex for this precision"); } return marshal; } @@ -174,7 +176,7 @@ struct TargetAArch64 : public GenericTarget { static constexpr int defaultWidth = 64; CodeGenSpecifics::Marshalling - complexArgumentType(mlir::Type eleTy) const override { + complexArgumentType(mlir::Location loc, mlir::Type eleTy) const override { CodeGenSpecifics::Marshalling marshal; const auto *sem = &floatToSemantics(kindMap, eleTy); if (sem == &llvm::APFloat::IEEEsingle() || @@ -182,13 +184,13 @@ struct TargetAArch64 : public GenericTarget { // [2 x t] array of 2 eleTy marshal.emplace_back(fir::SequenceType::get({2}, eleTy), AT{}); } else { - llvm::report_fatal_error("complex for this precision not implemented"); + TODO(loc, "complex for this precision"); } return marshal; } CodeGenSpecifics::Marshalling - complexReturnType(mlir::Type eleTy) const override { + complexReturnType(mlir::Location loc, mlir::Type eleTy) const override { CodeGenSpecifics::Marshalling marshal; const auto *sem = &floatToSemantics(kindMap, eleTy); if (sem == &llvm::APFloat::IEEEsingle() || @@ -199,7 +201,7 @@ struct TargetAArch64 : public GenericTarget { marshal.emplace_back(mlir::TupleType::get(eleTy.getContext(), range), AT{}); } else { - llvm::report_fatal_error("complex for this precision not implemented"); + TODO(loc, "complex for this precision"); } return marshal; } @@ -217,7 +219,7 @@ struct TargetPPC64le : public GenericTarget { static constexpr int defaultWidth = 64; CodeGenSpecifics::Marshalling - complexArgumentType(mlir::Type eleTy) const override { + complexArgumentType(mlir::Location, mlir::Type eleTy) const override { CodeGenSpecifics::Marshalling marshal; // two distinct element type arguments (re, im) marshal.emplace_back(eleTy, AT{}); @@ -226,7 +228,7 @@ struct TargetPPC64le : public GenericTarget { } CodeGenSpecifics::Marshalling - complexReturnType(mlir::Type eleTy) const override { + complexReturnType(mlir::Location, mlir::Type eleTy) const override { CodeGenSpecifics::Marshalling marshal; // Use a type that will be translated into LLVM as: // { t, t } struct of 2 element type @@ -291,5 +293,5 @@ fir::CodeGenSpecifics::get(mlir::MLIRContext *ctx, llvm::Triple &&trp, } break; } - llvm::report_fatal_error("target not implemented"); + TODO(mlir::UnknownLoc::get(ctx), "target not implemented"); } diff --git a/flang/lib/Optimizer/CodeGen/Target.h b/flang/lib/Optimizer/CodeGen/Target.h index f6996fcd1bcb6..7f6d8d96d23bc 100644 --- a/flang/lib/Optimizer/CodeGen/Target.h +++ b/flang/lib/Optimizer/CodeGen/Target.h @@ -71,11 +71,13 @@ class CodeGenSpecifics { /// Type representation of a `complex` type argument when passed by /// value. An argument value may need to be passed as a (safe) reference /// argument. - virtual Marshalling complexArgumentType(mlir::Type eleTy) const = 0; + virtual Marshalling complexArgumentType(mlir::Location loc, + mlir::Type eleTy) const = 0; /// Type representation of a `complex` type return value. Such a return /// value may need to be converted to a hidden reference argument. - virtual Marshalling complexReturnType(mlir::Type eleTy) const = 0; + virtual Marshalling complexReturnType(mlir::Location loc, + mlir::Type eleTy) const = 0; /// Type presentation of a `boxchar` type value in memory. virtual mlir::Type boxcharMemoryType(mlir::Type eleTy) const = 0; diff --git a/flang/lib/Optimizer/CodeGen/TargetRewrite.cpp b/flang/lib/Optimizer/CodeGen/TargetRewrite.cpp index 65932b8d3ab4e..e20792115f423 100644 --- a/flang/lib/Optimizer/CodeGen/TargetRewrite.cpp +++ b/flang/lib/Optimizer/CodeGen/TargetRewrite.cpp @@ -16,9 +16,9 @@ #include "PassDetail.h" #include "Target.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/CodeGen/CodeGen.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROps.h" @@ -114,14 +114,14 @@ class TargetRewrite : public fir::TargetRewriteBase { template std::function - rewriteCallComplexResultType(A ty, B &newResTys, B &newInTys, C &newOpers) { - auto m = specifics->complexReturnType(ty.getElementType()); + rewriteCallComplexResultType(mlir::Location loc, A ty, B &newResTys, + B &newInTys, C &newOpers) { + auto m = specifics->complexReturnType(loc, ty.getElementType()); // Currently targets mandate COMPLEX is a single aggregate or packed // scalar, including the sret case. assert(m.size() == 1 && "target lowering of complex return not supported"); auto resTy = std::get(m[0]); auto attr = std::get(m[0]); - auto loc = mlir::UnknownLoc::get(resTy.getContext()); if (attr.isSRet()) { assert(fir::isa_ref_type(resTy) && "must be a memory reference type"); mlir::Value stack = @@ -147,9 +147,11 @@ class TargetRewrite : public fir::TargetRewriteBase { template void rewriteCallComplexInputType(A ty, mlir::Value oper, B &newInTys, C &newOpers) { - auto m = specifics->complexArgumentType(ty.getElementType()); auto *ctx = ty.getContext(); - auto loc = mlir::UnknownLoc::get(ctx); + mlir::Location loc = mlir::UnknownLoc::get(ctx); + if (auto *op = oper.getDefiningOp()) + loc = op->getLoc(); + auto m = specifics->complexArgumentType(loc, ty.getElementType()); if (m.size() == 1) { // COMPLEX is a single aggregate auto resTy = std::get(m[0]); @@ -210,11 +212,11 @@ class TargetRewrite : public fir::TargetRewriteBase { mlir::Type ty = fnTy.getResult(0); llvm::TypeSwitch(ty) .template Case([&](fir::ComplexType cmplx) { - wrap = rewriteCallComplexResultType(cmplx, newResTys, newInTys, + wrap = rewriteCallComplexResultType(loc, cmplx, newResTys, newInTys, newOpers); }) .template Case([&](mlir::ComplexType cmplx) { - wrap = rewriteCallComplexResultType(cmplx, newResTys, newInTys, + wrap = rewriteCallComplexResultType(loc, cmplx, newResTys, newInTys, newOpers); }) .Default([&](mlir::Type ty) { newResTys.push_back(ty); }); @@ -337,11 +339,13 @@ class TargetRewrite : public fir::TargetRewriteBase { // Result type fixup for fir::ComplexType and mlir::ComplexType template - void lowerComplexSignatureRes(A cmplx, B &newResTys, B &newInTys) { + void lowerComplexSignatureRes(mlir::Location loc, A cmplx, B &newResTys, + B &newInTys) { if (noComplexConversion) { newResTys.push_back(cmplx); } else { - for (auto &tup : specifics->complexReturnType(cmplx.getElementType())) { + for (auto &tup : + specifics->complexReturnType(loc, cmplx.getElementType())) { auto argTy = std::get(tup); if (std::get(tup).isSRet()) newInTys.push_back(argTy); @@ -353,11 +357,12 @@ class TargetRewrite : public fir::TargetRewriteBase { // Argument type fixup for fir::ComplexType and mlir::ComplexType template - void lowerComplexSignatureArg(A cmplx, B &newInTys) { + void lowerComplexSignatureArg(mlir::Location loc, A cmplx, B &newInTys) { if (noComplexConversion) newInTys.push_back(cmplx); else - for (auto &tup : specifics->complexArgumentType(cmplx.getElementType())) + for (auto &tup : + specifics->complexArgumentType(loc, cmplx.getElementType())) newInTys.push_back(std::get(tup)); } @@ -367,13 +372,14 @@ class TargetRewrite : public fir::TargetRewriteBase { auto addrTy = addrOp.getType().cast(); llvm::SmallVector newResTys; llvm::SmallVector newInTys; + auto loc = addrOp.getLoc(); for (mlir::Type ty : addrTy.getResults()) { llvm::TypeSwitch(ty) .Case([&](fir::ComplexType ty) { - lowerComplexSignatureRes(ty, newResTys, newInTys); + lowerComplexSignatureRes(loc, ty, newResTys, newInTys); }) .Case([&](mlir::ComplexType ty) { - lowerComplexSignatureRes(ty, newResTys, newInTys); + lowerComplexSignatureRes(loc, ty, newResTys, newInTys); }) .Default([&](mlir::Type ty) { newResTys.push_back(ty); }); } @@ -394,10 +400,10 @@ class TargetRewrite : public fir::TargetRewriteBase { } }) .Case([&](fir::ComplexType ty) { - lowerComplexSignatureArg(ty, newInTys); + lowerComplexSignatureArg(loc, ty, newInTys); }) .Case([&](mlir::ComplexType ty) { - lowerComplexSignatureArg(ty, newInTys); + lowerComplexSignatureArg(loc, ty, newInTys); }) .Case([&](mlir::TupleType tuple) { if (fir::isCharacterProcedureTuple(tuple)) { @@ -730,7 +736,8 @@ class TargetRewrite : public fir::TargetRewriteBase { newResTys.push_back(cmplx); return; } - auto m = specifics->complexReturnType(cmplx.getElementType()); + auto m = + specifics->complexReturnType(func.getLoc(), cmplx.getElementType()); assert(m.size() == 1); auto &tup = m[0]; auto attr = std::get(tup); @@ -757,7 +764,8 @@ class TargetRewrite : public fir::TargetRewriteBase { newInTys.push_back(cmplx); return; } - auto m = specifics->complexArgumentType(cmplx.getElementType()); + auto m = + specifics->complexArgumentType(func.getLoc(), cmplx.getElementType()); const auto fixupCode = m.size() > 1 ? FixupTy::Codes::Split : FixupTy::Codes::ArgumentType; for (auto e : llvm::enumerate(m)) { diff --git a/flang/lib/Optimizer/CodeGen/TypeConverter.h b/flang/lib/Optimizer/CodeGen/TypeConverter.h index aefe5923c1396..1c7ef9c0bc461 100644 --- a/flang/lib/Optimizer/CodeGen/TypeConverter.h +++ b/flang/lib/Optimizer/CodeGen/TypeConverter.h @@ -15,7 +15,7 @@ #include "DescriptorModel.h" #include "Target.h" -#include "flang/Lower/Todo.h" // remove when TODO's are done +#include "flang/Optimizer/Builder/Todo.h" // remove when TODO's are done #include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Optimizer/Support/FIRContext.h" #include "flang/Optimizer/Support/KindMapping.h" @@ -128,6 +128,29 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter { return mlir::LLVM::LLVMStructType::getLiteral( none.getContext(), llvm::None, /*isPacked=*/false); }); + // FIXME: https://reviews.llvm.org/D82831 introduced an automatic + // materialization of conversion around function calls that is not working + // well with fir lowering to llvm (incorrect llvm.mlir.cast are inserted). + // Workaround until better analysis: register a handler that does not insert + // any conversions. + addSourceMaterialization( + [&](mlir::OpBuilder &builder, mlir::Type resultType, + mlir::ValueRange inputs, + mlir::Location loc) -> llvm::Optional { + if (inputs.size() != 1) + return llvm::None; + return inputs[0]; + }); + // Similar FIXME workaround here (needed for compare.fir/select-type.fir + // tests). + addTargetMaterialization( + [&](mlir::OpBuilder &builder, mlir::Type resultType, + mlir::ValueRange inputs, + mlir::Location loc) -> llvm::Optional { + if (inputs.size() != 1) + return llvm::None; + return inputs[0]; + }); } // i32 is used here because LLVM wants i32 constants when indexing into struct @@ -315,7 +338,8 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter { // convert a front-end kind value to either a std or LLVM IR dialect type // fir.real --> llvm.anyfloat where anyfloat is a kind mapping mlir::Type convertRealType(fir::KindTy kind) { - return fromRealTypeID(kindMapping.getRealTypeID(kind), kind); + return fir::fromRealTypeID(&getContext(), kindMapping.getRealTypeID(kind), + kind); } // fir.array --> llvm<"[...[c x any]]"> @@ -346,28 +370,6 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter { mlir::IntegerType::get(&getContext(), 8)); } - /// Convert llvm::Type::TypeID to mlir::Type - mlir::Type fromRealTypeID(llvm::Type::TypeID typeID, fir::KindTy kind) { - switch (typeID) { - case llvm::Type::TypeID::HalfTyID: - return mlir::FloatType::getF16(&getContext()); - case llvm::Type::TypeID::BFloatTyID: - return mlir::FloatType::getBF16(&getContext()); - case llvm::Type::TypeID::FloatTyID: - return mlir::FloatType::getF32(&getContext()); - case llvm::Type::TypeID::DoubleTyID: - return mlir::FloatType::getF64(&getContext()); - case llvm::Type::TypeID::X86_FP80TyID: - return mlir::FloatType::getF80(&getContext()); - case llvm::Type::TypeID::FP128TyID: - return mlir::FloatType::getF128(&getContext()); - default: - mlir::emitError(mlir::UnknownLoc::get(&getContext())) - << "unsupported type: !fir.real<" << kind << ">"; - return {}; - } - } - KindMapping &getKindMap() { return kindMapping; } private: diff --git a/flang/lib/Optimizer/Dialect/CMakeLists.txt b/flang/lib/Optimizer/Dialect/CMakeLists.txt index def1ef82f683e..c991b43239d41 100644 --- a/flang/lib/Optimizer/Dialect/CMakeLists.txt +++ b/flang/lib/Optimizer/Dialect/CMakeLists.txt @@ -12,7 +12,7 @@ add_flang_library(FIRDialect LINK_LIBS FIRSupport - MLIRArithmetic + MLIRArithmeticDialect MLIROpenMPToLLVM MLIRLLVMToLLVMIRTranslation MLIRTargetLLVMIRExport diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp index 9e58afa74fadc..fc5d85886246a 100644 --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -14,6 +14,8 @@ #include "flang/Optimizer/Dialect/FIRAttr.h" #include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Optimizer/Dialect/FIRType.h" +#include "flang/Optimizer/Support/FIRContext.h" +#include "flang/Optimizer/Support/KindMapping.h" #include "flang/Optimizer/Support/Utils.h" #include "mlir/Dialect/CommonFolders.h" #include "mlir/Dialect/Func/IR/FuncOps.h" @@ -3437,8 +3439,11 @@ mlir::Type fir::applyPathToType(mlir::Type eleTy, mlir::ValueRange path) { return mlir::Type{}; }) .Case([&](fir::ComplexType ty) { - if (fir::isa_integer((*i++).getType())) - return ty.getElementType(); + auto x = *i; + if (auto *op = (*i++).getDefiningOp()) + if (fir::isa_integer(x.getType())) + return ty.getEleType(fir::getKindMapping( + op->getParentOfType())); return mlir::Type{}; }) .Case([&](mlir::ComplexType ty) { diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp index 834173be2dd81..3293cad6177a2 100644 --- a/flang/lib/Optimizer/Dialect/FIRType.cpp +++ b/flang/lib/Optimizer/Dialect/FIRType.cpp @@ -12,6 +12,7 @@ #include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Optimizer/Dialect/FIRDialect.h" +#include "flang/Optimizer/Support/KindMapping.h" #include "flang/Tools/PointerModels.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinDialect.h" @@ -483,6 +484,13 @@ mlir::Type fir::ComplexType::getElementType() const { return fir::RealType::get(getContext(), getFKind()); } +// Return the MLIR float type of the complex element type. +mlir::Type fir::ComplexType::getEleType(const fir::KindMapping &kindMap) const { + auto fkind = getFKind(); + auto realTypeID = kindMap.getRealTypeID(fkind); + return fir::fromRealTypeID(getContext(), realTypeID, fkind); +} + //===----------------------------------------------------------------------===// // HeapType //===----------------------------------------------------------------------===// @@ -925,6 +933,37 @@ bool fir::isCharacterProcedureTuple(mlir::Type ty, bool acceptRawFunc) { fir::isa_integer(tuple.getType(1)); } +bool fir::hasAbstractResult(mlir::FunctionType ty) { + if (ty.getNumResults() == 0) + return false; + auto resultType = ty.getResult(0); + return resultType.isa(); +} + +/// Convert llvm::Type::TypeID to mlir::Type. \p kind is provided for error +/// messages only. +mlir::Type fir::fromRealTypeID(mlir::MLIRContext *context, + llvm::Type::TypeID typeID, fir::KindTy kind) { + switch (typeID) { + case llvm::Type::TypeID::HalfTyID: + return mlir::FloatType::getF16(context); + case llvm::Type::TypeID::BFloatTyID: + return mlir::FloatType::getBF16(context); + case llvm::Type::TypeID::FloatTyID: + return mlir::FloatType::getF32(context); + case llvm::Type::TypeID::DoubleTyID: + return mlir::FloatType::getF64(context); + case llvm::Type::TypeID::X86_FP80TyID: + return mlir::FloatType::getF80(context); + case llvm::Type::TypeID::FP128TyID: + return mlir::FloatType::getF128(context); + default: + mlir::emitError(mlir::UnknownLoc::get(context)) + << "unsupported type: !fir.real<" << kind << ">"; + return {}; + } +} + //===----------------------------------------------------------------------===// // FIROpsDialect //===----------------------------------------------------------------------===// diff --git a/flang/lib/Optimizer/Transforms/AbstractResult.cpp b/flang/lib/Optimizer/Transforms/AbstractResult.cpp index 1946ccdfd69f9..7dd821474698f 100644 --- a/flang/lib/Optimizer/Transforms/AbstractResult.cpp +++ b/flang/lib/Optimizer/Transforms/AbstractResult.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "PassDetail.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIRType.h" @@ -31,13 +32,6 @@ struct AbstractResultOptions { mlir::Value newArg; }; -static bool mustConvertCallOrFunc(mlir::FunctionType type) { - if (type.getNumResults() == 0) - return false; - auto resultType = type.getResult(0); - return resultType.isa(); -} - static mlir::Type getResultArgumentType(mlir::Type resultType, const AbstractResultOptions &options) { return llvm::TypeSwitch(resultType) @@ -223,7 +217,7 @@ class AbstractResultOpt : public fir::AbstractResultOptBase { // Convert function type itself if it has an abstract result auto funcTy = func.getFunctionType().cast(); - if (mustConvertCallOrFunc(funcTy)) { + if (hasAbstractResult(funcTy)) { func.setType(getNewFunctionType(funcTy, options)); unsigned zero = 0; if (!func.empty()) { @@ -252,11 +246,11 @@ class AbstractResultOpt : public fir::AbstractResultOptBase { mlir::func::FuncDialect>(); target.addIllegalOp(); target.addDynamicallyLegalOp([](fir::CallOp call) { - return !mustConvertCallOrFunc(call.getFunctionType()); + return !hasAbstractResult(call.getFunctionType()); }); target.addDynamicallyLegalOp([](fir::AddrOfOp addrOf) { if (auto funTy = addrOf.getType().dyn_cast()) - return !mustConvertCallOrFunc(funTy); + return !hasAbstractResult(funTy); return true; }); target.addDynamicallyLegalOp([](fir::DispatchOp dispatch) { @@ -264,8 +258,7 @@ class AbstractResultOpt : public fir::AbstractResultOptBase { return true; auto resultType = dispatch->getResult(0).getType(); if (resultType.isa()) { - mlir::emitError(dispatch.getLoc(), - "TODO: dispatchOp with abstract results"); + TODO(dispatch.getLoc(), "dispatchOp with abstract results"); return false; } return true; diff --git a/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp b/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp index 5e44fdc1b6601..839275a98f60d 100644 --- a/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp +++ b/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp @@ -7,12 +7,12 @@ //===----------------------------------------------------------------------===// #include "PassDetail.h" -#include "flang/Lower/Todo.h" #include "flang/Optimizer/Builder/Array.h" #include "flang/Optimizer/Builder/BoxValue.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Factory.h" #include "flang/Optimizer/Builder/Runtime/Derived.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Optimizer/Support/FIRContext.h" @@ -667,11 +667,11 @@ amendingAccess(llvm::ArrayRef mentions) { return {}; } -// Are either of types of conflicts present? -inline bool conflictDetected(llvm::ArrayRef reach, - llvm::ArrayRef accesses, +// Are any conflicts present? The conflicts detected here are described above. +static bool conflictDetected(llvm::ArrayRef reach, + llvm::ArrayRef mentions, ArrayMergeStoreOp st) { - return conflictOnLoad(reach, st) || conflictOnMerge(accesses); + return conflictOnLoad(reach, st) || conflictOnMerge(mentions); } // Assume that any call to a function that uses host-associations will be @@ -871,21 +871,33 @@ static mlir::Type toRefType(mlir::Type ty) { return fir::ReferenceType::get(ty); } -static mlir::Value -genCoorOp(mlir::PatternRewriter &rewriter, mlir::Location loc, mlir::Type eleTy, - mlir::Type resTy, mlir::Value alloc, mlir::Value shape, - mlir::Value slice, mlir::ValueRange indices, - mlir::ValueRange typeparams, bool skipOrig = false) { +static llvm::SmallVector +getTypeParamsIfRawData(mlir::Location loc, FirOpBuilder &builder, + ArrayLoadOp arrLoad, mlir::Type ty) { + if (ty.isa()) + return {}; + return fir::factory::getTypeParams(loc, builder, arrLoad); +} + +static mlir::Value genCoorOp(mlir::PatternRewriter &rewriter, + mlir::Location loc, mlir::Type eleTy, + mlir::Type resTy, mlir::Value alloc, + mlir::Value shape, mlir::Value slice, + mlir::ValueRange indices, ArrayLoadOp load, + bool skipOrig = false) { llvm::SmallVector originated; if (skipOrig) originated.assign(indices.begin(), indices.end()); else - originated = fir::factory::originateIndices(loc, rewriter, alloc.getType(), - shape, indices); - auto seqTy = fir::dyn_cast_ptrOrBoxEleTy(alloc.getType()); - assert(seqTy && seqTy.isa()); - const auto dimension = seqTy.cast().getDimension(); - mlir::Value result = rewriter.create( + originated = factory::originateIndices(loc, rewriter, alloc.getType(), + shape, indices); + auto seqTy = dyn_cast_ptrOrBoxEleTy(alloc.getType()); + assert(seqTy && seqTy.isa()); + const auto dimension = seqTy.cast().getDimension(); + auto module = load->getParentOfType(); + FirOpBuilder builder(rewriter, getKindMapping(module)); + auto typeparams = getTypeParamsIfRawData(loc, builder, load, alloc.getType()); + mlir::Value result = rewriter.create( loc, eleTy, alloc, shape, slice, llvm::ArrayRef{originated}.take_front(dimension), typeparams); @@ -946,20 +958,19 @@ void genArrayCopy(mlir::Location loc, mlir::PatternRewriter &rewriter, } // Reverse the indices so they are in column-major order. std::reverse(indices.begin(), indices.end()); - auto typeparams = arrLoad.getTypeparams(); + auto module = arrLoad->getParentOfType(); + FirOpBuilder builder(rewriter, getKindMapping(module)); auto fromAddr = rewriter.create( loc, getEleTy(src.getType()), src, shapeOp, CopyIn && copyUsingSlice ? sliceOp : mlir::Value{}, factory::originateIndices(loc, rewriter, src.getType(), shapeOp, indices), - typeparams); + getTypeParamsIfRawData(loc, builder, arrLoad, src.getType())); auto toAddr = rewriter.create( loc, getEleTy(dst.getType()), dst, shapeOp, !CopyIn && copyUsingSlice ? sliceOp : mlir::Value{}, factory::originateIndices(loc, rewriter, dst.getType(), shapeOp, indices), - typeparams); + getTypeParamsIfRawData(loc, builder, arrLoad, src.getType())); auto eleTy = unwrapSequenceType(unwrapPassByRefType(dst.getType())); - auto module = toAddr->getParentOfType(); - FirOpBuilder builder(rewriter, getKindMapping(module)); // Copy from (to) object to (from) temp copy of same object. if (auto charTy = eleTy.dyn_cast()) { auto len = getCharacterLen(loc, builder, arrLoad, charTy); @@ -1093,11 +1104,10 @@ class ArrayUpdateConversionBase : public mlir::OpRewritePattern { load); // Generate the reference for the access. rewriter.setInsertionPoint(op); - auto coor = - genCoorOp(rewriter, loc, getEleTy(load.getType()), eleTy, allocmem, - shapeOp, copyUsingSlice ? mlir::Value{} : load.getSlice(), - access.getIndices(), load.getTypeparams(), - access->hasAttr(factory::attrFortranArrayOffsets())); + auto coor = genCoorOp( + rewriter, loc, getEleTy(load.getType()), eleTy, allocmem, shapeOp, + copyUsingSlice ? mlir::Value{} : load.getSlice(), access.getIndices(), + load, access->hasAttr(factory::attrFortranArrayOffsets())); // Copy out. auto *storeOp = useMap.lookup(loadOp); auto store = mlir::cast(storeOp); @@ -1145,7 +1155,7 @@ class ArrayUpdateConversionBase : public mlir::OpRewritePattern { auto coor = genCoorOp( rewriter, loc, getEleTy(load.getType()), lhsEltRefType, allocmem, shapeOp, copyUsingSlice ? mlir::Value{} : load.getSlice(), - update.getIndices(), load.getTypeparams(), + update.getIndices(), load, update->hasAttr(factory::attrFortranArrayOffsets())); assignElement(coor); auto *storeOp = useMap.lookup(loadOp); @@ -1163,10 +1173,10 @@ class ArrayUpdateConversionBase : public mlir::OpRewritePattern { LLVM_DEBUG(llvm::outs() << "No, conflict wasn't found\n"); rewriter.setInsertionPoint(op); auto coorTy = getEleTy(load.getType()); - auto coor = genCoorOp(rewriter, loc, coorTy, lhsEltRefType, - load.getMemref(), load.getShape(), load.getSlice(), - update.getIndices(), load.getTypeparams(), - update->hasAttr(factory::attrFortranArrayOffsets())); + auto coor = + genCoorOp(rewriter, loc, coorTy, lhsEltRefType, load.getMemref(), + load.getShape(), load.getSlice(), update.getIndices(), load, + update->hasAttr(factory::attrFortranArrayOffsets())); assignElement(coor); return {coor, load.getResult()}; } @@ -1240,11 +1250,10 @@ class ArrayFetchConversion : public mlir::OpRewritePattern { rewriter.setInsertionPoint(op); auto load = mlir::cast(useMap.lookup(op)); auto loc = fetch.getLoc(); - auto coor = - genCoorOp(rewriter, loc, getEleTy(load.getType()), - toRefType(fetch.getType()), load.getMemref(), load.getShape(), - load.getSlice(), fetch.getIndices(), load.getTypeparams(), - fetch->hasAttr(factory::attrFortranArrayOffsets())); + auto coor = genCoorOp( + rewriter, loc, getEleTy(load.getType()), toRefType(fetch.getType()), + load.getMemref(), load.getShape(), load.getSlice(), fetch.getIndices(), + load, fetch->hasAttr(factory::attrFortranArrayOffsets())); if (isa_ref_type(fetch.getType())) rewriter.replaceOp(fetch, coor); else @@ -1280,11 +1289,10 @@ class ArrayAccessConversion : public ArrayUpdateConversionBase { } rewriter.setInsertionPoint(op); auto load = mlir::cast(useMap.lookup(op)); - auto coor = genCoorOp(rewriter, loc, getEleTy(load.getType()), - toRefType(access.getType()), load.getMemref(), - load.getShape(), load.getSlice(), access.getIndices(), - load.getTypeparams(), - access->hasAttr(factory::attrFortranArrayOffsets())); + auto coor = genCoorOp( + rewriter, loc, getEleTy(load.getType()), toRefType(access.getType()), + load.getMemref(), load.getShape(), load.getSlice(), access.getIndices(), + load, access->hasAttr(factory::attrFortranArrayOffsets())); rewriter.replaceOp(access, coor); return mlir::success(); } diff --git a/flang/lib/Optimizer/Transforms/CMakeLists.txt b/flang/lib/Optimizer/Transforms/CMakeLists.txt index 2d4ea740a5e68..86547792cd698 100644 --- a/flang/lib/Optimizer/Transforms/CMakeLists.txt +++ b/flang/lib/Optimizer/Transforms/CMakeLists.txt @@ -21,9 +21,9 @@ add_flang_library(FIRTransforms FIRBuilder FIRDialect MLIRAffineUtils - MLIRFunc - MLIRLLVMIR - MLIROpenACC - MLIROpenMP + MLIRFuncDialect + MLIRLLVMDialect + MLIROpenACCDialect + MLIROpenMPDialect FIRSupport ) diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 9a4f4bbcc7abd..e3d6d5f90bd54 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -52,12 +52,30 @@ TYPE_PARSER(construct( TYPE_PARSER(construct( maybe(Parser{}), Parser{})) -// 2.15.5.2 defaultmap -> DEFAULTMAP (TOFROM:SCALAR) +// [OpenMP 5.0] +// 2.19.7.2 defaultmap(implicit-behavior[:variable-category]) +// implicit-behavior -> ALLOC | TO | FROM | TOFROM | FIRSRTPRIVATE | NONE | +// DEFAULT +// variable-category -> SCALAR | AGGREGATE | ALLOCATABLE | POINTER TYPE_PARSER(construct( construct( - "TOFROM" >> pure(OmpDefaultmapClause::ImplicitBehavior::Tofrom)), - maybe(":" >> construct("SCALAR" >> - pure(OmpDefaultmapClause::VariableCategory::Scalar))))) + "ALLOC" >> pure(OmpDefaultmapClause::ImplicitBehavior::Alloc) || + "TO"_id >> pure(OmpDefaultmapClause::ImplicitBehavior::To) || + "FROM" >> pure(OmpDefaultmapClause::ImplicitBehavior::From) || + "TOFROM" >> pure(OmpDefaultmapClause::ImplicitBehavior::Tofrom) || + "FIRSTPRIVATE" >> + pure(OmpDefaultmapClause::ImplicitBehavior::Firstprivate) || + "NONE" >> pure(OmpDefaultmapClause::ImplicitBehavior::None) || + "DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default)), + maybe(":" >> + construct( + "SCALAR" >> pure(OmpDefaultmapClause::VariableCategory::Scalar) || + "AGGREGATE" >> + pure(OmpDefaultmapClause::VariableCategory::Aggregate) || + "ALLOCATABLE" >> + pure(OmpDefaultmapClause::VariableCategory::Allocatable) || + "POINTER" >> + pure(OmpDefaultmapClause::VariableCategory::Pointer))))) // 2.7.1 SCHEDULE ([modifier1 [, modifier2]:]kind[, chunk_size]) // Modifier -> MONITONIC | NONMONOTONIC | SIMD @@ -104,6 +122,10 @@ TYPE_PARSER(construct(Parser{}) || TYPE_PARSER(construct( Parser{} / ":", Parser{})) +// OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list) +TYPE_PARSER(construct( + Parser{} / ":", Parser{})) + // OMP 5.0 2.11.4 ALLOCATE ([allocator:] variable-name-list) TYPE_PARSER(construct( maybe(construct(scalarIntExpr) / ":"), @@ -224,6 +246,8 @@ TYPE_PARSER( parenthesized(Parser{}))) || "REDUCTION" >> construct(construct( parenthesized(Parser{}))) || + "IN_REDUCTION" >> construct(construct( + parenthesized(Parser{}))) || "TASK_REDUCTION" >> construct(construct( parenthesized(Parser{}))) || diff --git a/flang/lib/Parser/parsing.cpp b/flang/lib/Parser/parsing.cpp index 6b0119008dbf4..3ea14e934b178 100644 --- a/flang/lib/Parser/parsing.cpp +++ b/flang/lib/Parser/parsing.cpp @@ -35,9 +35,12 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) { const SourceFile *sourceFile; if (path == "-") { sourceFile = allSources.ReadStandardInput(fileError); + } else if (options.isModuleFile) { + // Don't mess with intrinsic module search path + sourceFile = allSources.Open(path, fileError); } else { - std::optional currentDirectory{"."}; - sourceFile = allSources.Open(path, fileError, std::move(currentDirectory)); + sourceFile = + allSources.Open(path, fileError, "."s /*prepend to search path*/); } if (!fileError.str().empty()) { ProvenanceRange range{allSources.AddCompilerInsertion(path)}; diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index c52ad06eeacec..880d8323ab32a 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2025,6 +2025,11 @@ class UnparseVisitor { Put(":"); Walk(std::get(x.t)); } + void Unparse(const OmpInReductionClause &x) { + Walk(std::get(x.t)); + Put(":"); + Walk(std::get(x.t)); + } void Unparse(const OmpAllocateClause &x) { Walk(std::get>(x.t)); Put(":"); diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index 6b559545e448f..9f5eeadd07b32 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -46,6 +46,7 @@ class CheckHelper { void Check(const ArraySpec &); void Check(const DeclTypeSpec &, bool canHaveAssumedTypeParameters); void Check(const Symbol &); + void CheckCommonBlock(const Symbol &); void Check(const Scope &); const Procedure *Characterize(const Symbol &); @@ -351,6 +352,10 @@ void CheckHelper::Check(const Symbol &symbol) { "A dummy argument may not have the SAVE attribute"_err_en_US); } } else if (IsFunctionResult(symbol)) { + if (IsNamedConstant(symbol)) { + messages_.Say( + "A function result may not also be a named constant"_err_en_US); + } if (!symbol.test(Symbol::Flag::InDataStmt) /*caught elsewhere*/ && IsSaved(symbol)) { messages_.Say( @@ -371,6 +376,8 @@ void CheckHelper::Check(const Symbol &symbol) { } } +void CheckHelper::CheckCommonBlock(const Symbol &symbol) { CheckBindC(symbol); } + void CheckHelper::CheckValue( const Symbol &symbol, const DerivedTypeSpec *derived) { // C863 - C865 if (!IsDummy(symbol)) { @@ -1725,6 +1732,9 @@ void CheckHelper::Check(const Scope &scope) { for (const auto &pair : scope) { Check(*pair.second); } + for (const auto &pair : scope.commonBlocks()) { + CheckCommonBlock(*pair.second); + } int mainProgCnt{0}; for (const Scope &child : scope.children()) { Check(child); @@ -1861,7 +1871,7 @@ static const std::string *DefinesBindCName(const Symbol &symbol) { const auto *subp{symbol.detailsIf()}; if ((subp && !subp->isInterface() && ClassifyProcedure(symbol) != ProcedureDefinitionClass::Internal) || - symbol.has()) { + symbol.has() || symbol.has()) { // Symbol defines data or entry point return symbol.GetBindName(); } else { @@ -1869,11 +1879,11 @@ static const std::string *DefinesBindCName(const Symbol &symbol) { } } -// Check that BIND(C) names are distinct and BIND(C) variable declared in module void CheckHelper::CheckBindC(const Symbol &symbol) { if (!symbol.attrs().test(Attr::BIND_C)) { return; } + CheckConflicting(symbol, Attr::BIND_C, Attr::PARAMETER); if (symbol.has() && !symbol.owner().IsModule()) { messages_.Say(symbol.name(), "A variable with BIND(C) attribute may only appear in the specification part of a module"_err_en_US); @@ -1882,8 +1892,11 @@ void CheckHelper::CheckBindC(const Symbol &symbol) { auto pair{bindC_.emplace(*name, symbol)}; if (!pair.second) { const Symbol &other{*pair.first->second}; - if (DefinesBindCName(other) && !context_.HasError(other)) { - if (auto *msg{messages_.Say( + // Two common blocks with the same name can have the same BIND(C) name. + if ((!symbol.has() || + symbol.name() != other.name()) && + DefinesBindCName(other) && !context_.HasError(other)) { + if (auto *msg{messages_.Say(symbol.name(), "Two symbols have the same BIND(C) name '%s'"_err_en_US, *name)}) { msg->Attach(other.name(), "Conflicting symbol"_en_US); @@ -1893,6 +1906,13 @@ void CheckHelper::CheckBindC(const Symbol &symbol) { } } } + if (const auto *proc{symbol.detailsIf()}) { + if (!proc->interface().symbol() || + !proc->interface().symbol()->attrs().test(Attr::BIND_C)) { + messages_.Say(symbol.name(), + "An interface name with BIND attribute must be specified if the BIND attribute is specified in a procedure declaration statement"_err_en_US); + } + } } bool CheckHelper::CheckDioDummyIsData( diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 38ca2e11ad36a..58ad55bde405f 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -922,6 +922,8 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar( common::visitors{ [&](const parser::Designator &) { if (const auto *name{parser::Unwrap(ompObject)}) { + const auto &useScope{ + context_.FindScope(GetContext().directiveSource)}; const auto &declScope{ GetProgramUnitContaining(name->symbol->GetUltimate())}; const auto *sym = @@ -967,6 +969,12 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar( "declared in the scope of a module or have the SAVE " "attribute, either explicitly or implicitly"_err_en_US, ContextDirectiveAsFortran()); + } else if (useScope != declScope) { + context_.Say(name->source, + "The %s directive and the common block or variable in it " + "must appear in the same declaration section of a " + "scoping unit"_err_en_US, + ContextDirectiveAsFortran()); } else if (FindEquivalenceSet(*name->symbol)) { context_.Say(name->source, "A variable in a %s directive cannot appear in an " @@ -1764,7 +1772,6 @@ CHECK_SIMPLE_CLAUSE(AtomicDefaultMemOrder, OMPC_atomic_default_mem_order) CHECK_SIMPLE_CLAUSE(Affinity, OMPC_affinity) CHECK_SIMPLE_CLAUSE(Allocate, OMPC_allocate) CHECK_SIMPLE_CLAUSE(Capture, OMPC_capture) -CHECK_SIMPLE_CLAUSE(Copyin, OMPC_copyin) CHECK_SIMPLE_CLAUSE(Default, OMPC_default) CHECK_SIMPLE_CLAUSE(Depobj, OMPC_depobj) CHECK_SIMPLE_CLAUSE(Destroy, OMPC_destroy) @@ -2086,6 +2093,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Firstprivate &x) { SymbolSourceMap currSymbols; GetSymbolsInObjectList(x.v, currSymbols); + CheckCopyingPolymorphicAllocatable( + currSymbols, llvm::omp::Clause::OMPC_firstprivate); DirectivesClauseTriple dirClauseTriple; // Check firstprivate variables in worksharing constructs @@ -2348,9 +2357,28 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) { } } +void OmpStructureChecker::CheckCopyingPolymorphicAllocatable( + SymbolSourceMap &symbols, const llvm::omp::Clause clause) { + for (auto it{symbols.begin()}; it != symbols.end(); ++it) { + const auto *symbol{it->first}; + const auto source{it->second}; + if (IsPolymorphicAllocatable(*symbol)) { + context_.Say(source, + "If a polymorphic variable with allocatable attribute '%s' is in " + "%s clause, the behavior is unspecified"_port_en_US, + symbol->name(), + parser::ToUpperCaseLetters(getClauseName(clause).str())); + } + } +} + void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) { CheckAllowed(llvm::omp::Clause::OMPC_copyprivate); CheckIntentInPointer(x.v, llvm::omp::Clause::OMPC_copyprivate); + SymbolSourceMap currSymbols; + GetSymbolsInObjectList(x.v, currSymbols); + CheckCopyingPolymorphicAllocatable( + currSymbols, llvm::omp::Clause::OMPC_copyprivate); } void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) { @@ -2360,6 +2388,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) { SymbolSourceMap currSymbols; GetSymbolsInObjectList(x.v, currSymbols); CheckDefinableObjects(currSymbols, GetClauseKindForParserClass(x)); + CheckCopyingPolymorphicAllocatable( + currSymbols, llvm::omp::Clause::OMPC_lastprivate); // Check lastprivate variables in worksharing constructs dirClauseTriple.emplace(llvm::omp::Directive::OMPD_do, @@ -2373,6 +2403,15 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) { currSymbols, dirClauseTriple, GetClauseKindForParserClass(x)); } +void OmpStructureChecker::Enter(const parser::OmpClause::Copyin &x) { + CheckAllowed(llvm::omp::Clause::OMPC_copyin); + + SymbolSourceMap currSymbols; + GetSymbolsInObjectList(x.v, currSymbols); + CheckCopyingPolymorphicAllocatable( + currSymbols, llvm::omp::Clause::OMPC_copyin); +} + llvm::StringRef OmpStructureChecker::getClauseName(llvm::omp::Clause clause) { return llvm::omp::getOpenMPClauseName(clause); } diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index ccf3b06cf4d72..e959fb751cc99 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -218,6 +218,8 @@ class OmpStructureChecker const parser::OmpObjectList &, const llvm::omp::Clause); void GetSymbolsInObjectList(const parser::OmpObjectList &, SymbolSourceMap &); void CheckDefinableObjects(SymbolSourceMap &, const llvm::omp::Clause); + void CheckCopyingPolymorphicAllocatable( + SymbolSourceMap &, const llvm::omp::Clause); void CheckPrivateSymbolsInOuterCxt( SymbolSourceMap &, DirectivesClauseTriple &, const llvm::omp::Clause); const parser::Name GetLoopIndex(const parser::DoConstruct *x); diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index d8b7729a59d37..1d7026cc5e3c2 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -249,20 +249,6 @@ MaybeExpr ExpressionAnalyzer::CompleteSubscripts(ArrayRef &&ref) { symbolRank, symbol.name(), subscripts); } return std::nullopt; - } else if (Component * component{ref.base().UnwrapComponent()}) { - int baseRank{component->base().Rank()}; - if (baseRank > 0) { - int subscriptRank{0}; - for (const auto &expr : ref.subscript()) { - subscriptRank += expr.Rank(); - } - if (subscriptRank > 0) { // C919a - Say("Subscripts of component '%s' of rank-%d derived type " - "array have rank %d but must all be scalar"_err_en_US, - symbol.name(), baseRank, subscriptRank); - return std::nullopt; - } - } } else if (const auto *object{ symbol.detailsIf()}) { // C928 & C1002 @@ -306,21 +292,47 @@ MaybeExpr ExpressionAnalyzer::ApplySubscripts( std::move(dataRef.u)); } -// Top-level checks for data references. -MaybeExpr ExpressionAnalyzer::TopLevelChecks(DataRef &&dataRef) { - if (Component * component{std::get_if(&dataRef.u)}) { - const Symbol &symbol{component->GetLastSymbol()}; - int componentRank{symbol.Rank()}; - if (componentRank > 0) { - int baseRank{component->base().Rank()}; - if (baseRank > 0) { // C919a - Say("Reference to whole rank-%d component '%%%s' of " - "rank-%d array of derived type is not allowed"_err_en_US, - componentRank, symbol.name(), baseRank); - } - } - } - return Designate(std::move(dataRef)); +// C919a - only one part-ref of a data-ref may have rank > 0 +bool ExpressionAnalyzer::CheckRanks(const DataRef &dataRef) { + return common::visit( + common::visitors{ + [this](const Component &component) { + const Symbol &symbol{component.GetLastSymbol()}; + if (int componentRank{symbol.Rank()}; componentRank > 0) { + if (int baseRank{component.base().Rank()}; baseRank > 0) { + Say("Reference to whole rank-%d component '%s' of rank-%d array of derived type is not allowed"_err_en_US, + componentRank, symbol.name(), baseRank); + return false; + } + } else { + return CheckRanks(component.base()); + } + return true; + }, + [this](const ArrayRef &arrayRef) { + if (const auto *component{arrayRef.base().UnwrapComponent()}) { + int subscriptRank{0}; + for (const Subscript &subscript : arrayRef.subscript()) { + subscriptRank += subscript.Rank(); + } + if (subscriptRank > 0) { + if (int componentBaseRank{component->base().Rank()}; + componentBaseRank > 0) { + Say("Subscripts of component '%s' of rank-%d derived type array have rank %d but must all be scalar"_err_en_US, + component->GetLastSymbol().name(), componentBaseRank, + subscriptRank); + return false; + } + } else { + return CheckRanks(component->base()); + } + } + return true; + }, + [](const SymbolRef &) { return true; }, + [](const CoarrayRef &) { return true; }, + }, + dataRef.u); } // Parse tree correction after a substring S(j:k) was misparsed as an @@ -369,11 +381,22 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Designator &d) { FixMisparsedSubstring(d); // These checks have to be deferred to these "top level" data-refs where // we can be sure that there are no following subscripts (yet). - // Substrings have already been run through TopLevelChecks() and - // won't be returned by ExtractDataRef(). if (MaybeExpr result{Analyze(d.u)}) { if (std::optional dataRef{ExtractDataRef(std::move(result))}) { - return TopLevelChecks(std::move(*dataRef)); + if (!CheckRanks(std::move(*dataRef))) { + return std::nullopt; + } + return Designate(std::move(*dataRef)); + } else if (std::optional dataRef{ + ExtractDataRef(std::move(result), /*intoSubstring=*/true)}) { + if (!CheckRanks(std::move(*dataRef))) { + return std::nullopt; + } + } else if (std::optional dataRef{ExtractDataRef(std::move(result), + /*intoSubstring=*/false, /*intoComplexPart=*/true)}) { + if (!CheckRanks(std::move(*dataRef))) { + return std::nullopt; + } } return result; } @@ -826,7 +849,7 @@ std::optional> ExpressionAnalyzer::GetSubstringBound( MaybeExpr ExpressionAnalyzer::Analyze(const parser::Substring &ss) { if (MaybeExpr baseExpr{Analyze(std::get(ss.t))}) { if (std::optional dataRef{ExtractDataRef(std::move(*baseExpr))}) { - if (MaybeExpr newBaseExpr{TopLevelChecks(std::move(*dataRef))}) { + if (MaybeExpr newBaseExpr{Designate(std::move(*dataRef))}) { if (std::optional checked{ ExtractDataRef(std::move(*newBaseExpr))}) { const parser::SubstringRange &range{ @@ -1954,13 +1977,16 @@ auto ExpressionAnalyzer::AnalyzeProcedureComponentRef( return std::nullopt; } } + std::optional dataRef{ExtractDataRef(std::move(*dtExpr))}; + if (dataRef.has_value() && !CheckRanks(std::move(*dataRef))) { + return std::nullopt; + } if (const Symbol * resolution{GetBindingResolution(dtExpr->GetType(), *sym)}) { AddPassArg(arguments, std::move(*dtExpr), *sym, false); return CalleeAndArguments{ ProcedureDesignator{*resolution}, std::move(arguments)}; - } else if (std::optional dataRef{ - ExtractDataRef(std::move(*dtExpr))}) { + } else if (dataRef.has_value()) { if (sym->attrs().test(semantics::Attr::NOPASS)) { return CalleeAndArguments{ ProcedureDesignator{Component{std::move(*dataRef), *sym}}, diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index 2ba8918f88473..d97b81786e7fe 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -518,8 +518,14 @@ void ModFileWriter::PutGeneric(const Symbol &symbol) { void ModFileWriter::PutUse(const Symbol &symbol) { auto &details{symbol.get()}; auto &use{details.symbol()}; - uses_ << "use " << GetUsedModule(details).name(); - PutGenericName(uses_ << ",only:", symbol); + const Symbol &module{GetUsedModule(details)}; + if (use.owner().parent().IsIntrinsicModules()) { + uses_ << "use,intrinsic::"; + } else { + uses_ << "use "; + } + uses_ << module.name() << ",only:"; + PutGenericName(uses_, symbol); // Can have intrinsic op with different local-name and use-name // (e.g. `operator(<)` and `operator(.lt.)`) but rename is not allowed if (!IsIntrinsicOp(symbol) && use.name() != symbol.name()) { @@ -953,6 +959,7 @@ Scope *ModFileReader::Read(const SourceName &name, std::remove(options.searchDirectories.begin(), options.searchDirectories.end(), dir); } + options.searchDirectories.insert(options.searchDirectories.begin(), "."s); } if (isIntrinsic.value_or(true)) { for (const auto &dir : context_.intrinsicModuleDirectories()) { diff --git a/flang/lib/Semantics/resolve-labels.cpp b/flang/lib/Semantics/resolve-labels.cpp index b099d24070cc7..c54740033b10d 100644 --- a/flang/lib/Semantics/resolve-labels.cpp +++ b/flang/lib/Semantics/resolve-labels.cpp @@ -233,13 +233,16 @@ class ParseTreeAnalyzer { using LabeledConstructEndStmts = std::tuple; + parser::EndIfStmt, parser::EndWhereStmt>; using LabeledProgramUnitEndStmts = std::tuple; auto targetFlags{ConstructBranchTargetFlags(statement)}; if constexpr (common::HasMember) { AddTargetLabelDefinition(label.value(), targetFlags, ParentScope()); + } else if constexpr (std::is_same_v) { + // the label on an END SELECT is not in the last case + AddTargetLabelDefinition(label.value(), targetFlags, ParentScope(), true); } else if constexpr (common::HasMember) { constexpr bool isExecutableConstructEndStmt{true}; AddTargetLabelDefinition(label.value(), targetFlags, currentScope_, @@ -286,19 +289,23 @@ class ParseTreeAnalyzer { bool Pre(const parser::CaseConstruct &caseConstruct) { return PushConstructName(caseConstruct); } + void Post(const parser::SelectCaseStmt &) { PushScope(); } bool Pre(const parser::CaseConstruct::Case &) { return SwitchToNewScope(); } bool Pre(const parser::SelectRankConstruct &selectRankConstruct) { return PushConstructName(selectRankConstruct); } + void Post(const parser::SelectRankStmt &) { PushScope(); } bool Pre(const parser::SelectRankConstruct::RankCase &) { return SwitchToNewScope(); } bool Pre(const parser::SelectTypeConstruct &selectTypeConstruct) { return PushConstructName(selectTypeConstruct); } + void Post(const parser::SelectTypeStmt &) { PushScope(); } bool Pre(const parser::SelectTypeConstruct::TypeCase &) { return SwitchToNewScope(); } + void Post(const parser::EndSelectStmt &) { PopScope(); } bool Pre(const parser::WhereConstruct &whereConstruct) { return PushConstructName(whereConstruct); } @@ -994,7 +1001,7 @@ void CheckScopeConstraints(const SourceStmtList &stmts, context.Say(position, isFatal ? "Label '%u' is in a construct that prevents its use as a branch target here"_err_en_US - : "Label '%u' is in a construct that prevents its use as a branch target here"_en_US, + : "Label '%u' is in a construct that should not be used as a branch target here"_warn_en_US, SayLabel(label)); } } diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 4c34392ecdc84..d5e883feedfd9 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1674,7 +1674,19 @@ void AttrsVisitor::SetBindNameOn(Symbol &symbol) { } else { label = parser::ToLowerCaseLetters(symbol.name().ToString()); } + // Check if a symbol has two Bind names. + std::string oldBindName; + if (symbol.GetBindName()) { + oldBindName = *symbol.GetBindName(); + } symbol.SetBindName(std::move(*label)); + if (!oldBindName.empty()) { + if (const std::string * newBindName{symbol.GetBindName()}) { + if (oldBindName.compare(*newBindName) != 0) { + Say(symbol.name(), "The entity '%s' has multiple BIND names"_err_en_US); + } + } + } } void AttrsVisitor::Post(const parser::LanguageBindingSpec &x) { @@ -2698,15 +2710,23 @@ ModuleVisitor::SymbolRename ModuleVisitor::AddUse( // symbol must be either a Use or a Generic formed by merging two uses. // Convert it to a UseError with this additional location. -static void ConvertToUseError( +static bool ConvertToUseError( Symbol &symbol, const SourceName &location, const Scope &module) { const auto *useDetails{symbol.detailsIf()}; if (!useDetails) { - auto &genericDetails{symbol.get()}; - useDetails = &genericDetails.uses().at(0)->get(); + if (auto *genericDetails{symbol.detailsIf()}) { + if (!genericDetails->uses().empty()) { + useDetails = &genericDetails->uses().at(0)->get(); + } + } + } + if (useDetails) { + symbol.set_details( + UseErrorDetails{*useDetails}.add_occurrence(location, module)); + return true; + } else { + return false; } - symbol.set_details( - UseErrorDetails{*useDetails}.add_occurrence(location, module)); } // If a symbol has previously been USE-associated and did not appear in a USE @@ -2807,9 +2827,7 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName, } } if (!combine) { - if (localSymbol.has() || localSymbol.has()) { - ConvertToUseError(localSymbol, location, *useModuleScope_); - } else { + if (!ConvertToUseError(localSymbol, location, *useModuleScope_)) { Say(location, "Cannot use-associate '%s'; it is already declared in this scope"_err_en_US, localName) @@ -5233,7 +5251,7 @@ void DeclarationVisitor::CheckSaveStmts() { } else if (specPartState_.saveInfo.saveAll) { // C889 - note that pgi, ifort, xlf do not enforce this constraint Say2(name, - "Explicit SAVE of '%s' is redundant due to global SAVE statement"_err_en_US, + "Explicit SAVE of '%s' is redundant due to global SAVE statement"_warn_en_US, *specPartState_.saveInfo.saveAll, "Global SAVE statement"_en_US); } else if (auto msg{CheckSaveAttr(*symbol)}) { Say(name, std::move(*msg)); @@ -5341,6 +5359,9 @@ void DeclarationVisitor::CheckCommonBlocks() { } else if (attrs.test(Attr::BIND_C)) { Say(name, "Variable '%s' with BIND attribute may not appear in a COMMON block"_err_en_US); + } else if (IsNamedConstant(*symbol)) { + Say(name, + "A named constant '%s' may not appear in a COMMON block"_err_en_US); } else if (IsDummy(*symbol)) { Say(name, "Dummy argument '%s' may not appear in a COMMON block"_err_en_US); diff --git a/flang/lib/Semantics/rewrite-parse-tree.cpp b/flang/lib/Semantics/rewrite-parse-tree.cpp index 1e0b9105dda8f..8fb7673bbfac2 100644 --- a/flang/lib/Semantics/rewrite-parse-tree.cpp +++ b/flang/lib/Semantics/rewrite-parse-tree.cpp @@ -79,6 +79,19 @@ void RewriteMutator::Post(parser::Name &name) { } } +static bool ReturnsDataPointer(const Symbol &symbol) { + if (const Symbol * funcRes{FindFunctionResult(symbol)}) { + return IsPointer(*funcRes) && !IsProcedure(*funcRes); + } else if (const auto *generic{symbol.detailsIf()}) { + for (auto ref : generic->specificProcs()) { + if (ReturnsDataPointer(*ref)) { + return true; + } + } + } + return false; +} + // Find mis-parsed statement functions and move to stmtFuncsToConvert_ list. void RewriteMutator::Post(parser::SpecificationPart &x) { auto &list{std::get>(x.t)}; @@ -87,9 +100,9 @@ void RewriteMutator::Post(parser::SpecificationPart &x) { if (auto *stmt{std::get_if(&it->u)}) { if (const Symbol * symbol{std::get(stmt->statement.value().t).symbol}) { - const Symbol *funcRes{FindFunctionResult(*symbol)}; - isAssignment = symbol->has() || - (funcRes && IsPointer(*funcRes) && !IsProcedure(*funcRes)); + const Symbol &ultimate{symbol->GetUltimate()}; + isAssignment = + ultimate.has() || ReturnsDataPointer(ultimate); if (isAssignment) { stmtFuncsToConvert_.emplace_back(std::move(*stmt)); } diff --git a/flang/module/__fortran_ieee_exceptions.f90 b/flang/module/__fortran_ieee_exceptions.f90 index 7232bbf53cd61..0b620f55cee84 100644 --- a/flang/module/__fortran_ieee_exceptions.f90 +++ b/flang/module/__fortran_ieee_exceptions.f90 @@ -124,13 +124,13 @@ end subroutine ieee_set_status end interface #define IEEE_SUPPORT_FLAG_R(XKIND) \ - logical function ieee_support_flag_a##XKIND(flag, x); \ + pure logical function ieee_support_flag_a##XKIND(flag, x); \ import ieee_flag_type; \ type(ieee_flag_type), intent(in) :: flag; \ real(XKIND), intent(in) :: x(..); \ end function ieee_support_flag_a##XKIND; interface ieee_support_flag - logical function ieee_support_flag(flag) + pure logical function ieee_support_flag(flag) import ieee_flag_type type(ieee_flag_type), intent(in) :: flag end function ieee_support_flag diff --git a/flang/module/ieee_arithmetic.f90 b/flang/module/ieee_arithmetic.f90 index b2ac217aa86ae..365f803aca71e 100644 --- a/flang/module/ieee_arithmetic.f90 +++ b/flang/module/ieee_arithmetic.f90 @@ -514,7 +514,7 @@ pure logical function ieee_support_rounding_a##XKIND(round_value, x); \ real(XKIND), intent(in) :: x(..); \ end function ieee_support_rounding_a##XKIND; interface ieee_support_rounding - logical function ieee_support_rounding(round_value) + pure logical function ieee_support_rounding(round_value) import ieee_round_type type(ieee_round_type), intent(in) :: round_value end function ieee_support_rounding diff --git a/flang/runtime/complex-reduction.c b/flang/runtime/complex-reduction.c index 0e40c047adee6..d77e1c0a55006 100644 --- a/flang/runtime/complex-reduction.c +++ b/flang/runtime/complex-reduction.c @@ -8,7 +8,7 @@ */ #include "complex-reduction.h" -#include "flang/Common/long-double.h" +#include struct CppComplexFloat { float r, i; @@ -90,10 +90,10 @@ ADAPT_REDUCTION(SumComplex4, float_Complex_t, CppComplexFloat, CMPLXF, REDUCTION_ARGS, REDUCTION_ARG_NAMES) ADAPT_REDUCTION(SumComplex8, double_Complex_t, CppComplexDouble, CMPLX, REDUCTION_ARGS, REDUCTION_ARG_NAMES) -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 ADAPT_REDUCTION(SumComplex10, long_double_Complex_t, CppComplexLongDouble, CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES) -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 ADAPT_REDUCTION(SumComplex16, long_double_Complex_t, CppComplexLongDouble, CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES) #endif @@ -103,10 +103,10 @@ ADAPT_REDUCTION(ProductComplex4, float_Complex_t, CppComplexFloat, CMPLXF, REDUCTION_ARGS, REDUCTION_ARG_NAMES) ADAPT_REDUCTION(ProductComplex8, double_Complex_t, CppComplexDouble, CMPLX, REDUCTION_ARGS, REDUCTION_ARG_NAMES) -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 ADAPT_REDUCTION(ProductComplex10, long_double_Complex_t, CppComplexLongDouble, CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES) -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 ADAPT_REDUCTION(ProductComplex16, long_double_Complex_t, CppComplexLongDouble, CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES) #endif @@ -116,10 +116,10 @@ ADAPT_REDUCTION(DotProductComplex4, float_Complex_t, CppComplexFloat, CMPLXF, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) ADAPT_REDUCTION(DotProductComplex8, double_Complex_t, CppComplexDouble, CMPLX, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 ADAPT_REDUCTION(DotProductComplex10, long_double_Complex_t, CppComplexLongDouble, CMPLXL, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 ADAPT_REDUCTION(DotProductComplex16, long_double_Complex_t, CppComplexLongDouble, CMPLXL, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) #endif diff --git a/flang/runtime/dot-product.cpp b/flang/runtime/dot-product.cpp index 4b28732228593..2f9debbfccaa0 100644 --- a/flang/runtime/dot-product.cpp +++ b/flang/runtime/dot-product.cpp @@ -6,11 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "float.h" #include "terminator.h" #include "tools.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" #include "flang/Runtime/reduction.h" +#include #include namespace Fortran::runtime { @@ -178,13 +180,14 @@ double RTNAME(DotProductReal8)( const Descriptor &x, const Descriptor &y, const char *source, int line) { return DotProduct{}(x, y, source, line); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 long double RTNAME(DotProductReal10)( const Descriptor &x, const Descriptor &y, const char *source, int line) { return DotProduct{}(x, y, source, line); } -#elif LONG_DOUBLE == 128 -long double RTNAME(DotProductReal16)( +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +CppTypeFor RTNAME(DotProductReal16)( const Descriptor &x, const Descriptor &y, const char *source, int line) { return DotProduct{}(x, y, source, line); } @@ -200,13 +203,13 @@ void RTNAME(CppDotProductComplex8)(std::complex &result, const Descriptor &x, const Descriptor &y, const char *source, int line) { result = DotProduct{}(x, y, source, line); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 void RTNAME(CppDotProductComplex10)(std::complex &result, const Descriptor &x, const Descriptor &y, const char *source, int line) { result = DotProduct{}(x, y, source, line); } -#elif LONG_DOUBLE == 128 -void RTNAME(CppDotProductComplex16)(std::complex &result, +#elif LDBL_MANT_DIG == 113 +void RTNAME(CppDotProductComplex16)(std::complex &result, const Descriptor &x, const Descriptor &y, const char *source, int line) { result = DotProduct{}(x, y, source, line); } diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp index 7e53b54f59949..57a935fd57658 100644 --- a/flang/runtime/edit-input.cpp +++ b/flang/runtime/edit-input.cpp @@ -21,14 +21,16 @@ static bool EditBOZInput( IoStatementState &io, const DataEdit &edit, void *n, std::size_t bytes) { std::optional remaining; std::optional next{io.PrepareInput(edit, remaining)}; - if (*next == '0') { + if (next.value_or('?') == '0') { do { next = io.NextInField(remaining, edit); } while (next && *next == '0'); } // Count significant digits after any leading white space & zeroes int digits{0}; + int chars{0}; for (; next; next = io.NextInField(remaining, edit)) { + ++chars; char32_t ch{*next}; if (ch == ' ' || ch == '\t') { continue; @@ -52,7 +54,7 @@ static bool EditBOZInput( return false; } // Reset to start of significant digits - io.HandleRelativePosition(-digits); + io.HandleRelativePosition(-chars); remaining.reset(); // Make a second pass now that the digit count is known std::memset(n, 0, bytes); @@ -297,7 +299,9 @@ static int ScanRealInput(char *buffer, int bufferSize, IoStatementState &io, } for (exponent = 0; next; next = io.NextInField(remaining, edit)) { if (*next >= '0' && *next <= '9') { - exponent = 10 * exponent + *next - '0'; + if (exponent < 10000) { + exponent = 10 * exponent + *next - '0'; + } } else if (*next == ' ' || *next == '\t') { if (bzMode) { exponent = 10 * exponent; @@ -392,7 +396,7 @@ static bool TryFastPathRealInput( const char *limit{str + maxConsume}; decimal::ConversionToBinaryResult converted{ decimal::ConvertToBinary(p, edit.modes.round, limit)}; - if (converted.flags & decimal::Invalid) { + if (converted.flags & (decimal::Invalid | decimal::Overflow)) { return false; } if (edit.digits.value_or(0) != 0) { @@ -505,6 +509,10 @@ bool EditCommonRealInput(IoStatementState &io, const DataEdit &edit, void *n) { converted.binary; // Set FP exception flags if (converted.flags != decimal::ConversionResultFlags::Exact) { + if (converted.flags & decimal::ConversionResultFlags::Overflow) { + io.GetIoErrorHandler().SignalError(IostatRealInputOverflow); + return false; + } RaiseFPExceptions(converted.flags); } return true; diff --git a/flang/runtime/edit-output.cpp b/flang/runtime/edit-output.cpp index eca27e3e2c0cf..9b25ef2fba16f 100644 --- a/flang/runtime/edit-output.cpp +++ b/flang/runtime/edit-output.cpp @@ -21,7 +21,11 @@ static bool EditBOZOutput(IoStatementState &io, const DataEdit &edit, const unsigned char *data0, std::size_t bytes) { int digits{static_cast((bytes * 8) / LOG2_BASE)}; int get{static_cast(bytes * 8) - digits * LOG2_BASE}; - get = get ? get : LOG2_BASE; + if (get > 0) { + ++digits; + } else { + get = LOG2_BASE; + } int shift{7}; int increment{isHostLittleEndian ? -1 : 1}; const unsigned char *data{data0 + (isHostLittleEndian ? bytes - 1 : 0)}; @@ -178,8 +182,10 @@ const char *RealOutputEditingBase::FormatExponent( *--exponent = '0' + e - 10 * quotient; e = quotient; } + bool overflow{false}; if (edit.expoDigits) { if (int ed{*edit.expoDigits}) { // Ew.dEe with e > 0 + overflow = exponent + ed < eEnd; while (exponent > exponent_ + 2 /*E+*/ && exponent + ed > eEnd) { *--exponent = '0'; } @@ -196,7 +202,7 @@ const char *RealOutputEditingBase::FormatExponent( *--exponent = edit.descriptor == 'D' ? 'D' : 'E'; // not 'G' } length = eEnd - exponent; - return exponent; + return overflow ? nullptr : exponent; } bool RealOutputEditingBase::EmitPrefix( @@ -254,9 +260,14 @@ bool RealOutputEditing::EditEorDOutput(const DataEdit &edit) { if (edit.modes.editingFlags & signPlus) { flags |= decimal::AlwaysSign; } + bool noLeadingSpaces{editWidth == 0}; if (editWidth == 0) { // "the processor selects the field width" if (edit.digits.has_value()) { // E0.d - editWidth = editDigits + 6; // -.666E+ee + if (editDigits == 0) { // E0.0 + editWidth = 7; // -.0E+ee + } else { + editWidth = editDigits + 6; // -.666E+ee + } } else { // E0 flags |= decimal::Minimize; significantDigits = @@ -265,9 +276,15 @@ bool RealOutputEditing::EditEorDOutput(const DataEdit &edit) { } bool isEN{edit.variation == 'N'}; bool isES{edit.variation == 'S'}; - int scale{isEN || isES ? 1 : edit.modes.scale}; // 'kP' value + int scale{edit.modes.scale}; // 'kP' value int zeroesAfterPoint{0}; - if (scale < 0) { + if (isEN) { + scale = IsZero() ? 1 : 3; + significantDigits += scale; + } else if (isES) { + scale = 1; + ++significantDigits; + } else if (scale < 0) { if (scale <= -editDigits) { io_.GetIoErrorHandler().SignalError(IostatBadScaleFactor, "Scale factor (kP) %d cannot be less than -d (%d)", scale, @@ -286,7 +303,7 @@ bool RealOutputEditing::EditEorDOutput(const DataEdit &edit) { ++significantDigits; scale = std::min(scale, significantDigits + 1); } - // In EN editing, multiple attempts may be necessary, so it's in a loop. + // In EN editing, multiple attempts may be necessary, so this is a loop. while (true) { decimal::ConversionToDecimalResult converted{ Convert(significantDigits, edit.modes.round, flags)}; @@ -297,12 +314,29 @@ bool RealOutputEditing::EditEorDOutput(const DataEdit &edit) { if (!IsZero()) { converted.decimalExponent -= scale; } - if (isEN && scale < 3 && (converted.decimalExponent % 3) != 0) { - // EN mode: boost the scale and significant digits, try again; need - // an effective exponent field that's a multiple of three. - ++scale; - ++significantDigits; - continue; + if (isEN) { + // EN mode: we need an effective exponent field that is + // a multiple of three. + if (int modulus{converted.decimalExponent % 3}; modulus != 0) { + if (significantDigits > 1) { + --significantDigits; + --scale; + continue; + } + // Rounded nines up to a 1. + scale += modulus; + converted.decimalExponent -= modulus; + } + if (scale > 3) { + int adjust{3 * (scale / 3)}; + scale -= adjust; + converted.decimalExponent += adjust; + } else if (scale < 1) { + int adjust{3 - 3 * (scale / 3)}; + scale += adjust; + converted.decimalExponent -= adjust; + } + significantDigits = editDigits + scale; } // Format the exponent (see table 13.1 for all the cases) int expoLength{0}; @@ -321,7 +355,7 @@ bool RealOutputEditing::EditEorDOutput(const DataEdit &edit) { 1 /*'.'*/ + zeroesAfterPoint + digitsAfterPoint + trailingZeroes + expoLength}; int width{editWidth > 0 ? editWidth : totalLength}; - if (totalLength > width) { + if (totalLength > width || !exponent) { return io_.EmitRepeated('*', width); } if (totalLength < width && digitsBeforePoint == 0 && @@ -329,6 +363,9 @@ bool RealOutputEditing::EditEorDOutput(const DataEdit &edit) { zeroesBeforePoint = 1; ++totalLength; } + if (totalLength < width && noLeadingSpaces) { + width = totalLength; + } return EmitPrefix(edit, totalLength, width) && io_.Emit(converted.str, signLength + digitsBeforePoint) && io_.EmitRepeated('0', zeroesBeforePoint) && @@ -444,9 +481,10 @@ bool RealOutputEditing::EditFOutput(const DataEdit &edit) { template DataEdit RealOutputEditing::EditForGOutput(DataEdit edit) { edit.descriptor = 'E'; + int editWidth{edit.width.value_or(0)}; int significantDigits{ edit.digits.value_or(BinaryFloatingPoint::decimalPrecision)}; // 'd' - if (!edit.width.has_value() || (*edit.width > 0 && significantDigits == 0)) { + if (editWidth > 0 && significantDigits == 0) { return edit; // Gw.0 -> Ew.0 for w > 0 } int flags{0}; @@ -456,7 +494,7 @@ DataEdit RealOutputEditing::EditForGOutput(DataEdit edit) { decimal::ConversionToDecimalResult converted{ Convert(significantDigits, edit.modes.round, flags)}; if (IsInfOrNaN(converted)) { - return edit; + return edit; // Inf/Nan -> Ew.d (same as Fw.d) } int expo{IsZero() ? 1 : converted.decimalExponent}; // 's' if (expo < 0 || expo > significantDigits) { @@ -465,7 +503,6 @@ DataEdit RealOutputEditing::EditForGOutput(DataEdit edit) { edit.descriptor = 'F'; edit.modes.scale = 0; // kP is ignored for G when no exponent field trailingBlanks_ = 0; - int editWidth{edit.width.value_or(0)}; if (editWidth > 0) { int expoDigits{edit.expoDigits.value_or(0)}; trailingBlanks_ = expoDigits > 0 ? expoDigits + 2 : 4; // 'n' diff --git a/flang/runtime/edit-output.h b/flang/runtime/edit-output.h index bd1377e3a18c4..765e41f89827d 100644 --- a/flang/runtime/edit-output.h +++ b/flang/runtime/edit-output.h @@ -52,6 +52,7 @@ class RealOutputEditingBase { return *p < '0' || *p > '9'; } + // Returns null when the exponent overflows a fixed-size output field. const char *FormatExponent(int, const DataEdit &edit, int &length); bool EmitPrefix(const DataEdit &, std::size_t length, std::size_t width); bool EmitSuffix(const DataEdit &); diff --git a/flang/runtime/extrema.cpp b/flang/runtime/extrema.cpp index a2634d71ffda8..709a032911d46 100644 --- a/flang/runtime/extrema.cpp +++ b/flang/runtime/extrema.cpp @@ -11,10 +11,11 @@ // NORM2 using common infrastructure. #include "reduction-templates.h" -#include "flang/Common/long-double.h" #include "flang/Runtime/character.h" +#include "flang/Runtime/float128.h" #include "flang/Runtime/reduction.h" #include +#include #include #include #include @@ -511,13 +512,14 @@ CppTypeFor RTNAME(MaxvalReal8)(const Descriptor &x, return TotalNumericMaxOrMin( x, source, line, dim, mask, "MAXVAL"); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(MaxvalReal10)(const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return TotalNumericMaxOrMin( x, source, line, dim, mask, "MAXVAL"); } -#elif LONG_DOUBLE == 128 +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(MaxvalReal16)(const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return TotalNumericMaxOrMin( @@ -570,13 +572,14 @@ CppTypeFor RTNAME(MinvalReal8)(const Descriptor &x, return TotalNumericMaxOrMin( x, source, line, dim, mask, "MINVAL"); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(MinvalReal10)(const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return TotalNumericMaxOrMin( x, source, line, dim, mask, "MINVAL"); } -#elif LONG_DOUBLE == 128 +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(MinvalReal16)(const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return TotalNumericMaxOrMin( @@ -612,8 +615,19 @@ void RTNAME(MinvalDim)(Descriptor &result, const Descriptor &x, int dim, template class Norm2Accumulator { public: using Type = CppTypeFor; - // Use at least double precision for accumulators - using AccumType = CppTypeFor; + // Use at least double precision for accumulators. + // Don't use __float128, it doesn't work with abs() or sqrt() yet. + static constexpr int largestLDKind { +#if LDBL_MANT_DIG == 113 + 16 +#elif LDBL_MANT_DIG == 64 + 10 +#else + 8 +#endif + }; + using AccumType = CppTypeFor; explicit Norm2Accumulator(const Descriptor &array) : array_{array} {} void Reinitialize() { max_ = sum_ = 0; } template void GetResult(A *p, int /*zeroBasedDim*/ = -1) const { @@ -621,7 +635,7 @@ template class Norm2Accumulator { *p = static_cast(max_ * std::sqrt(1 + sum_)); } bool Accumulate(Type x) { - auto absX{AccumType{std::abs(x)}}; + auto absX{std::abs(static_cast(x))}; if (!max_) { max_ = x; } else if (absX > max_) { @@ -666,13 +680,14 @@ CppTypeFor RTNAME(Norm2_8)(const Descriptor &x, return GetTotalReduction( x, source, line, dim, mask, Norm2Accumulator<8>{x}, "NORM2"); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Norm2_10)(const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction( x, source, line, dim, mask, Norm2Accumulator<10>{x}, "NORM2"); } -#elif LONG_DOUBLE == 128 +#endif +#if LDBL_MANT_DIG == 113 CppTypeFor RTNAME(Norm2_16)(const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction( diff --git a/flang/runtime/file.cpp b/flang/runtime/file.cpp index d1744c053e8db..8ff9724762858 100644 --- a/flang/runtime/file.cpp +++ b/flang/runtime/file.cpp @@ -97,12 +97,18 @@ void OpenFile::Open(OpenStatus status, std::optional action, flags |= O_TRUNC; } if (!action) { - // Try to open read/write, back off to read-only on failure + // Try to open read/write, back off to read-only or even write-only + // on failure fd_ = ::open(path_.get(), flags | O_RDWR, 0600); if (fd_ >= 0) { action = Action::ReadWrite; } else { - action = Action::Read; + fd_ = ::open(path_.get(), flags | O_RDONLY, 0600); + if (fd_ >= 0) { + action = Action::Read; + } else { + action = Action::Write; + } } } if (fd_ < 0) { @@ -126,7 +132,7 @@ void OpenFile::Open(OpenStatus status, std::optional action, RUNTIME_CHECK(handler, action.has_value()); pending_.reset(); if (position == Position::Append && !RawSeekToEnd()) { - handler.SignalErrno(); + handler.SignalError(IostatOpenBadAppend); } isTerminal_ = ::isatty(fd_) == 1; mayRead_ = *action != Action::Write; @@ -371,7 +377,7 @@ bool OpenFile::Seek(FileOffset at, IoErrorHandler &handler) { SetPosition(at); return true; } else { - handler.SignalErrno(); + handler.SignalError(IostatCannotReposition); return false; } } @@ -434,4 +440,17 @@ bool MayWrite(const char *path) { return ::access(path, W_OK) == 0; } bool MayReadAndWrite(const char *path) { return ::access(path, R_OK | W_OK) == 0; } + +std::int64_t SizeInBytes(const char *path) { +#ifndef _WIN32 + struct stat buf; + if (::stat(path, &buf) == 0) { + return buf.st_size; + } +#else // TODO: _WIN32 +#endif + // No Fortran compiler signals an error + return -1; +} + } // namespace Fortran::runtime::io diff --git a/flang/runtime/file.h b/flang/runtime/file.h index 712b2045532ba..a0712136a7f3d 100644 --- a/flang/runtime/file.h +++ b/flang/runtime/file.h @@ -28,8 +28,8 @@ class OpenFile { using FileOffset = std::int64_t; const char *path() const { return path_.get(); } - void set_path(OwningPtr &&, std::size_t bytes); std::size_t pathLength() const { return pathLength_; } + void set_path(OwningPtr &&, std::size_t bytes); bool mayRead() const { return mayRead_; } bool mayWrite() const { return mayWrite_; } bool mayPosition() const { return mayPosition_; } @@ -109,5 +109,6 @@ bool IsExtant(const char *path); bool MayRead(const char *path); bool MayWrite(const char *path); bool MayReadAndWrite(const char *path); +std::int64_t SizeInBytes(const char *path); } // namespace Fortran::runtime::io #endif // FORTRAN_RUNTIME_FILE_H_ diff --git a/flang/runtime/findloc.cpp b/flang/runtime/findloc.cpp index 6a3aaef882072..339e0c75f05fe 100644 --- a/flang/runtime/findloc.cpp +++ b/flang/runtime/findloc.cpp @@ -10,7 +10,6 @@ // integer kinds. #include "reduction-templates.h" -#include "flang/Common/long-double.h" #include "flang/Runtime/character.h" #include "flang/Runtime/reduction.h" #include diff --git a/flang/runtime/format-implementation.h b/flang/runtime/format-implementation.h index ab2fad3188bd9..cec51d8d957e4 100644 --- a/flang/runtime/format-implementation.h +++ b/flang/runtime/format-implementation.h @@ -434,6 +434,11 @@ DataEdit FormatControl::GetNextDataEdit( } else if (edit.descriptor != DataEdit::DefinedDerivedType) { edit.width = GetIntField(context); } + if constexpr (std::is_base_of_v) { + if (edit.width.value_or(-1) == 0) { + ReportBadFormat(context, "Input field width is zero", start); + } + } if (edit.descriptor != DataEdit::DefinedDerivedType && PeekNext() == '.') { ++offset_; edit.digits = GetIntField(context); diff --git a/flang/runtime/internal-unit.cpp b/flang/runtime/internal-unit.cpp index 39a8e4b2c9c4e..9f1d6c572c327 100644 --- a/flang/runtime/internal-unit.cpp +++ b/flang/runtime/internal-unit.cpp @@ -41,7 +41,9 @@ template void InternalDescriptorUnit::EndIoStatement() { if constexpr (DIR == Direction::Output) { // Clear the remainder of the current record if anything was written // to it, or if it is the only record. - if (endfileRecordNumber.value_or(-1) == 2 || furthestPositionInRecord > 0) { + auto end{endfileRecordNumber.value_or(0)}; + if (currentRecordNumber < end && + (end == 2 || furthestPositionInRecord > 0)) { BlankFillOutputRecord(); } } diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp index a50f01131b7af..42f4c2bcc7600 100644 --- a/flang/runtime/io-api.cpp +++ b/flang/runtime/io-api.cpp @@ -172,7 +172,7 @@ Cookie BeginExternalListIO( *child, sourceFile, sourceLine); } else { return &child->BeginIoStatement( - iostat, sourceFile, sourceLine); + iostat, nullptr /* no unit */, sourceFile, sourceLine); } } else { if (iostat == IostatOk && unit.access == Access::Direct) { @@ -186,7 +186,7 @@ Cookie BeginExternalListIO( std::forward(xs)..., unit, sourceFile, sourceLine); } else { return &unit.BeginIoStatement( - iostat, sourceFile, sourceLine); + iostat, &unit, sourceFile, sourceLine); } } } @@ -228,7 +228,7 @@ Cookie BeginExternalFormattedIO(const char *format, std::size_t formatLength, *child, format, formatLength, sourceFile, sourceLine); } else { return &child->BeginIoStatement( - iostat, sourceFile, sourceLine); + iostat, nullptr /* no unit */, sourceFile, sourceLine); } } else { if (iostat == IostatOk) { @@ -239,7 +239,7 @@ Cookie BeginExternalFormattedIO(const char *format, std::size_t formatLength, unit, format, formatLength, sourceFile, sourceLine); } else { return &unit.BeginIoStatement( - iostat, sourceFile, sourceLine); + iostat, &unit, sourceFile, sourceLine); } } } @@ -280,7 +280,7 @@ Cookie BeginUnformattedIO( *child, sourceFile, sourceLine); } else { return &child->BeginIoStatement( - iostat, sourceFile, sourceLine); + iostat, nullptr /* no unit */, sourceFile, sourceLine); } } else { if (iostat == IostatOk) { @@ -301,7 +301,7 @@ Cookie BeginUnformattedIO( return &io; } else { return &unit.BeginIoStatement( - iostat, sourceFile, sourceLine); + iostat, &unit, sourceFile, sourceLine); } } } @@ -337,18 +337,30 @@ Cookie IONAME(BeginOpenNewUnit)( // OPEN(NEWUNIT=j) unit, false /*was an existing file*/, sourceFile, sourceLine); } -Cookie IONAME(BeginWait)(ExternalUnit unitNumber, AsynchronousId id) { - // TODO: add and use sourceFile & sourceLine here - Terminator oom; - // TODO: add and use sourceFile & sourceLine here - auto &io{ - New{oom}(nullptr, 0).release()->ioStatementState()}; - if (id != 0 && !ExternalFileUnit::LookUp(unitNumber)) { - io.GetIoErrorHandler().SetPendingError(IostatBadWaitUnit); +Cookie IONAME(BeginWait)(ExternalUnit unitNumber, AsynchronousId id, + const char *sourceFile, int sourceLine) { + Terminator terminator{sourceFile, sourceLine}; + if (ExternalFileUnit * unit{ExternalFileUnit::LookUp(unitNumber)}) { + if (unit->Wait(id)) { + return &unit->BeginIoStatement( + *unit, ExternalMiscIoStatementState::Wait, sourceFile, sourceLine); + } else { + return &unit->BeginIoStatement( + IostatBadWaitId, unit, sourceFile, sourceLine); + } + } else { + auto &io{ + New{terminator}(sourceFile, sourceLine, unitNumber) + .release() + ->ioStatementState()}; + if (id != 0) { + io.GetIoErrorHandler().SetPendingError(IostatBadWaitUnit); + } + return &io; } - return &io; } -Cookie IONAME(BeginWaitAll)(ExternalUnit unitNumber) { +Cookie IONAME(BeginWaitAll)( + ExternalUnit unitNumber, const char *sourceFile, int sourceLine) { return IONAME(BeginWait)(unitNumber, 0 /*no ID=*/); } @@ -431,7 +443,9 @@ Cookie IONAME(BeginInquireFile)(const char *path, std::size_t pathLength, Terminator oom{sourceFile, sourceLine}; auto trimmed{ SaveDefaultCharacter(path, TrimTrailingSpaces(path, pathLength), oom)}; - if (ExternalFileUnit * unit{ExternalFileUnit::LookUp(trimmed.get())}) { + if (ExternalFileUnit * + unit{ExternalFileUnit::LookUp( + trimmed.get(), std::strlen(trimmed.get()))}) { // INQUIRE(FILE=) to a connected unit return &unit->BeginIoStatement( *unit, sourceFile, sourceLine); @@ -577,8 +591,9 @@ bool IONAME(SetPos)(Cookie cookie, std::int64_t pos) { if (auto *unit{io.GetExternalFileUnit()}) { unit->SetPosition(pos - 1, handler); return true; + } else if (!io.get_if()) { + io.GetIoErrorHandler().Crash("SetPos() called on internal unit"); } - io.GetIoErrorHandler().Crash("SetPos() called on internal unit"); return false; } @@ -658,8 +673,11 @@ bool IONAME(SetAccess)(Cookie cookie, const char *keyword, std::size_t length) { IoStatementState &io{*cookie}; auto *open{io.get_if()}; if (!open) { - io.GetIoErrorHandler().Crash( - "SetAccess() called when not in an OPEN statement"); + if (!io.get_if()) { + io.GetIoErrorHandler().Crash( + "SetAccess() called when not in an OPEN statement"); + } + return false; } else if (open->completedOperation()) { io.GetIoErrorHandler().Crash( "SetAccess() called after GetNewUnit() for an OPEN statement"); @@ -690,8 +708,11 @@ bool IONAME(SetAction)(Cookie cookie, const char *keyword, std::size_t length) { IoStatementState &io{*cookie}; auto *open{io.get_if()}; if (!open) { - io.GetIoErrorHandler().Crash( - "SetAction() called when not in an OPEN statement"); + if (!io.get_if()) { + io.GetIoErrorHandler().Crash( + "SetAction() called when not in an OPEN statement"); + } + return false; } else if (open->completedOperation()) { io.GetIoErrorHandler().Crash( "SetAction() called after GetNewUnit() for an OPEN statement"); @@ -735,11 +756,15 @@ bool IONAME(SetAsynchronous)( "SetAsynchronous() called after GetNewUnit() for an OPEN statement"); } open->unit().set_mayAsynchronous(isYes); - } else if (ExternalFileUnit * unit{io.GetExternalFileUnit()}) { - if (isYes && !unit->mayAsynchronous()) { - handler.SignalError(IostatBadAsynchronous); + } else if (auto *ext{io.get_if()}) { + if (isYes) { + if (ext->unit().mayAsynchronous()) { + ext->SetAsynchronous(); + } else { + handler.SignalError(IostatBadAsynchronous); + } } - } else { + } else if (!io.get_if()) { handler.Crash("SetAsynchronous() called when not in an OPEN or external " "I/O statement"); } @@ -751,8 +776,11 @@ bool IONAME(SetCarriagecontrol)( IoStatementState &io{*cookie}; auto *open{io.get_if()}; if (!open) { - io.GetIoErrorHandler().Crash( - "SetCarriageControl() called when not in an OPEN statement"); + if (!io.get_if()) { + io.GetIoErrorHandler().Crash( + "SetCarriageControl() called when not in an OPEN statement"); + } + return false; } else if (open->completedOperation()) { io.GetIoErrorHandler().Crash( "SetCarriageControl() called after GetNewUnit() for an OPEN statement"); @@ -779,8 +807,11 @@ bool IONAME(SetConvert)( IoStatementState &io{*cookie}; auto *open{io.get_if()}; if (!open) { - io.GetIoErrorHandler().Crash( - "SetConvert() called when not in an OPEN statement"); + if (!io.get_if()) { + io.GetIoErrorHandler().Crash( + "SetConvert() called when not in an OPEN statement"); + } + return false; } else if (open->completedOperation()) { io.GetIoErrorHandler().Crash( "SetConvert() called after GetNewUnit() for an OPEN statement"); @@ -800,8 +831,11 @@ bool IONAME(SetEncoding)( IoStatementState &io{*cookie}; auto *open{io.get_if()}; if (!open) { - io.GetIoErrorHandler().Crash( - "SetEncoding() called when not in an OPEN statement"); + if (!io.get_if()) { + io.GetIoErrorHandler().Crash( + "SetEncoding() called when not in an OPEN statement"); + } + return false; } else if (open->completedOperation()) { io.GetIoErrorHandler().Crash( "SetEncoding() called after GetNewUnit() for an OPEN statement"); @@ -832,8 +866,10 @@ bool IONAME(SetForm)(Cookie cookie, const char *keyword, std::size_t length) { IoStatementState &io{*cookie}; auto *open{io.get_if()}; if (!open) { - io.GetIoErrorHandler().Crash( - "SetForm() called when not in an OPEN statement"); + if (!io.get_if()) { + io.GetIoErrorHandler().Crash( + "SetForm() called when not in an OPEN statement"); + } } else if (open->completedOperation()) { io.GetIoErrorHandler().Crash( "SetForm() called after GetNewUnit() for an OPEN statement"); @@ -858,8 +894,11 @@ bool IONAME(SetPosition)( IoStatementState &io{*cookie}; auto *open{io.get_if()}; if (!open) { - io.GetIoErrorHandler().Crash( - "SetPosition() called when not in an OPEN statement"); + if (!io.get_if()) { + io.GetIoErrorHandler().Crash( + "SetPosition() called when not in an OPEN statement"); + } + return false; } else if (open->completedOperation()) { io.GetIoErrorHandler().Crash( "SetPosition() called after GetNewUnit() for an OPEN statement"); @@ -886,8 +925,11 @@ bool IONAME(SetRecl)(Cookie cookie, std::size_t n) { IoStatementState &io{*cookie}; auto *open{io.get_if()}; if (!open) { - io.GetIoErrorHandler().Crash( - "SetRecl() called when not in an OPEN statement"); + if (!io.get_if()) { + io.GetIoErrorHandler().Crash( + "SetRecl() called when not in an OPEN statement"); + } + return false; } else if (open->completedOperation()) { io.GetIoErrorHandler().Crash( "SetRecl() called after GetNewUnit() for an OPEN statement"); @@ -951,7 +993,8 @@ bool IONAME(SetStatus)(Cookie cookie, const char *keyword, std::size_t length) { } return false; } - if (io.get_if()) { + if (io.get_if() || + io.get_if()) { return true; // don't bother validating STATUS= in a no-op CLOSE } io.GetIoErrorHandler().Crash( @@ -967,9 +1010,10 @@ bool IONAME(SetFile)(Cookie cookie, const char *path, std::size_t chars) { } open->set_path(path, chars); return true; + } else if (!io.get_if()) { + io.GetIoErrorHandler().Crash( + "SetFile() called when not in an OPEN statement"); } - io.GetIoErrorHandler().Crash( - "SetFile() called when not in an OPEN statement"); return false; } @@ -977,8 +1021,11 @@ bool IONAME(GetNewUnit)(Cookie cookie, int &unit, int kind) { IoStatementState &io{*cookie}; auto *open{io.get_if()}; if (!open) { - io.GetIoErrorHandler().Crash( - "GetNewUnit() called when not in an OPEN statement"); + if (!io.get_if()) { + io.GetIoErrorHandler().Crash( + "GetNewUnit() called when not in an OPEN statement"); + } + return false; } else if (!open->InError()) { open->CompleteOperation(); } @@ -1013,9 +1060,10 @@ bool IONAME(OutputUnformattedBlock)(Cookie cookie, const char *x, return unf->Emit(x, length, elementBytes); } else if (auto *inq{io.get_if()}) { return inq->Emit(x, length, elementBytes); + } else if (!io.get_if()) { + io.GetIoErrorHandler().Crash("OutputUnformattedBlock() called for an I/O " + "statement that is not unformatted output"); } - io.GetIoErrorHandler().Crash("OutputUnformattedBlock() called for an I/O " - "statement that is not unformatted output"); return false; } @@ -1030,14 +1078,17 @@ bool IONAME(InputUnformattedBlock)( if (auto *unf{ io.get_if>()}) { return unf->Receive(x, length, elementBytes); + } else if (!io.get_if()) { + handler.Crash("InputUnformattedBlock() called for an I/O statement that is " + "not unformatted input"); } - handler.Crash("InputUnformattedBlock() called for an I/O statement that is " - "not unformatted input"); return false; } bool IONAME(OutputInteger8)(Cookie cookie, std::int8_t n) { - cookie->CheckFormattedStmtType("OutputInteger8"); + if (!cookie->CheckFormattedStmtType("OutputInteger8")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( @@ -1046,7 +1097,9 @@ bool IONAME(OutputInteger8)(Cookie cookie, std::int8_t n) { } bool IONAME(OutputInteger16)(Cookie cookie, std::int16_t n) { - cookie->CheckFormattedStmtType("OutputInteger16"); + if (!cookie->CheckFormattedStmtType("OutputInteger16")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( @@ -1055,7 +1108,9 @@ bool IONAME(OutputInteger16)(Cookie cookie, std::int16_t n) { } bool IONAME(OutputInteger32)(Cookie cookie, std::int32_t n) { - cookie->CheckFormattedStmtType("OutputInteger32"); + if (!cookie->CheckFormattedStmtType("OutputInteger32")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( @@ -1064,7 +1119,9 @@ bool IONAME(OutputInteger32)(Cookie cookie, std::int32_t n) { } bool IONAME(OutputInteger64)(Cookie cookie, std::int64_t n) { - cookie->CheckFormattedStmtType("OutputInteger64"); + if (!cookie->CheckFormattedStmtType("OutputInteger64")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( @@ -1074,7 +1131,9 @@ bool IONAME(OutputInteger64)(Cookie cookie, std::int64_t n) { #ifdef __SIZEOF_INT128__ bool IONAME(OutputInteger128)(Cookie cookie, common::int128_t n) { - cookie->CheckFormattedStmtType("OutputInteger128"); + if (!cookie->CheckFormattedStmtType("OutputInteger128")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( @@ -1084,7 +1143,9 @@ bool IONAME(OutputInteger128)(Cookie cookie, common::int128_t n) { #endif bool IONAME(InputInteger)(Cookie cookie, std::int64_t &n, int kind) { - cookie->CheckFormattedStmtType("InputInteger"); + if (!cookie->CheckFormattedStmtType("InputInteger")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( @@ -1093,7 +1154,9 @@ bool IONAME(InputInteger)(Cookie cookie, std::int64_t &n, int kind) { } bool IONAME(OutputReal32)(Cookie cookie, float x) { - cookie->CheckFormattedStmtType("OutputReal32"); + if (!cookie->CheckFormattedStmtType("OutputReal32")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish(TypeCategory::Real, 4, reinterpret_cast(&x), 0); @@ -1101,7 +1164,9 @@ bool IONAME(OutputReal32)(Cookie cookie, float x) { } bool IONAME(OutputReal64)(Cookie cookie, double x) { - cookie->CheckFormattedStmtType("OutputReal64"); + if (!cookie->CheckFormattedStmtType("OutputReal64")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish(TypeCategory::Real, 8, reinterpret_cast(&x), 0); @@ -1109,7 +1174,9 @@ bool IONAME(OutputReal64)(Cookie cookie, double x) { } bool IONAME(InputReal32)(Cookie cookie, float &x) { - cookie->CheckFormattedStmtType("InputReal32"); + if (!cookie->CheckFormattedStmtType("InputReal32")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish(TypeCategory::Real, 4, reinterpret_cast(&x), 0); @@ -1117,7 +1184,9 @@ bool IONAME(InputReal32)(Cookie cookie, float &x) { } bool IONAME(InputReal64)(Cookie cookie, double &x) { - cookie->CheckFormattedStmtType("InputReal64"); + if (!cookie->CheckFormattedStmtType("InputReal64")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish(TypeCategory::Real, 8, reinterpret_cast(&x), 0); @@ -1125,7 +1194,9 @@ bool IONAME(InputReal64)(Cookie cookie, double &x) { } bool IONAME(OutputComplex32)(Cookie cookie, float r, float i) { - cookie->CheckFormattedStmtType("OutputComplex32"); + if (!cookie->CheckFormattedStmtType("OutputComplex32")) { + return false; + } float z[2]{r, i}; StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; @@ -1135,7 +1206,9 @@ bool IONAME(OutputComplex32)(Cookie cookie, float r, float i) { } bool IONAME(OutputComplex64)(Cookie cookie, double r, double i) { - cookie->CheckFormattedStmtType("OutputComplex64"); + if (!cookie->CheckFormattedStmtType("OutputComplex64")) { + return false; + } double z[2]{r, i}; StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; @@ -1145,7 +1218,9 @@ bool IONAME(OutputComplex64)(Cookie cookie, double r, double i) { } bool IONAME(InputComplex32)(Cookie cookie, float z[2]) { - cookie->CheckFormattedStmtType("InputComplex32"); + if (!cookie->CheckFormattedStmtType("InputComplex32")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( @@ -1154,7 +1229,9 @@ bool IONAME(InputComplex32)(Cookie cookie, float z[2]) { } bool IONAME(InputComplex64)(Cookie cookie, double z[2]) { - cookie->CheckFormattedStmtType("InputComplex64"); + if (!cookie->CheckFormattedStmtType("InputComplex64")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( @@ -1164,7 +1241,9 @@ bool IONAME(InputComplex64)(Cookie cookie, double z[2]) { bool IONAME(OutputCharacter)( Cookie cookie, const char *x, std::size_t length, int kind) { - cookie->CheckFormattedStmtType("OutputCharacter"); + if (!cookie->CheckFormattedStmtType("OutputCharacter")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( @@ -1178,7 +1257,9 @@ bool IONAME(OutputAscii)(Cookie cookie, const char *x, std::size_t length) { bool IONAME(InputCharacter)( Cookie cookie, char *x, std::size_t length, int kind) { - cookie->CheckFormattedStmtType("InputCharacter"); + if (!cookie->CheckFormattedStmtType("InputCharacter")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish(kind, length, reinterpret_cast(x), 0); @@ -1190,7 +1271,9 @@ bool IONAME(InputAscii)(Cookie cookie, char *x, std::size_t length) { } bool IONAME(OutputLogical)(Cookie cookie, bool truth) { - cookie->CheckFormattedStmtType("OutputLogical"); + if (!cookie->CheckFormattedStmtType("OutputLogical")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( @@ -1199,7 +1282,9 @@ bool IONAME(OutputLogical)(Cookie cookie, bool truth) { } bool IONAME(InputLogical)(Cookie cookie, bool &truth) { - cookie->CheckFormattedStmtType("InputLogical"); + if (!cookie->CheckFormattedStmtType("InputLogical")) { + return false; + } StaticDescriptor staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( @@ -1216,9 +1301,10 @@ std::size_t IONAME(GetSize)(Cookie cookie) { if (const auto *formatted{ io.get_if>()}) { return formatted->GetEditDescriptorChars(); + } else if (!io.get_if()) { + handler.Crash("GetIoSize() called for an I/O statement that is not a " + "formatted READ()"); } - handler.Crash( - "GetIoSize() called for an I/O statement that is not a formatted READ()"); return 0; } @@ -1230,9 +1316,10 @@ std::size_t IONAME(GetIoLength)(Cookie cookie) { } if (const auto *inq{io.get_if()}) { return inq->bytes(); + } else if (!io.get_if()) { + handler.Crash("GetIoLength() called for an I/O statement that is not " + "INQUIRE(IOLENGTH=)"); } - handler.Crash("GetIoLength() called for an I/O statement that is not " - "INQUIRE(IOLENGTH=)"); return 0; } diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp index 78fae20a173c9..480cbea81821e 100644 --- a/flang/runtime/io-stmt.cpp +++ b/flang/runtime/io-stmt.cpp @@ -206,6 +206,10 @@ int ExternalIoStatementBase::EndIoStatement() { return result; } +void ExternalIoStatementBase::SetAsynchronous() { + asynchronousID_ = unit().GetAsynchronousId(*this); +} + void OpenStatementState::set_path(const char *path, std::size_t length) { pathLength_ = TrimTrailingSpaces(path, length); path_ = SaveDefaultCharacter(path, pathLength_, *this); @@ -315,20 +319,18 @@ void ExternalIoStatementState::CompleteOperation() { } if constexpr (DIR == Direction::Input) { BeginReadingRecord(); // in case there were no I/O items - if (mutableModes().nonAdvancing) { + if (mutableModes().nonAdvancing && !InError()) { unit().leftTabLimit = unit().furthestPositionInRecord; - } - if (!mutableModes().nonAdvancing || GetIoStat() == IostatEor) { + } else { FinishReadingRecord(); } } else { // output if (mutableModes().nonAdvancing) { // Make effects of positioning past the last Emit() visible with blanks. std::int64_t n{unit().positionInRecord - unit().furthestPositionInRecord}; - unit().positionInRecord = unit().furthestPositionInRecord; while (n-- > 0 && unit().Emit(" ", 1, 1, *this)) { } - unit().leftTabLimit = unit().furthestPositionInRecord; + unit().leftTabLimit = unit().positionInRecord; } else { unit().AdvanceRecord(*this); } @@ -796,7 +798,9 @@ ListDirectedStatementState::GetNextDataEdit( if (remaining_ > 0) { repeatPosition_.emplace(io); } - return edit; + if (!imaginaryPart_) { + return edit; + } } // Skip separators, handle a "r*c" repeat count; see 13.10.2 in Fortran 2018 if (imaginaryPart_) { @@ -1024,6 +1028,8 @@ void ExternalMiscIoStatementState::CompleteOperation() { case Rewind: ext.Rewind(*this); break; + case Wait: + break; // handled in io-api.cpp BeginWait } return IoStatementBase::CompleteOperation(); } @@ -1483,9 +1489,11 @@ bool InquireUnconnectedFileState::Inquire( case HashInquiryKeyword("NUMBER"): case HashInquiryKeyword("POS"): case HashInquiryKeyword("RECL"): - case HashInquiryKeyword("SIZE"): result = -1; return true; + case HashInquiryKeyword("SIZE"): + result = SizeInBytes(path_.get()); + return true; default: BadInquiryKeywordHashCrash(inquiry); return false; @@ -1518,6 +1526,9 @@ bool InquireIOLengthState::Emit(const char32_t *p, std::size_t n) { int ErroneousIoStatementState::EndIoStatement() { SignalPendingError(); + if (unit_) { + unit_->EndIoStatement(); + } return IoStatementBase::EndIoStatement(); } diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h index 16a0e031403f7..5e3209b7acab6 100644 --- a/flang/runtime/io-stmt.h +++ b/flang/runtime/io-stmt.h @@ -136,7 +136,7 @@ class IoStatementState { std::optional PrepareInput( const DataEdit &edit, std::optional &remaining) { remaining.reset(); - if (edit.descriptor == DataEdit::ListDirected) { + if (edit.IsListDirected()) { std::size_t byteCount{0}; GetNextNonBlank(byteCount); } else { @@ -194,11 +194,16 @@ class IoStatementState { return ch; } - template void CheckFormattedStmtType(const char *name) { - if (!get_if>()) { - GetIoErrorHandler().Crash( - "%s called for I/O statement that is not formatted %s", name, - D == Direction::Output ? "output" : "input"); + template bool CheckFormattedStmtType(const char *name) { + if (get_if>()) { + return true; + } else { + if (!get_if()) { + GetIoErrorHandler().Crash( + "%s called for I/O statement that is not formatted %s", name, + D == Direction::Output ? "output" : "input"); + } + return false; } } @@ -407,11 +412,14 @@ class ExternalIoStatementBase : public IoStatementBase { ExternalFileUnit &unit() { return unit_; } MutableModes &mutableModes(); ConnectionState &GetConnectionState(); + int asynchronousID() const { return asynchronousID_; } int EndIoStatement(); ExternalFileUnit *GetExternalFileUnit() const { return &unit_; } + void SetAsynchronous(); private: ExternalFileUnit &unit_; + int asynchronousID_{-1}; }; template @@ -698,7 +706,7 @@ class InquireIOLengthState : public NoUnitIoStatementState, class ExternalMiscIoStatementState : public ExternalIoStatementBase { public: - enum Which { Flush, Backspace, Endfile, Rewind }; + enum Which { Flush, Backspace, Endfile, Rewind, Wait }; ExternalMiscIoStatementState(ExternalFileUnit &unit, Which which, const char *sourceFile = nullptr, int sourceLine = 0) : ExternalIoStatementBase{unit, sourceFile, sourceLine}, which_{which} {} @@ -711,9 +719,10 @@ class ExternalMiscIoStatementState : public ExternalIoStatementBase { class ErroneousIoStatementState : public IoStatementBase { public: - explicit ErroneousIoStatementState( - Iostat iostat, const char *sourceFile = nullptr, int sourceLine = 0) - : IoStatementBase{sourceFile, sourceLine} { + explicit ErroneousIoStatementState(Iostat iostat, + ExternalFileUnit *unit = nullptr, const char *sourceFile = nullptr, + int sourceLine = 0) + : IoStatementBase{sourceFile, sourceLine}, unit_{unit} { SetPendingError(iostat); } int EndIoStatement(); @@ -722,6 +731,7 @@ class ErroneousIoStatementState : public IoStatementBase { private: ConnectionState connection_; + ExternalFileUnit *unit_{nullptr}; }; extern template bool IoStatementState::EmitEncoded( diff --git a/flang/runtime/iostat.cpp b/flang/runtime/iostat.cpp index 5ab1ee435ef22..3008c6e763d5a 100644 --- a/flang/runtime/iostat.cpp +++ b/flang/runtime/iostat.cpp @@ -87,11 +87,22 @@ const char *IostatErrorString(int iostat) { return "READ/WRITE(ASYNCHRONOUS='YES') on unit without " "OPEN(ASYNCHRONOUS='YES')"; case IostatBadWaitUnit: - return "WAIT(ID=nonzero) for a bad unit number"; + return "WAIT(UNIT=) for a bad unit number"; case IostatBOZInputOverflow: return "B/O/Z input value overflows variable"; case IostatIntegerInputOverflow: return "Integer input value overflows variable"; + case IostatRealInputOverflow: + return "Real or complex input value overflows type"; + case IostatCannotReposition: + return "Attempt to reposition a unit which is connected to a file that can " + "only be processed sequentially"; + case IostatOpenAlreadyConnected: + return "OPEN of file already connected to another unit"; + case IostatBadWaitId: + return "WAIT(ID=nonzero) for an ID value that is not a pending operation"; + case IostatTooManyAsyncOps: + return "Too many asynchronous operations pending on unit"; default: return nullptr; } diff --git a/flang/runtime/lock.h b/flang/runtime/lock.h index 0abc1158c2c19..7af1ab89758ed 100644 --- a/flang/runtime/lock.h +++ b/flang/runtime/lock.h @@ -23,6 +23,10 @@ #if USE_PTHREADS #include +#elif defined(_WIN32) +// Do not define macros for "min" and "max" +#define NOMINMAX +#include #else #include #endif @@ -40,6 +44,12 @@ class Lock { } bool Try() { return pthread_mutex_trylock(&mutex_) == 0; } void Drop() { pthread_mutex_unlock(&mutex_); } +#elif defined(_WIN32) + Lock() { InitializeCriticalSection(&cs_); } + ~Lock() { DeleteCriticalSection(&cs_); } + void Take() { EnterCriticalSection(&cs_); } + bool Try() { return TryEnterCriticalSection(&cs_); } + void Drop() { LeaveCriticalSection(&cs_); } #else void Take() { mutex_.lock(); } bool Try() { return mutex_.try_lock(); } @@ -56,6 +66,8 @@ class Lock { private: #if USE_PTHREADS pthread_mutex_t mutex_{}; +#elif defined(_WIN32) + CRITICAL_SECTION cs_; #else std::mutex mutex_; #endif diff --git a/flang/runtime/numeric.cpp b/flang/runtime/numeric.cpp index c04d50111934b..391837bc4752b 100644 --- a/flang/runtime/numeric.cpp +++ b/flang/runtime/numeric.cpp @@ -7,7 +7,9 @@ //===----------------------------------------------------------------------===// #include "flang/Runtime/numeric.h" -#include "flang/Common/long-double.h" +#include "terminator.h" +#include "flang/Runtime/float128.h" +#include #include #include #include @@ -62,14 +64,24 @@ template inline T Fraction(T x) { } // MOD & MODULO (16.9.135, .136) -template inline T IntMod(T x, T p) { +template +inline T IntMod(T x, T p, const char *sourceFile, int sourceLine) { + if (p == 0) { + Terminator{sourceFile, sourceLine}.Crash( + IS_MODULO ? "MODULO with P==0" : "MOD with P==0"); + } auto mod{x - (x / p) * p}; if (IS_MODULO && (x > 0) != (p > 0)) { mod += p; } return mod; } -template inline T RealMod(T x, T p) { +template +inline T RealMod(T x, T p, const char *sourceFile, int sourceLine) { + if (p == 0) { + Terminator{sourceFile, sourceLine}.Crash( + IS_MODULO ? "MODULO with P==0" : "MOD with P==0"); + } if constexpr (IS_MODULO) { return x - std::floor(x / p) * p; } else { @@ -164,7 +176,7 @@ CppTypeFor RTNAME(Aint8_8)( CppTypeFor x) { return Aint>(x); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Aint4_10)( CppTypeFor x) { return Aint>(x); @@ -185,7 +197,7 @@ CppTypeFor RTNAME(Aint10_10)( CppTypeFor x) { return Aint>(x); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(Aint4_16)( CppTypeFor x) { return Aint>(x); @@ -224,7 +236,7 @@ CppTypeFor RTNAME(Anint8_8)( CppTypeFor x) { return Anint>(x); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Anint4_10)( CppTypeFor x) { return Anint>(x); @@ -245,7 +257,7 @@ CppTypeFor RTNAME(Anint10_10)( CppTypeFor x) { return Anint>(x); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(Anint4_16)( CppTypeFor x) { return Anint>(x); @@ -312,7 +324,7 @@ CppTypeFor RTNAME(Ceiling8_16)( return Ceiling>(x); } #endif -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Ceiling10_1)( CppTypeFor x) { return Ceiling>(x); @@ -335,7 +347,7 @@ CppTypeFor RTNAME(Ceiling10_16)( return Ceiling>(x); } #endif -#else +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(Ceiling16_1)( CppTypeFor x) { return Ceiling>(x); @@ -376,7 +388,7 @@ CppTypeFor RTNAME(Exponent8_8)( CppTypeFor x) { return Exponent>(x); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Exponent10_4)( CppTypeFor x) { return Exponent>(x); @@ -385,7 +397,7 @@ CppTypeFor RTNAME(Exponent10_8)( CppTypeFor x) { return Exponent>(x); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(Exponent16_4)( CppTypeFor x) { return Exponent>(x); @@ -440,7 +452,7 @@ CppTypeFor RTNAME(Floor8_16)( return Floor>(x); } #endif -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Floor10_1)( CppTypeFor x) { return Floor>(x); @@ -463,7 +475,7 @@ CppTypeFor RTNAME(Floor10_16)( return Floor>(x); } #endif -#else +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(Floor16_1)( CppTypeFor x) { return Floor>(x); @@ -496,12 +508,12 @@ CppTypeFor RTNAME(Fraction8)( CppTypeFor x) { return Fraction(x); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Fraction10)( CppTypeFor x) { return Fraction(x); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(Fraction16)( CppTypeFor x) { return Fraction(x); @@ -514,11 +526,11 @@ bool RTNAME(IsFinite4)(CppTypeFor x) { bool RTNAME(IsFinite8)(CppTypeFor x) { return std::isfinite(x); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 bool RTNAME(IsFinite10)(CppTypeFor x) { return std::isfinite(x); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 bool RTNAME(IsFinite16)(CppTypeFor x) { return std::isfinite(x); } @@ -530,11 +542,11 @@ bool RTNAME(IsNaN4)(CppTypeFor x) { bool RTNAME(IsNaN8)(CppTypeFor x) { return std::isnan(x); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 bool RTNAME(IsNaN10)(CppTypeFor x) { return std::isnan(x); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 bool RTNAME(IsNaN16)(CppTypeFor x) { return std::isnan(x); } @@ -542,99 +554,113 @@ bool RTNAME(IsNaN16)(CppTypeFor x) { CppTypeFor RTNAME(ModInteger1)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModInteger2)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModInteger4)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModInteger8)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } #ifdef __SIZEOF_INT128__ CppTypeFor RTNAME(ModInteger16)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } #endif CppTypeFor RTNAME(ModReal4)( - CppTypeFor x, CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModReal8)( - CppTypeFor x, CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(ModReal10)( - CppTypeFor x, - CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(ModReal16)( - CppTypeFor x, - CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } #endif CppTypeFor RTNAME(ModuloInteger1)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModuloInteger2)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModuloInteger4)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModuloInteger8)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } #ifdef __SIZEOF_INT128__ CppTypeFor RTNAME(ModuloInteger16)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } #endif CppTypeFor RTNAME(ModuloReal4)( - CppTypeFor x, CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModuloReal8)( - CppTypeFor x, CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(ModuloReal10)( - CppTypeFor x, - CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(ModuloReal16)( - CppTypeFor x, - CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } #endif @@ -646,12 +672,12 @@ CppTypeFor RTNAME(Nearest8)( CppTypeFor x, bool positive) { return Nearest<53>(x, positive); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Nearest10)( CppTypeFor x, bool positive) { return Nearest<64>(x, positive); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(Nearest16)( CppTypeFor x, bool positive) { return Nearest<113>(x, positive); @@ -702,7 +728,7 @@ CppTypeFor RTNAME(Nint8_16)( return Anint>(x); } #endif -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Nint10_1)( CppTypeFor x) { return Anint>(x); @@ -725,7 +751,7 @@ CppTypeFor RTNAME(Nint10_16)( return Anint>(x); } #endif -#else +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(Nint16_1)( CppTypeFor x) { return Anint>(x); @@ -758,12 +784,12 @@ CppTypeFor RTNAME(RRSpacing8)( CppTypeFor x) { return RRSpacing<53>(x); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(RRSpacing10)( CppTypeFor x) { return RRSpacing<64>(x); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(RRSpacing16)( CppTypeFor x) { return RRSpacing<113>(x); @@ -778,12 +804,12 @@ CppTypeFor RTNAME(SetExponent8)( CppTypeFor x, std::int64_t p) { return SetExponent(x, p); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(SetExponent10)( CppTypeFor x, std::int64_t p) { return SetExponent(x, p); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(SetExponent16)( CppTypeFor x, std::int64_t p) { return SetExponent(x, p); @@ -798,12 +824,12 @@ CppTypeFor RTNAME(Scale8)( CppTypeFor x, std::int64_t p) { return Scale(x, p); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Scale10)( CppTypeFor x, std::int64_t p) { return Scale(x, p); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(Scale16)( CppTypeFor x, std::int64_t p) { return Scale(x, p); @@ -818,12 +844,12 @@ CppTypeFor RTNAME(Spacing8)( CppTypeFor x) { return Spacing<53>(x); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Spacing10)( CppTypeFor x) { return Spacing<64>(x); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(Spacing16)( CppTypeFor x) { return Spacing<113>(x); diff --git a/flang/runtime/product.cpp b/flang/runtime/product.cpp index d245e0da8a458..072e2fed2c28f 100644 --- a/flang/runtime/product.cpp +++ b/flang/runtime/product.cpp @@ -9,8 +9,9 @@ // Implements PRODUCT for all required operand types and shapes. #include "reduction-templates.h" -#include "flang/Common/long-double.h" +#include "flang/Runtime/float128.h" #include "flang/Runtime/reduction.h" +#include #include #include @@ -105,14 +106,14 @@ CppTypeFor RTNAME(ProductReal8)(const Descriptor &x, NonComplexProductAccumulator>{x}, "PRODUCT"); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(ProductReal10)(const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction(x, source, line, dim, mask, NonComplexProductAccumulator>{x}, "PRODUCT"); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(ProductReal16)(const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction(x, source, line, dim, mask, @@ -135,7 +136,7 @@ void RTNAME(CppProductComplex8)(CppTypeFor &result, mask, ComplexProductAccumulator>{x}, "PRODUCT"); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 void RTNAME(CppProductComplex10)(CppTypeFor &result, const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { @@ -143,7 +144,7 @@ void RTNAME(CppProductComplex10)(CppTypeFor &result, mask, ComplexProductAccumulator>{x}, "PRODUCT"); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 void RTNAME(CppProductComplex16)(CppTypeFor &result, const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { diff --git a/flang/runtime/random.cpp b/flang/runtime/random.cpp index 8f8145b299f4a..0f6a6a2be623f 100644 --- a/flang/runtime/random.cpp +++ b/flang/runtime/random.cpp @@ -15,6 +15,7 @@ #include "flang/Common/uint128.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" +#include "flang/Runtime/float128.h" #include #include #include @@ -40,6 +41,19 @@ static constexpr int rangeBits{ static Lock lock; static Generator generator; +static std::optional nextValue; + +// Call only with lock held +static GeneratedWord GetNextValue() { + GeneratedWord result; + if (nextValue.has_value()) { + result = *nextValue; + nextValue.reset(); + } else { + result = generator(); + } + return result; +} template inline void Generate(const Descriptor &harvest) { @@ -54,17 +68,23 @@ inline void Generate(const Descriptor &harvest) { { CriticalSection critical{lock}; for (std::size_t j{0}; j < elements; ++j) { - Int fraction{generator()}; - if constexpr (words > 1) { - for (std::size_t k{1}; k < words; ++k) { - static constexpr auto rangeMask{(GeneratedWord{1} << rangeBits) - 1}; - GeneratedWord word{(generator() - generator.min()) & rangeMask}; - fraction = (fraction << rangeBits) | word; + while (true) { + Int fraction{GetNextValue()}; + if constexpr (words > 1) { + for (std::size_t k{1}; k < words; ++k) { + static constexpr auto rangeMask{ + (GeneratedWord{1} << rangeBits) - 1}; + GeneratedWord word{(GetNextValue() - generator.min()) & rangeMask}; + fraction = (fraction << rangeBits) | word; + } + } + fraction >>= words * rangeBits - PREC; + REAL next{std::ldexp(static_cast(fraction), -(PREC + 1))}; + if (next >= 0.0 && next < 1.0) { + *harvest.Element(at) = next; + break; } } - fraction >>= words * rangeBits - PREC; - *harvest.Element(at) = - std::ldexp(static_cast(fraction), -(PREC + 1)); harvest.IncrementSubscripts(at); } } @@ -94,23 +114,28 @@ void RTNAME(RandomNumber)( // TODO: REAL (2 & 3) case 4: Generate, 24>(harvest); - break; + return; case 8: Generate, 53>(harvest); - break; -#if LONG_DOUBLE == 80 + return; case 10: - Generate, 64>(harvest); + if constexpr (HasCppTypeFor) { +#if LDBL_MANT_DIG == 64 + Generate, 64>(harvest); + return; +#endif + } break; -#elif LONG_DOUBLE == 128 case 16: - Generate, 113>(harvest); - break; + if constexpr (HasCppTypeFor) { +#if LDBL_MANT_DIG == 113 + Generate, 113>(harvest); + return; #endif - default: - terminator.Crash( - "not yet implemented: RANDOM_NUMBER(): REAL kind %d", kind); + } + break; } + terminator.Crash("not yet implemented: RANDOM_NUMBER(): REAL kind %d", kind); } void RTNAME(RandomSeedSize)( @@ -155,6 +180,7 @@ void RTNAME(RandomSeedPut)( { CriticalSection critical{lock}; generator.seed(seed); + nextValue = seed; } } @@ -177,8 +203,8 @@ void RTNAME(RandomSeedGet)( GeneratedWord seed; { CriticalSection critical{lock}; - seed = generator(); - generator.seed(seed); + seed = GetNextValue(); + nextValue = seed; } switch (kind) { case 4: diff --git a/flang/runtime/sum.cpp b/flang/runtime/sum.cpp index 6bdb599eea75c..ba0e75d017a23 100644 --- a/flang/runtime/sum.cpp +++ b/flang/runtime/sum.cpp @@ -13,8 +13,9 @@ // (basically the same as manual "double-double"). #include "reduction-templates.h" -#include "flang/Common/long-double.h" +#include "flang/Runtime/float128.h" #include "flang/Runtime/reduction.h" +#include #include #include @@ -129,13 +130,14 @@ CppTypeFor RTNAME(SumReal8)(const Descriptor &x, return GetTotalReduction( x, source, line, dim, mask, RealSumAccumulator{x}, "SUM"); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(SumReal10)(const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction( x, source, line, dim, mask, RealSumAccumulator{x}, "SUM"); } -#elif LONG_DOUBLE == 128 +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTNAME(SumReal16)(const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction( @@ -155,14 +157,14 @@ void RTNAME(CppSumComplex8)(CppTypeFor &result, result = GetTotalReduction( x, source, line, dim, mask, ComplexSumAccumulator{x}, "SUM"); } -#if LONG_DOUBLE == 80 +#if LDBL_MANT_DIG == 64 void RTNAME(CppSumComplex10)(CppTypeFor &result, const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { result = GetTotalReduction( x, source, line, dim, mask, ComplexSumAccumulator{x}, "SUM"); } -#elif LONG_DOUBLE == 128 +#elif LDBL_MANT_DIG == 113 void RTNAME(CppSumComplex16)(CppTypeFor &result, const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { diff --git a/flang/runtime/tools.h b/flang/runtime/tools.h index dd35917b58e9b..a9c942d53eea4 100644 --- a/flang/runtime/tools.h +++ b/flang/runtime/tools.h @@ -10,7 +10,6 @@ #define FORTRAN_RUNTIME_TOOLS_H_ #include "terminator.h" -#include "flang/Common/long-double.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" #include "flang/Runtime/memory.h" @@ -148,16 +147,18 @@ inline RESULT ApplyType( return FUNC{}(std::forward(x)...); case 8: return FUNC{}(std::forward(x)...); -#if LONG_DOUBLE == 80 case 10: - return FUNC{}(std::forward(x)...); -#elif LONG_DOUBLE == 128 + if constexpr (HasCppTypeFor) { + return FUNC{}(std::forward(x)...); + } + break; case 16: - return FUNC{}(std::forward(x)...); -#endif - default: - terminator.Crash("not yet implemented: REAL(KIND=%d)", kind); + if constexpr (HasCppTypeFor) { + return FUNC{}(std::forward(x)...); + } + break; } + terminator.Crash("not yet implemented: REAL(KIND=%d)", kind); case TypeCategory::Complex: switch (kind) { #if 0 // TODO: COMPLEX(2 & 3) @@ -170,16 +171,18 @@ inline RESULT ApplyType( return FUNC{}(std::forward(x)...); case 8: return FUNC{}(std::forward(x)...); -#if LONG_DOUBLE == 80 case 10: - return FUNC{}(std::forward(x)...); -#elif LONG_DOUBLE == 128 + if constexpr (HasCppTypeFor) { + return FUNC{}(std::forward(x)...); + } + break; case 16: - return FUNC{}(std::forward(x)...); -#endif - default: - terminator.Crash("not yet implemented: COMPLEX(KIND=%d)", kind); + if constexpr (HasCppTypeFor) { + return FUNC{}(std::forward(x)...); + } + break; } + terminator.Crash("not yet implemented: COMPLEX(KIND=%d)", kind); case TypeCategory::Character: switch (kind) { case 1: @@ -246,16 +249,18 @@ inline RESULT ApplyFloatingPointKind( return FUNC<4>{}(std::forward(x)...); case 8: return FUNC<8>{}(std::forward(x)...); -#if LONG_DOUBLE == 80 case 10: - return FUNC<10>{}(std::forward(x)...); -#elif LONG_DOUBLE == 128 + if constexpr (HasCppTypeFor) { + return FUNC<10>{}(std::forward(x)...); + } + break; case 16: - return FUNC<16>{}(std::forward(x)...); -#endif - default: - terminator.Crash("not yet implemented: REAL/COMPLEX(KIND=%d)", kind); + if constexpr (HasCppTypeFor) { + return FUNC<16>{}(std::forward(x)...); + } + break; } + terminator.Crash("not yet implemented: REAL/COMPLEX(KIND=%d)", kind); } template