diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c246c42b0904d2fd84687e8362ef67ad0eb2400d..77ba81c58c5d63f7e5e054d9503e882afd3ae468 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -59,8 +59,8 @@ clang/test/AST/Interp/ @tbaederr /mlir/Dialect/*/Transforms/Bufferize.cpp @matthias-springer # Linalg Dialect in MLIR. -/mlir/include/mlir/Dialect/Linalg @dcaballe @nicolasvasilache -/mlir/lib/Dialect/Linalg @dcaballe @nicolasvasilache +/mlir/include/mlir/Dialect/Linalg/* @dcaballe @nicolasvasilache +/mlir/lib/Dialect/Linalg/* @dcaballe @nicolasvasilache /mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp @MaheshRavishankar @nicolasvasilache /mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp @MaheshRavishankar @nicolasvasilache /mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp @MaheshRavishankar @nicolasvasilache @@ -77,14 +77,14 @@ clang/test/AST/Interp/ @tbaederr /mlir/**/*SME* @banach-space @dcaballe @nicolasvasilache /mlir/**/*SVE* @banach-space @dcaballe @nicolasvasilache /mlir/**/*VectorInterfaces* @dcaballe @nicolasvasilache -/mlir/**/*VectorToSCF* @banach-space @dcaballe @nicolasvasilache @matthias-springer +/mlir/**/*VectorToSCF* @banach-space @dcaballe @matthias-springer @nicolasvasilache /mlir/**/*VectorToLLVM* @banach-space @dcaballe @nicolasvasilache /mlir/**/*X86Vector* @aartbik @dcaballe @nicolasvasilache -/mlir/include/mlir/Dialect/Vector @dcaballe @nicolasvasilache -/mlir/lib/Dialect/Vector @dcaballe @nicolasvasilache -/mlir/lib/Dialect/Vector/Transforms/VectorEmulateNarrowType.cpp @MaheshRavishankar @nicolasvasilache -/mlir/**/*EmulateNarrowType* @hanhanW +/mlir/include/mlir/Dialect/Vector/* @dcaballe @nicolasvasilache +/mlir/lib/Dialect/Vector/* @dcaballe @nicolasvasilache /mlir/lib/Dialect/Vector/Transforms/* @hanhanW @nicolasvasilache +/mlir/lib/Dialect/Vector/Transforms/VectorEmulateNarrowType.cpp @MaheshRavishankar @nicolasvasilache +/mlir/**/*EmulateNarrowType* @dcaballe @hanhanW # Presburger library in MLIR /mlir/**/*Presburger* @Groverkss @Superty @@ -96,6 +96,7 @@ clang/test/AST/Interp/ @tbaederr # Transform Dialect in MLIR. /mlir/include/mlir/Dialect/Transform/* @ftynse @nicolasvasilache /mlir/lib/Dialect/Transform/* @ftynse @nicolasvasilache +/mlir/**/*TransformOps* @ftynse @nicolasvasilache # SPIR-V Dialect in MLIR. /mlir/**/SPIRV/ @antiagainst @kuhar @@ -119,3 +120,8 @@ clang/test/AST/Interp/ @tbaederr # Bazel build system. /utils/bazel/ @rupprecht + +# InstallAPI and TextAPI +/llvm/**/TextAPI/ @cyndyishida +/clang/**/InstallAPI/ @cyndyishida +/clang/tools/clang-installapi/ @cyndyishida diff --git a/.github/workflows/issue-write.yml b/.github/workflows/issue-write.yml new file mode 100644 index 0000000000000000000000000000000000000000..02a5f7c213e898d32d5e5f4d3d42db11df7359c7 --- /dev/null +++ b/.github/workflows/issue-write.yml @@ -0,0 +1,128 @@ +name: Comment on an issue + +on: + workflow_run: + workflows: ["Check code formatting"] + types: + - completed + +permissions: + contents: read + +jobs: + pr-comment: + runs-on: ubuntu-latest + permissions: + pull-requests: write + if: > + github.event.workflow_run.event == 'pull_request' + steps: + - name: 'Download artifact' + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + with: + github-token: ${{ secrets.ISSUE_WRITE_DOWNLOAD_ARTIFACT }} + run-id: ${{ github.event.workflow_run.id }} + name: workflow-args + + - name: 'Comment on PR' + uses: actions/github-script@v3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + var fs = require('fs'); + const comments = JSON.parse(fs.readFileSync('./comments')); + if (!comments) { + return; + } + + let runInfo = await github.actions.getWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id + }); + + console.log(runInfo); + + + // Query to find the number of the pull request that triggered this job. + // The associated pull requests are based off of the branch name, so if + // you create a pull request for a branch, close it, and then create + // another pull request with the same branch, then this query will return + // two associated pull requests. This is why we have to fetch all the + // associated pull requests and then iterate through them to find the + // one that is open. + const gql_query = ` + query($repo_owner : String!, $repo_name : String!, $branch: String!) { + repository(owner: $repo_owner, name: $repo_name) { + ref (qualifiedName: $branch) { + associatedPullRequests(first: 100) { + nodes { + baseRepository { + owner { + login + } + } + number + state + } + } + } + } + } + ` + const gql_variables = { + repo_owner: runInfo.data.head_repository.owner.login, + repo_name: runInfo.data.head_repository.name, + branch: runInfo.data.head_branch + } + const gql_result = await github.graphql(gql_query, gql_variables); + console.log(gql_result); + console.log(gql_result.repository.ref.associatedPullRequests.nodes); + + var pr_number = 0; + gql_result.repository.ref.associatedPullRequests.nodes.forEach((pr) => { + if (pr.baseRepository.owner.login = context.repo.owner && pr.state == 'OPEN') { + pr_number = pr.number; + } + }); + if (pr_number == 0) { + console.log("Error retrieving pull request number"); + return; + } + + await comments.forEach(function (comment) { + if (comment.id) { + // Security check: Ensure that this comment was created by + // the github-actions bot, so a malicious input won't overwrite + // a user's comment. + github.issues.getComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: comment.id + }).then((old_comment) => { + console.log(old_comment); + if (old_comment.data.user.login != "github-actions[bot]") { + console.log("Invalid comment id: " + comment.id); + return; + } + github.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr_number, + comment_id: comment.id, + body: comment.body + }); + }); + } else { + github.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr_number, + body: comment.body + }); + } + }); + + - name: Dump comments file + if: always() + run: cat comments diff --git a/.github/workflows/pr-code-format.yml b/.github/workflows/pr-code-format.yml index 1d1fa2483b658f762b5d4a3a65ec4c99842d65ba..54dfe3aadbb423d98b106ea02d9f4f09e25574c3 100644 --- a/.github/workflows/pr-code-format.yml +++ b/.github/workflows/pr-code-format.yml @@ -1,12 +1,9 @@ name: "Check code formatting" on: - pull_request_target: + pull_request: branches: - main -permissions: - pull-requests: write - jobs: code_formatter: runs-on: ubuntu-latest @@ -31,12 +28,13 @@ jobs: separator: "," skip_initial_fetch: true - # We need to make sure that we aren't executing/using any code from the - # PR for security reasons as we're using pull_request_target. Checkout - # the target branch with the necessary files. + # We need to pull the script from the main branch, so that we ensure + # we get the latest version of this script. - name: Fetch code formatting utils uses: actions/checkout@v4 with: + reository: ${{ github.repository }} + ref: ${{ github.base_ref }} sparse-checkout: | llvm/utils/git/requirements_formatting.txt llvm/utils/git/code-format-helper.py @@ -75,10 +73,20 @@ jobs: # to take advantage of the new --diff_from_common_commit option # explicitly in code-format-helper.py and not have to diff starting at # the merge base. + # Create an empty comments file so the pr-write job doesn't fail. run: | + echo "[]" > comments && python ./code-format-tools/llvm/utils/git/code-format-helper.py \ + --write-comment-to-file \ --token ${{ secrets.GITHUB_TOKEN }} \ --issue-number $GITHUB_PR_NUMBER \ --start-rev $(git merge-base $START_REV $END_REV) \ --end-rev $END_REV \ --changed-files "$CHANGED_FILES" + + - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 + if: always() + with: + name: workflow-args + path: | + comments diff --git a/bolt/include/bolt/Core/DebugNames.h b/bolt/include/bolt/Core/DebugNames.h index 1f17f1ae4d139badf57defc981f0557d78c35593..fbaa7f4e68aac9281989f8432346b1eb9546c3cb 100644 --- a/bolt/include/bolt/Core/DebugNames.h +++ b/bolt/include/bolt/Core/DebugNames.h @@ -68,6 +68,16 @@ public: std::unique_ptr releaseBuffer() { return std::move(FullTableBuffer); } + /// Adds a DIE that is referenced across CUs. + void addCrossCUDie(const DIE *Die) { + CrossCUDies.insert({Die->getOffset(), Die}); + } + /// Returns true if the DIE can generate an entry for a cross cu reference. + /// This only checks TAGs of a DIE because when this is invoked DIE might not + /// be fully constructed. + bool canGenerateEntryWithCrossCUReference( + const DWARFUnit &Unit, const DIE &Die, + const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec); private: BinaryContext &BC; @@ -128,6 +138,7 @@ private: llvm::DenseMap CUOffsetsToPatch; // Contains a map of Entry ID to Entry relative offset. llvm::DenseMap EntryRelativeOffsets; + llvm::DenseMap CrossCUDies; /// Adds Unit to either CUList, LocalTUList or ForeignTUList. /// Input Unit being processed, and DWO ID if Unit is being processed comes /// from a DWO section. diff --git a/bolt/include/bolt/Profile/BoltAddressTranslation.h b/bolt/include/bolt/Profile/BoltAddressTranslation.h index 03ed10ca7f58cbedf1fc0d4e05cea90167d5183a..caf907cc43da3e8d4af24c6b5be5b5c41293e65c 100644 --- a/bolt/include/bolt/Profile/BoltAddressTranslation.h +++ b/bolt/include/bolt/Profile/BoltAddressTranslation.h @@ -115,39 +115,9 @@ public: /// Save function and basic block hashes used for metadata dump. void saveMetadata(BinaryContext &BC); - /// Returns BB hash by function output address (after BOLT) and basic block - /// input offset. - size_t getBBHash(uint64_t FuncOutputAddress, uint32_t BBInputOffset) const; - - /// Returns BF hash by function output address (after BOLT). - size_t getBFHash(uint64_t OutputAddress) const; - /// True if a given \p Address is a function with translation table entry. bool isBATFunction(uint64_t Address) const { return Maps.count(Address); } - /// Returns BB index by function output address (after BOLT) and basic block - /// input offset. - unsigned getBBIndex(uint64_t FuncOutputAddress, uint32_t BBInputOffset) const; - - using BBHashMap = std::map>; - /// Return a mapping from basic block input offset to hash and block index for a given function. - const BBHashMap &getBBHashMap(uint64_t OutputAddress) const { - return FuncHashes.at(OutputAddress).second; - } - - static unsigned getBBIndex(const BBHashMap &BBMap, uint32_t BBInputOffset) { - return BBMap.at(BBInputOffset).first; - } - - static size_t getBBHash(const BBHashMap &BBMap, uint32_t BBInputOffset) { - return BBMap.at(BBInputOffset).second; - } - - /// Returns the maximum BB index for a given function. - size_t getNumBasicBlocks(uint64_t OutputAddress) const { - return NumBasicBlocksMap.at(OutputAddress); - } - /// Returns branch offsets grouped by containing basic block in a given /// function. std::unordered_map> @@ -159,7 +129,7 @@ private: /// emitted for the start of the BB. More entries may be emitted to cover /// the location of calls or any instruction that may change control flow. void writeEntriesForBB(MapTy &Map, const BinaryBasicBlock &BB, - uint64_t FuncAddress); + uint64_t FuncInputAddress, uint64_t FuncOutputAddress); /// Write the serialized address translation table for a function. template @@ -182,9 +152,6 @@ private: std::map Maps; - /// Map basic block input offset to a basic block index and hash pair. - std::unordered_map> FuncHashes; - /// Map a function to its basic blocks count std::unordered_map NumBasicBlocksMap; @@ -200,6 +167,111 @@ private: /// Identifies the address of a control-flow changing instructions in a /// translation map entry const static uint32_t BRANCHENTRY = 0x1; + +public: + /// Map basic block input offset to a basic block index and hash pair. + class BBHashMapTy { + class EntryTy { + unsigned Index; + size_t Hash; + + public: + unsigned getBBIndex() const { return Index; } + size_t getBBHash() const { return Hash; } + EntryTy(unsigned Index, size_t Hash) : Index(Index), Hash(Hash) {} + }; + + std::unordered_map Map; + const EntryTy &getEntry(uint32_t BBInputOffset) const { + auto It = Map.find(BBInputOffset); + assert(It != Map.end()); + return It->second; + } + + public: + bool isInputBlock(uint32_t InputOffset) const { + return Map.count(InputOffset); + } + + unsigned getBBIndex(uint32_t BBInputOffset) const { + return getEntry(BBInputOffset).getBBIndex(); + } + + size_t getBBHash(uint32_t BBInputOffset) const { + return getEntry(BBInputOffset).getBBHash(); + } + + void addEntry(uint32_t BBInputOffset, unsigned BBIndex, size_t BBHash) { + Map.emplace(BBInputOffset, EntryTy(BBIndex, BBHash)); + } + + size_t getNumBasicBlocks() const { return Map.size(); } + }; + + /// Map function output address to its hash and basic blocks hash map. + class FuncHashesTy { + class EntryTy { + size_t Hash; + BBHashMapTy BBHashMap; + + public: + size_t getBFHash() const { return Hash; } + const BBHashMapTy &getBBHashMap() const { return BBHashMap; } + EntryTy(size_t Hash) : Hash(Hash) {} + }; + + std::unordered_map Map; + const EntryTy &getEntry(uint64_t FuncOutputAddress) const { + auto It = Map.find(FuncOutputAddress); + assert(It != Map.end()); + return It->second; + } + + public: + size_t getBFHash(uint64_t FuncOutputAddress) const { + return getEntry(FuncOutputAddress).getBFHash(); + } + + const BBHashMapTy &getBBHashMap(uint64_t FuncOutputAddress) const { + return getEntry(FuncOutputAddress).getBBHashMap(); + } + + void addEntry(uint64_t FuncOutputAddress, size_t BFHash) { + Map.emplace(FuncOutputAddress, EntryTy(BFHash)); + } + + size_t getNumFunctions() const { return Map.size(); }; + + size_t getNumBasicBlocks() const { + size_t NumBasicBlocks{0}; + for (auto &I : Map) + NumBasicBlocks += I.second.getBBHashMap().getNumBasicBlocks(); + return NumBasicBlocks; + } + }; + + /// Returns BF hash by function output address (after BOLT). + size_t getBFHash(uint64_t FuncOutputAddress) const { + return FuncHashes.getBFHash(FuncOutputAddress); + } + + /// Returns BBHashMap by function output address (after BOLT). + const BBHashMapTy &getBBHashMap(uint64_t FuncOutputAddress) const { + return FuncHashes.getBBHashMap(FuncOutputAddress); + } + + BBHashMapTy &getBBHashMap(uint64_t FuncOutputAddress) { + return const_cast( + std::as_const(*this).getBBHashMap(FuncOutputAddress)); + } + + /// Returns the number of basic blocks in a function. + size_t getNumBasicBlocks(uint64_t OutputAddress) const { + return NumBasicBlocksMap.at(OutputAddress); + } + +private: + FuncHashesTy FuncHashes; }; } // namespace bolt diff --git a/bolt/lib/Core/DIEBuilder.cpp b/bolt/lib/Core/DIEBuilder.cpp index 0cf8a5e8c2c3db8a4892a62b78ee1f326887bb89..354fe5059443cca6d56a3dde6a1fe0948a666355 100644 --- a/bolt/lib/Core/DIEBuilder.cpp +++ b/bolt/lib/Core/DIEBuilder.cpp @@ -545,6 +545,10 @@ void DIEBuilder::cloneDieReferenceAttribute( NewRefDie = DieInfo.Die; if (AttrSpec.Form == dwarf::DW_FORM_ref_addr) { + // Adding referenced DIE to DebugNames to be used when entries are created + // that contain cross cu references. + if (DebugNamesTable.canGenerateEntryWithCrossCUReference(U, Die, AttrSpec)) + DebugNamesTable.addCrossCUDie(DieInfo.Die); // no matter forward reference or backward reference, we are supposed // to calculate them in `finish` due to the possible modification of // the DIE. @@ -554,7 +558,7 @@ void DIEBuilder::cloneDieReferenceAttribute( std::make_pair(CurDieInfo, AddrReferenceInfo(&DieInfo, AttrSpec))); Die.addValue(getState().DIEAlloc, AttrSpec.Attr, dwarf::DW_FORM_ref_addr, - DIEInteger(0xDEADBEEF)); + DIEInteger(DieInfo.Die->getOffset())); return; } diff --git a/bolt/lib/Core/DebugNames.cpp b/bolt/lib/Core/DebugNames.cpp index 23a29f52513c04bb751e9932df923fa052419a95..049244c4b51518a88cd9d8af1b5d64c24010d705 100644 --- a/bolt/lib/Core/DebugNames.cpp +++ b/bolt/lib/Core/DebugNames.cpp @@ -146,6 +146,55 @@ static bool shouldIncludeVariable(const DWARFUnit &Unit, const DIE &Die) { return false; } +bool static canProcess(const DWARFUnit &Unit, const DIE &Die, + std::string &NameToUse, const bool TagsOnly) { + switch (Die.getTag()) { + case dwarf::DW_TAG_base_type: + case dwarf::DW_TAG_class_type: + case dwarf::DW_TAG_enumeration_type: + case dwarf::DW_TAG_imported_declaration: + case dwarf::DW_TAG_pointer_type: + case dwarf::DW_TAG_structure_type: + case dwarf::DW_TAG_typedef: + case dwarf::DW_TAG_unspecified_type: + if (TagsOnly || Die.findAttribute(dwarf::Attribute::DW_AT_name)) + return true; + return false; + case dwarf::DW_TAG_namespace: + // According to DWARF5 spec namespaces without DW_AT_name needs to have + // "(anonymous namespace)" + if (!Die.findAttribute(dwarf::Attribute::DW_AT_name)) + NameToUse = "(anonymous namespace)"; + return true; + case dwarf::DW_TAG_inlined_subroutine: + case dwarf::DW_TAG_label: + case dwarf::DW_TAG_subprogram: + if (TagsOnly || Die.findAttribute(dwarf::Attribute::DW_AT_low_pc) || + Die.findAttribute(dwarf::Attribute::DW_AT_high_pc) || + Die.findAttribute(dwarf::Attribute::DW_AT_ranges) || + Die.findAttribute(dwarf::Attribute::DW_AT_entry_pc)) + return true; + return false; + case dwarf::DW_TAG_variable: + return TagsOnly || shouldIncludeVariable(Unit, Die); + default: + break; + } + return false; +} + +bool DWARF5AcceleratorTable::canGenerateEntryWithCrossCUReference( + const DWARFUnit &Unit, const DIE &Die, + const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) { + if (!isCreated()) + return false; + std::string NameToUse = ""; + if (!canProcess(Unit, Die, NameToUse, true)) + return false; + return (AttrSpec.Attr == dwarf::Attribute::DW_AT_abstract_origin || + AttrSpec.Attr == dwarf::Attribute::DW_AT_specification) && + AttrSpec.Form == dwarf::DW_FORM_ref_addr; +} /// Returns name offset in String Offset section. static uint64_t getNameOffset(BinaryContext &BC, DWARFUnit &Unit, const uint64_t Index) { @@ -175,41 +224,6 @@ DWARF5AcceleratorTable::addAccelTableEntry( if (Unit.getVersion() < 5 || !NeedToCreate) return std::nullopt; std::string NameToUse = ""; - auto canProcess = [&](const DIE &Die) -> bool { - switch (Die.getTag()) { - case dwarf::DW_TAG_base_type: - case dwarf::DW_TAG_class_type: - case dwarf::DW_TAG_enumeration_type: - case dwarf::DW_TAG_imported_declaration: - case dwarf::DW_TAG_pointer_type: - case dwarf::DW_TAG_structure_type: - case dwarf::DW_TAG_typedef: - case dwarf::DW_TAG_unspecified_type: - if (Die.findAttribute(dwarf::Attribute::DW_AT_name)) - return true; - return false; - case dwarf::DW_TAG_namespace: - // According to DWARF5 spec namespaces without DW_AT_name needs to have - // "(anonymous namespace)" - if (!Die.findAttribute(dwarf::Attribute::DW_AT_name)) - NameToUse = "(anonymous namespace)"; - return true; - case dwarf::DW_TAG_inlined_subroutine: - case dwarf::DW_TAG_label: - case dwarf::DW_TAG_subprogram: - if (Die.findAttribute(dwarf::Attribute::DW_AT_low_pc) || - Die.findAttribute(dwarf::Attribute::DW_AT_high_pc) || - Die.findAttribute(dwarf::Attribute::DW_AT_ranges) || - Die.findAttribute(dwarf::Attribute::DW_AT_entry_pc)) - return true; - return false; - case dwarf::DW_TAG_variable: - return shouldIncludeVariable(Unit, Die); - default: - break; - } - return false; - }; auto getUnitID = [&](const DWARFUnit &Unit, bool &IsTU, uint32_t &DieTag) -> uint32_t { @@ -223,7 +237,7 @@ DWARF5AcceleratorTable::addAccelTableEntry( return CUList.size() - 1; }; - if (!canProcess(Die)) + if (!canProcess(Unit, Die, NameToUse, false)) return std::nullopt; // Addes a Unit to either CU, LocalTU or ForeignTU list the first time we @@ -318,10 +332,24 @@ DWARF5AcceleratorTable::addAccelTableEntry( const DIEValue Value = Die.findAttribute(Attr); if (!Value) return std::nullopt; - const DIEEntry &DIEENtry = Value.getDIEEntry(); - DIE &EntryDie = DIEENtry.getEntry(); - addEntry(EntryDie.findAttribute(dwarf::Attribute::DW_AT_linkage_name)); - return addEntry(EntryDie.findAttribute(dwarf::Attribute::DW_AT_name)); + const DIE *EntryDie = nullptr; + if (Value.getForm() == dwarf::DW_FORM_ref_addr) { + auto Iter = CrossCUDies.find(Value.getDIEInteger().getValue()); + if (Iter == CrossCUDies.end()) { + BC.errs() << "BOLT-WARNING: [internal-dwarf-warning]: Could not find " + "referenced DIE in CrossCUDies for " + << Twine::utohexstr(Value.getDIEInteger().getValue()) + << ".\n"; + return std::nullopt; + } + EntryDie = Iter->second; + } else { + const DIEEntry &DIEENtry = Value.getDIEEntry(); + EntryDie = &DIEENtry.getEntry(); + } + + addEntry(EntryDie->findAttribute(dwarf::Attribute::DW_AT_linkage_name)); + return addEntry(EntryDie->findAttribute(dwarf::Attribute::DW_AT_name)); }; if (std::optional Entry = @@ -332,7 +360,6 @@ DWARF5AcceleratorTable::addAccelTableEntry( return *Entry; return addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_name)); - ; } /// Algorithm from llvm implementation. diff --git a/bolt/lib/Profile/BoltAddressTranslation.cpp b/bolt/lib/Profile/BoltAddressTranslation.cpp index 7606a92de1dc982b11b9a3cbcd8f65fe427f492c..bcd4a457ce3b491908b0a1617e66bee322cdd7c6 100644 --- a/bolt/lib/Profile/BoltAddressTranslation.cpp +++ b/bolt/lib/Profile/BoltAddressTranslation.cpp @@ -22,12 +22,10 @@ const char *BoltAddressTranslation::SECTION_NAME = ".note.bolt_bat"; void BoltAddressTranslation::writeEntriesForBB(MapTy &Map, const BinaryBasicBlock &BB, - uint64_t FuncAddress) { - uint64_t HotFuncAddress = ColdPartSource.count(FuncAddress) - ? ColdPartSource[FuncAddress] - : FuncAddress; + uint64_t FuncInputAddress, + uint64_t FuncOutputAddress) { const uint64_t BBOutputOffset = - BB.getOutputAddressRange().first - FuncAddress; + BB.getOutputAddressRange().first - FuncOutputAddress; const uint32_t BBInputOffset = BB.getInputOffset(); // Every output BB must track back to an input BB for profile collection @@ -42,11 +40,14 @@ void BoltAddressTranslation::writeEntriesForBB(MapTy &Map, LLVM_DEBUG(dbgs() << "BB " << BB.getName() << "\n"); LLVM_DEBUG(dbgs() << " Key: " << Twine::utohexstr(BBOutputOffset) << " Val: " << Twine::utohexstr(BBInputOffset) << "\n"); - LLVM_DEBUG(dbgs() << formatv(" Hash: {0:x}\n", - getBBHash(HotFuncAddress, BBInputOffset))); - (void)HotFuncAddress; - LLVM_DEBUG(dbgs() << formatv(" Index: {0}\n", - getBBIndex(HotFuncAddress, BBInputOffset))); + // NB: in `writeEntriesForBB` we use the input address because hashes are + // saved early in `saveMetadata` before output addresses are assigned. + const BBHashMapTy &BBHashMap = getBBHashMap(FuncInputAddress); + (void)BBHashMap; + LLVM_DEBUG( + dbgs() << formatv(" Hash: {0:x}\n", BBHashMap.getBBHash(BBInputOffset))); + LLVM_DEBUG( + dbgs() << formatv(" Index: {0}\n", BBHashMap.getBBIndex(BBInputOffset))); // In case of conflicts (same Key mapping to different Vals), the last // update takes precedence. Of course it is not ideal to have conflicts and // those happen when we have an empty BB that either contained only @@ -63,7 +64,7 @@ void BoltAddressTranslation::writeEntriesForBB(MapTy &Map, const auto InputAddress = BB.getFunction()->getAddress() + InputOffset; const auto OutputAddress = IOAddressMap.lookup(InputAddress); assert(OutputAddress && "Unknown instruction address"); - const auto OutputOffset = *OutputAddress - FuncAddress; + const auto OutputOffset = *OutputAddress - FuncOutputAddress; // Is this the first instruction in the BB? No need to duplicate the entry. if (OutputOffset == BBOutputOffset) @@ -106,7 +107,7 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) { MapTy Map; for (const BinaryBasicBlock *const BB : Function.getLayout().getMainFragment()) - writeEntriesForBB(Map, *BB, Function.getOutputAddress()); + writeEntriesForBB(Map, *BB, InputAddress, OutputAddress); Maps.emplace(Function.getOutputAddress(), std::move(Map)); ReverseMap.emplace(OutputAddress, InputAddress); @@ -120,7 +121,7 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) { ColdPartSource.emplace(FF.getAddress(), Function.getOutputAddress()); Map.clear(); for (const BinaryBasicBlock *const BB : FF) - writeEntriesForBB(Map, *BB, FF.getAddress()); + writeEntriesForBB(Map, *BB, InputAddress, FF.getAddress()); Maps.emplace(FF.getAddress(), std::move(Map)); } @@ -132,11 +133,9 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) { writeMaps(Maps, PrevAddress, OS); BC.outs() << "BOLT-INFO: Wrote " << Maps.size() << " BAT maps\n"; - const uint64_t NumBBHashes = std::accumulate( - FuncHashes.begin(), FuncHashes.end(), 0ull, - [](size_t Acc, const auto &B) { return Acc + B.second.second.size(); }); - BC.outs() << "BOLT-INFO: Wrote " << FuncHashes.size() << " function and " - << NumBBHashes << " basic block hashes\n"; + BC.outs() << "BOLT-INFO: Wrote " << FuncHashes.getNumFunctions() + << " function and " << FuncHashes.getNumBasicBlocks() + << " basic block hashes\n"; } APInt BoltAddressTranslation::calculateBranchEntriesBitMask(MapTy &Map, @@ -183,11 +182,10 @@ void BoltAddressTranslation::writeMaps(std::map &Maps, // Only process cold fragments in cold mode, and vice versa. if (Cold != ColdPartSource.count(Address)) continue; - // NB: here we use the input address because hashes are saved early (in - // `saveMetadata`) before output addresses are assigned. + // NB: in `writeMaps` we use the input address because hashes are saved + // early in `saveMetadata` before output addresses are assigned. const uint64_t HotInputAddress = ReverseMap[Cold ? ColdPartSource[Address] : Address]; - std::pair &FuncHashPair = FuncHashes[HotInputAddress]; MapTy &Map = MapEntry.second; const uint32_t NumEntries = Map.size(); LLVM_DEBUG(dbgs() << "Writing " << NumEntries << " entries for 0x" @@ -196,7 +194,7 @@ void BoltAddressTranslation::writeMaps(std::map &Maps, PrevAddress = Address; const uint32_t NumSecondaryEntryPoints = SecondaryEntryPointsMap.count(Address) - ? SecondaryEntryPointsMap.at(Address).size() + ? SecondaryEntryPointsMap[Address].size() : 0; if (Cold) { size_t HotIndex = @@ -205,10 +203,11 @@ void BoltAddressTranslation::writeMaps(std::map &Maps, PrevIndex = HotIndex; } else { // Function hash - LLVM_DEBUG(dbgs() << "Hash: " << formatv("{0:x}\n", FuncHashPair.first)); - OS.write(reinterpret_cast(&FuncHashPair.first), 8); + size_t BFHash = getBFHash(HotInputAddress); + LLVM_DEBUG(dbgs() << "Hash: " << formatv("{0:x}\n", BFHash)); + OS.write(reinterpret_cast(&BFHash), 8); // Number of basic blocks - size_t NumBasicBlocks = FuncHashPair.second.size(); + size_t NumBasicBlocks = getBBHashMap(HotInputAddress).getNumBasicBlocks(); LLVM_DEBUG(dbgs() << "Basic blocks: " << NumBasicBlocks << '\n'); encodeULEB128(NumBasicBlocks, OS); // Secondary entry points @@ -236,6 +235,7 @@ void BoltAddressTranslation::writeMaps(std::map &Maps, }); } } + const BBHashMapTy &BBHashMap = getBBHashMap(HotInputAddress); size_t Index = 0; uint64_t InOffset = 0; size_t PrevBBIndex = 0; @@ -248,9 +248,9 @@ void BoltAddressTranslation::writeMaps(std::map &Maps, encodeSLEB128(KeyVal.second - InOffset, OS); InOffset = KeyVal.second; // Keeping InOffset as if BRANCHENTRY is encoded if ((InOffset & BRANCHENTRY) == 0) { - unsigned BBIndex; - size_t BBHash; - std::tie(BBIndex, BBHash) = FuncHashPair.second[InOffset >> 1]; + const bool IsBlock = BBHashMap.isInputBlock(InOffset >> 1); + unsigned BBIndex = IsBlock ? BBHashMap.getBBIndex(InOffset >> 1) : 0; + size_t BBHash = IsBlock ? BBHashMap.getBBHash(InOffset >> 1) : 0; OS.write(reinterpret_cast(&BBHash), 8); // Basic block index in the input binary encodeULEB128(BBIndex - PrevBBIndex, OS); @@ -263,7 +263,7 @@ void BoltAddressTranslation::writeMaps(std::map &Maps, if (!Cold && NumSecondaryEntryPoints) { LLVM_DEBUG(dbgs() << "Secondary entry points: "); // Secondary entry point offsets, delta-encoded - for (uint32_t Offset : SecondaryEntryPointsMap.at(Address)) { + for (uint32_t Offset : SecondaryEntryPointsMap[Address]) { encodeULEB128(Offset - PrevOffset, OS); LLVM_DEBUG(dbgs() << formatv("{0:x} ", Offset)); PrevOffset = Offset; @@ -322,7 +322,7 @@ void BoltAddressTranslation::parseMaps(std::vector &HotFuncs, HotFuncs.push_back(Address); // Function hash const size_t FuncHash = DE.getU64(&Offset, &Err); - FuncHashes[Address].first = FuncHash; + FuncHashes.addEntry(Address, FuncHash); LLVM_DEBUG(dbgs() << formatv("{0:x}: hash {1:x}\n", Address, FuncHash)); // Number of basic blocks const size_t NumBasicBlocks = DE.getULEB128(&Offset, &Err); @@ -388,8 +388,7 @@ void BoltAddressTranslation::parseMaps(std::vector &HotFuncs, BBIndexDelta = DE.getULEB128(&Offset, &Err); BBIndex += BBIndexDelta; // Map basic block hash to hot fragment by input offset - FuncHashes[HotAddress].second.emplace(InputOffset >> 1, - std::pair(BBIndex, BBHash)); + getBBHashMap(HotAddress).addEntry(InputOffset >> 1, BBIndex, BBHash); } LLVM_DEBUG({ dbgs() << formatv( @@ -431,6 +430,8 @@ void BoltAddressTranslation::dump(raw_ostream &OS) { OS << formatv(", hash: {0:x}", getBFHash(Address)); OS << "\n"; OS << "BB mappings:\n"; + const BBHashMapTy &BBHashMap = + getBBHashMap(HotAddress ? HotAddress : Address); for (const auto &Entry : MapEntry.second) { const bool IsBranch = Entry.second & BRANCHENTRY; const uint32_t Val = Entry.second >> 1; // dropping BRANCHENTRY bit @@ -439,10 +440,16 @@ void BoltAddressTranslation::dump(raw_ostream &OS) { if (IsBranch) OS << " (branch)"; else - OS << formatv(" hash: {0:x}", - getBBHash(HotAddress ? HotAddress : Address, Val)); + OS << formatv(" hash: {0:x}", BBHashMap.getBBHash(Val)); OS << "\n"; } + if (SecondaryEntryPointsMap.count(Address)) { + const std::vector &SecondaryEntryPoints = + SecondaryEntryPointsMap[Address]; + OS << SecondaryEntryPoints.size() << " secondary entry points:\n"; + for (uint32_t EntryPointOffset : SecondaryEntryPoints) + OS << formatv("{0:x}\n", EntryPointOffset); + } OS << "\n"; } const size_t NumColdParts = ColdPartSource.size(); @@ -561,28 +568,15 @@ void BoltAddressTranslation::saveMetadata(BinaryContext &BC) { if (BF.isIgnored() || (!BC.HasRelocations && !BF.isSimple())) continue; // Prepare function and block hashes - FuncHashes[BF.getAddress()].first = BF.computeHash(); + FuncHashes.addEntry(BF.getAddress(), BF.computeHash()); BF.computeBlockHashes(); + BBHashMapTy &BBHashMap = getBBHashMap(BF.getAddress()); + // Set BF/BB metadata for (const BinaryBasicBlock &BB : BF) - FuncHashes[BF.getAddress()].second.emplace( - BB.getInputOffset(), std::pair(BB.getIndex(), BB.getHash())); + BBHashMap.addEntry(BB.getInputOffset(), BB.getIndex(), BB.getHash()); } } -size_t BoltAddressTranslation::getBBHash(uint64_t FuncOutputAddress, - uint32_t BBInputOffset) const { - return getBBHash(getBBHashMap(FuncOutputAddress), BBInputOffset); -} - -size_t BoltAddressTranslation::getBFHash(uint64_t OutputAddress) const { - return FuncHashes.at(OutputAddress).first; -} - -unsigned BoltAddressTranslation::getBBIndex(uint64_t FuncOutputAddress, - uint32_t BBInputOffset) const { - return getBBIndex(getBBHashMap(FuncOutputAddress), BBInputOffset); -} - std::unordered_map> BoltAddressTranslation::getBFBranches(uint64_t OutputAddress) const { std::unordered_map> Branches; @@ -602,5 +596,6 @@ BoltAddressTranslation::getBFBranches(uint64_t OutputAddress) const { } return Branches; } + } // namespace bolt } // namespace llvm diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index 5bb5953aa8e5075c4ae3d48b4d10fd134039a493..05099aa25ce22738687c0e3106e63302fadc0540 100644 --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -30,7 +30,6 @@ #include "llvm/Support/Regex.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" -#include #include #include #include @@ -2356,21 +2355,17 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC, YamlBF.Hash = BAT->getBFHash(FuncAddress); YamlBF.ExecCount = BF->getKnownExecutionCount(); YamlBF.NumBasicBlocks = BAT->getNumBasicBlocks(FuncAddress); - const auto &BlockMap = BAT->getBBHashMap(FuncAddress); - - auto addBBProfile = [&](yaml::bolt::BinaryBasicBlockProfile &YamlBB, - uint64_t Offset) { - if (!Branches.IntraIndex.contains(Offset)) - return; - for (const auto &[SuccOffset, SuccIdx] : - Branches.IntraIndex.at(Offset)) { - const llvm::bolt::BranchInfo &BI = Branches.Data.at(SuccIdx); - yaml::bolt::SuccessorInfo SI; - SI.Index = BAT->getBBIndex(BlockMap, SuccOffset); - SI.Count = BI.Branches; - SI.Mispreds = BI.Mispreds; - YamlBB.Successors.emplace_back(SI); - } + const BoltAddressTranslation::BBHashMapTy &BlockMap = + BAT->getBBHashMap(FuncAddress); + + auto addSuccProfile = [&](yaml::bolt::BinaryBasicBlockProfile &YamlBB, + uint64_t SuccOffset, unsigned SuccDataIdx) { + const llvm::bolt::BranchInfo &BI = Branches.Data.at(SuccDataIdx); + yaml::bolt::SuccessorInfo SI; + SI.Index = BlockMap.getBBIndex(SuccOffset); + SI.Count = BI.Branches; + SI.Mispreds = BI.Mispreds; + YamlBB.Successors.emplace_back(SI); }; std::unordered_map> BFBranches = @@ -2430,11 +2425,15 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC, } }; - for (const auto &[Offset, Val] : BlockMap) { + for (const auto &[FromOffset, SuccKV] : Branches.IntraIndex) { yaml::bolt::BinaryBasicBlockProfile YamlBB; - std::tie(YamlBB.Index, YamlBB.Hash) = Val; - addBBProfile(YamlBB, Offset); - addCallsProfile(YamlBB, Offset); + if (!BlockMap.isInputBlock(FromOffset)) + continue; + YamlBB.Index = BlockMap.getBBIndex(FromOffset); + YamlBB.Hash = BlockMap.getBBHash(FromOffset); + for (const auto &[SuccOffset, SuccDataIdx] : SuccKV) + addSuccProfile(YamlBB, SuccOffset, SuccDataIdx); + addCallsProfile(YamlBB, FromOffset); if (YamlBB.ExecCount || !YamlBB.Successors.empty() || !YamlBB.CallSites.empty()) YamlBF.Blocks.emplace_back(YamlBB); diff --git a/bolt/lib/Rewrite/BinaryPassManager.cpp b/bolt/lib/Rewrite/BinaryPassManager.cpp index 489b33fe1c7c201aa11b07f76d5d369170b9ef02..6c26bb7957269d71c06da0d33bfe80984b0f4e16 100644 --- a/bolt/lib/Rewrite/BinaryPassManager.cpp +++ b/bolt/lib/Rewrite/BinaryPassManager.cpp @@ -72,7 +72,7 @@ static cl::opt JTFootprintReductionFlag( "instructions at jump sites"), cl::cat(BoltOptCategory)); -static cl::opt +cl::opt KeepNops("keep-nops", cl::desc("keep no-op instructions. By default they are removed."), cl::Hidden, cl::cat(BoltOptCategory)); diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp index 8dc7b90a6e307e72f22b3c8053859cadeaa823d1..601a2105fc264f7af2168528d29af291991de27f 100644 --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -375,12 +375,11 @@ static cl::opt AlwaysConvertToRanges( extern cl::opt CompDirOverride; } // namespace opts -static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU, - uint64_t &LowPC, uint64_t &HighPC, - uint64_t &SectionIndex) { +/// If DW_AT_low_pc exists sets LowPC and returns true. +static bool getLowPC(const DIE &Die, const DWARFUnit &DU, uint64_t &LowPC, + uint64_t &SectionIndex) { DIEValue DvalLowPc = Die.findAttribute(dwarf::DW_AT_low_pc); - DIEValue DvalHighPc = Die.findAttribute(dwarf::DW_AT_high_pc); - if (!DvalLowPc || !DvalHighPc) + if (!DvalLowPc) return false; dwarf::Form Form = DvalLowPc.getForm(); @@ -403,14 +402,39 @@ static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU, LowPC = LowPcValue; SectionIndex = 0; } + return true; +} + +/// If DW_AT_high_pc exists sets HighPC and returns true. +static bool getHighPC(const DIE &Die, const uint64_t LowPC, uint64_t &HighPC) { + DIEValue DvalHighPc = Die.findAttribute(dwarf::DW_AT_high_pc); + if (!DvalHighPc) + return false; if (DvalHighPc.getForm() == dwarf::DW_FORM_addr) HighPC = DvalHighPc.getDIEInteger().getValue(); else HighPC = LowPC + DvalHighPc.getDIEInteger().getValue(); - return true; } +/// If DW_AT_low_pc and DW_AT_high_pc exist sets LowPC and HighPC and returns +/// true. +static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU, + uint64_t &LowPC, uint64_t &HighPC, + uint64_t &SectionIndex) { + uint64_t TempLowPC = LowPC; + uint64_t TempHighPC = HighPC; + uint64_t TempSectionIndex = SectionIndex; + if (getLowPC(Die, DU, TempLowPC, TempSectionIndex) && + getHighPC(Die, TempLowPC, TempHighPC)) { + LowPC = TempLowPC; + HighPC = TempHighPC; + SectionIndex = TempSectionIndex; + return true; + } + return false; +} + static Expected getDIEAddressRanges(const DIE &Die, DWARFUnit &DU) { uint64_t LowPC, HighPC, Index; @@ -1248,10 +1272,9 @@ void DWARFRewriter::updateUnitDebugInfo( } } } else if (LowPCAttrInfo) { - const std::optional Result = - LowPCAttrInfo.getDIEInteger().getValue(); - if (Result.has_value()) { - const uint64_t Address = Result.value(); + uint64_t Address = 0; + uint64_t SectionIndex = 0; + if (getLowPC(*Die, Unit, Address, SectionIndex)) { uint64_t NewAddress = 0; if (const BinaryFunction *Function = BC.getBinaryFunctionContainingAddress(Address)) { diff --git a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp index b028a455a6db526b81d56cc6d73b2fed737ca91f..42df9681727590044205e3031fcc293f1b449752 100644 --- a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp +++ b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp @@ -252,11 +252,17 @@ class LinuxKernelRewriter final : public MetadataRewriter { /// Paravirtual instruction patch sites. Error readParaInstructions(); + Error rewriteParaInstructions(); Error readBugTable(); - /// Read alternative instruction info from .altinstructions. + /// Do no process functions containing instruction annotated with + /// \p Annotation. + void skipFunctionsWithAnnotation(StringRef Annotation) const; + + /// Handle alternative instruction info from .altinstructions. Error readAltInstructions(); + Error rewriteAltInstructions(); /// Read .pci_fixup Error readPCIFixupTable(); @@ -318,6 +324,12 @@ public: if (Error E = rewriteExceptionTable()) return E; + if (Error E = rewriteAltInstructions()) + return E; + + if (Error E = rewriteParaInstructions()) + return E; + if (Error E = rewriteORCTables()) return E; @@ -1126,6 +1138,31 @@ Error LinuxKernelRewriter::readParaInstructions() { return Error::success(); } +void LinuxKernelRewriter::skipFunctionsWithAnnotation( + StringRef Annotation) const { + for (BinaryFunction &BF : llvm::make_second_range(BC.getBinaryFunctions())) { + if (!BC.shouldEmit(BF)) + continue; + for (const BinaryBasicBlock &BB : BF) { + const bool HasAnnotation = llvm::any_of(BB, [&](const MCInst &Inst) { + return BC.MIB->hasAnnotation(Inst, Annotation); + }); + if (HasAnnotation) { + BF.setSimple(false); + break; + } + } + } +} + +Error LinuxKernelRewriter::rewriteParaInstructions() { + // Disable output of functions with paravirtual instructions before the + // rewrite support is complete. + skipFunctionsWithAnnotation("ParaSite"); + + return Error::success(); +} + /// Process __bug_table section. /// This section contains information useful for kernel debugging. /// Each entry in the section is a struct bug_entry that contains a pointer to @@ -1305,6 +1342,14 @@ Error LinuxKernelRewriter::readAltInstructions() { return Error::success(); } +Error LinuxKernelRewriter::rewriteAltInstructions() { + // Disable output of functions with alt instructions before the rewrite + // support is complete. + skipFunctionsWithAnnotation("AltInst"); + + return Error::success(); +} + /// When the Linux kernel needs to handle an error associated with a given PCI /// device, it uses a table stored in .pci_fixup section to locate a fixup code /// specific to the vendor and the problematic device. The section contains a @@ -1679,6 +1724,8 @@ Error LinuxKernelRewriter::updateStaticKeysJumpTablePostEmit() { << "\n\tTargetAddress: 0x" << Twine::utohexstr(TargetAddress) << "\n\tKeyAddress: 0x" << Twine::utohexstr(KeyAddress) << '\n'; }); + (void)TargetAddress; + (void)KeyAddress; BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(JumpAddress, diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 03f4298e817d179a80e6b1de268630ec1227ad73..2ead51ff6a1286ffbc2a0c7b873c532c4aa4ea01 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -81,6 +81,7 @@ extern cl::list HotTextMoveSections; extern cl::opt Hugify; extern cl::opt Instrument; extern cl::opt JumpTables; +extern cl::opt KeepNops; extern cl::list ReorderData; extern cl::opt ReorderFunctions; extern cl::opt TimeBuild; @@ -2031,6 +2032,9 @@ void RewriteInstance::adjustCommandLineOptions() { if (opts::Lite) BC->outs() << "BOLT-INFO: enabling lite mode\n"; + + if (BC->IsLinuxKernel && !opts::KeepNops.getNumOccurrences()) + opts::KeepNops = true; } namespace { diff --git a/bolt/test/X86/bolt-address-translation-yaml.test b/bolt/test/X86/bolt-address-translation-yaml.test index 6513c7883fabc02e7c1ad8dad0f6da88e0011908..7fdf7709a8b9da3d2f103ec88c9b8ad1191893e7 100644 --- a/bolt/test/X86/bolt-address-translation-yaml.test +++ b/bolt/test/X86/bolt-address-translation-yaml.test @@ -18,7 +18,7 @@ RUN: | FileCheck --check-prefix CHECK-BOLT-YAML %s WRITE-BAT-CHECK: BOLT-INFO: Wrote 5 BAT maps WRITE-BAT-CHECK: BOLT-INFO: Wrote 4 function and 22 basic block hashes -WRITE-BAT-CHECK: BOLT-INFO: BAT section size (bytes): 380 +WRITE-BAT-CHECK: BOLT-INFO: BAT section size (bytes): 384 READ-BAT-CHECK-NOT: BOLT-ERROR: unable to save profile in YAML format for input file processed by BOLT READ-BAT-CHECK: BOLT-INFO: Parsed 5 BAT entries @@ -61,4 +61,4 @@ YAML-BAT-CHECK-NEXT: hash: 0xD70DC695320E0010 YAML-BAT-CHECK-NEXT: succ: {{.*}} { bid: 2, cnt: [[#]] } CHECK-BOLT-YAML: pre-processing profile using YAML profile reader -CHECK-BOLT-YAML-NEXT: 1 out of 16 functions in the binary (6.2%) have non-empty execution profile +CHECK-BOLT-YAML-NEXT: 5 out of 16 functions in the binary (31.2%) have non-empty execution profile diff --git a/bolt/test/X86/dwarf4-label-low-pc.s b/bolt/test/X86/dwarf4-label-low-pc.s new file mode 100644 index 0000000000000000000000000000000000000000..dfd5af18c09b75934fb6cac317d4d6807bcea5d4 --- /dev/null +++ b/bolt/test/X86/dwarf4-label-low-pc.s @@ -0,0 +1,263 @@ + +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %s -o %tmain.o +# RUN: %clang %cflags -dwarf-4 %tmain.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-info %t.bolt > %t.txt +# RUN: llvm-objdump -d %t.bolt >> %t.txt +# RUN: cat %t.txt | FileCheck --check-prefix=POSTCHECK %s + +## This test checks that we correctly handle DW_AT_low_pc [DW_FORM_addr] that is part of DW_TAG_label. + +# PRECHECK: version = 0x0004 +# PRECHECK: DW_TAG_label +# PRECHECK-NEXT: DW_AT_name +# PRECHECK-NEXT: DW_AT_decl_file +# PRECHECK-NEXT: DW_AT_decl_line +# PRECHECK-NEXT:DW_AT_low_pc [DW_FORM_addr] +# PRECHECK: DW_TAG_label +# PRECHECK-NEXT: DW_AT_name +# PRECHECK-NEXT: DW_AT_decl_file +# PRECHECK-NEXT: DW_AT_decl_line +# PRECHECK-NEXT:DW_AT_low_pc [DW_FORM_addr] + +# POSTCHECK: version = 0x0004 +# POSTCHECK: DW_TAG_label +# POSTCHECK-NEXT: DW_AT_name +# POSTCHECK-NEXT: DW_AT_decl_file +# POSTCHECK-NEXT: DW_AT_decl_line +# POSTCHECK-NEXT:DW_AT_low_pc [DW_FORM_addr] (0x[[ADDR:[1-9a-f]*]] +# POSTCHECK: DW_TAG_label +# POSTCHECK-NEXT: DW_AT_name +# POSTCHECK-NEXT: DW_AT_decl_file +# POSTCHECK-NEXT: DW_AT_decl_line +# POSTCHECK-NEXT:DW_AT_low_pc [DW_FORM_addr] (0x[[ADDR2:[1-9a-f]*]] + +# POSTCHECK: [[ADDR]]: 8b 45 f8 +# POSTCHECK: [[ADDR2]]: 8b 45 f8 + +## clang++ main.cpp -g2 -gdwarf-4 -S +## int main() { +## int a = 4; +## if (a == 5) +## goto LABEL1; +## else +## goto LABEL2; +## LABEL1:a++; +## LABEL2:a--; +## return 0; +## } + + .text + .file "main.cpp" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 1 "/home" "main.cpp" + .loc 1 1 0 # main.cpp:1: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) +.Ltmp0: + .loc 1 2 7 prologue_end # main.cpp:2:7 + movl $4, -8(%rbp) +.Ltmp1: + .loc 1 3 9 # main.cpp:3:9 + cmpl $5, -8(%rbp) +.Ltmp2: + .loc 1 3 7 is_stmt 0 # main.cpp:3:7 + jne .LBB0_2 +# %bb.1: # %if.then +.Ltmp3: + .loc 1 4 5 is_stmt 1 # main.cpp:4:5 + jmp .LBB0_3 +.LBB0_2: # %if.else + .loc 1 6 5 # main.cpp:6:5 + jmp .LBB0_4 +.Ltmp4: +.LBB0_3: # %LABEL1 + #DEBUG_LABEL: main:LABEL1 + .loc 1 7 11 # main.cpp:7:11 + movl -8(%rbp), %eax + addl $1, %eax + movl %eax, -8(%rbp) +.LBB0_4: # %LABEL2 +.Ltmp5: + #DEBUG_LABEL: main:LABEL2 + .loc 1 8 11 # main.cpp:8:11 + movl -8(%rbp), %eax + addl $-1, %eax + movl %eax, -8(%rbp) + .loc 1 9 3 # main.cpp:9:3 + xorl %eax, %eax + .loc 1 9 3 epilogue_begin is_stmt 0 # main.cpp:9:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp6: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .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 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .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 1 # DW_FORM_addr + .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 14 # DW_FORM_strp + .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 3 # 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 14 # DW_FORM_strp + .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 10 # DW_TAG_label + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .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 14 # DW_FORM_strp + .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 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:0x6d DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 2 # Abbrev [2] 0x2a:0x46 DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .long .Linfo_string3 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 112 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x43:0xe DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .long .Linfo_string5 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 112 # DW_AT_type + .byte 4 # Abbrev [4] 0x51:0xf DW_TAG_label + .long .Linfo_string6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .quad .Ltmp4 # DW_AT_low_pc + .byte 4 # Abbrev [4] 0x60:0xf DW_TAG_label + .long .Linfo_string7 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .quad .Ltmp5 # DW_AT_low_pc + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x70:0x7 DW_TAG_base_type + .long .Linfo_string4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=24 +.Linfo_string2: + .asciz "/home" # string offset=33 +.Linfo_string3: + .asciz "main" # string offset=71 +.Linfo_string4: + .asciz "int" # string offset=76 +.Linfo_string5: + .asciz "a" # string offset=80 +.Linfo_string6: + .asciz "LABEL1" # string offset=82 +.Linfo_string7: + .asciz "LABEL2" # string offset=89 + .ident "clang version 19.0.0git" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/dwarf5-debug-names-cross-cu.s b/bolt/test/X86/dwarf5-debug-names-cross-cu.s new file mode 100644 index 0000000000000000000000000000000000000000..73c50d6d41db09cf2976d91c71da4ed8dcaea3cd --- /dev/null +++ b/bolt/test/X86/dwarf5-debug-names-cross-cu.s @@ -0,0 +1,712 @@ + +# REQUIRES: system-linux + +# 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-dwarfdump --debug-info -r 0 --debug-names %t.bolt > %t.txt +# RUN: cat %t.txt | FileCheck --check-prefix=CHECK %s + +## This test checks that BOLT generates Entries for DW_AT_abstract_origin when it has cross cu reference. + +# CHECK: [[OFFSET1:0x[0-9a-f]*]]: Compile Unit +# CHECK: [[OFFSET2:0x[0-9a-f]*]]: Compile Unit +# CHECK: Name Index @ 0x0 { +# CHECK-NEXT: Header { +# CHECK-NEXT: Length: 0xD2 +# CHECK-NEXT: Format: DWARF32 +# CHECK-NEXT: Version: 5 +# CHECK-NEXT: CU count: 2 +# CHECK-NEXT: Local TU count: 0 +# CHECK-NEXT: Foreign TU count: 0 +# CHECK-NEXT: Bucket count: 5 +# CHECK-NEXT: Name count: 5 +# CHECK-NEXT: Abbreviations table size: 0x1F +# CHECK-NEXT: Augmentation: 'BOLT' +# CHECK-NEXT: } +# CHECK-NEXT: Compilation Unit offsets [ +# CHECK-NEXT: CU[0]: [[OFFSET1]] +# CHECK-NEXT: CU[1]: [[OFFSET2]] +# CHECK-NEXT: ] +# CHECK-NEXT: Abbreviations [ +# CHECK-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] { +# CHECK-NEXT: Tag: DW_TAG_subprogram +# CHECK-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +# CHECK-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# CHECK-NEXT: DW_IDX_parent: DW_FORM_flag_present +# CHECK-NEXT: } +# CHECK-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { +# CHECK-NEXT: Tag: DW_TAG_inlined_subroutine +# CHECK-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +# CHECK-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# CHECK-NEXT: DW_IDX_parent: DW_FORM_ref4 +# CHECK-NEXT: } +# CHECK-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { +# CHECK-NEXT: Tag: DW_TAG_base_type +# CHECK-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +# CHECK-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# CHECK-NEXT: DW_IDX_parent: DW_FORM_flag_present +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: Bucket 0 [ +# CHECK-NEXT: EMPTY +# CHECK-NEXT: ] +# CHECK-NEXT: Bucket 1 [ +# CHECK-NEXT: Name 1 { +# CHECK-NEXT: Hash: 0x7C9A7F6A +# CHECK-NEXT: String: {{.+}} "main" +# CHECK-NEXT: Entry @ [[ENTRY:0x[0-9a-f]*]] { +# CHECK-NEXT: Abbrev: [[ABBREV1]] +# CHECK-NEXT: Tag: DW_TAG_subprogram +# CHECK-NEXT: DW_IDX_compile_unit: 0x00 +# CHECK-NEXT: DW_IDX_die_offset: 0x00000024 +# CHECK-NEXT: DW_IDX_parent: +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: Name 2 { +# CHECK-NEXT: Hash: 0xB5063CFE +# CHECK-NEXT: String: {{.+}} "_Z3fooi" +# CHECK-NEXT: Entry @ {{.+}} { +# CHECK-NEXT: Abbrev: [[ABBREV1]] +# CHECK-NEXT: Tag: DW_TAG_subprogram +# CHECK-NEXT: DW_IDX_compile_unit: 0x01 +# CHECK-NEXT: DW_IDX_die_offset: 0x0000003a +# CHECK-NEXT: DW_IDX_parent: +# CHECK-NEXT: } +# CHECK-NEXT: Entry @ {{.+}} { +# CHECK-NEXT: Abbrev: [[ABBREV2]] +# CHECK-NEXT: Tag: DW_TAG_inlined_subroutine +# CHECK-NEXT: DW_IDX_compile_unit: 0x00 +# CHECK-NEXT: DW_IDX_die_offset: 0x00000054 +# CHECK-NEXT: DW_IDX_parent: Entry @ [[ENTRY]] +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: Bucket 2 [ +# CHECK-NEXT: EMPTY +# CHECK-NEXT: ] +# CHECK-NEXT: Bucket 3 [ +# CHECK-NEXT: Name 3 { +# CHECK-NEXT: Hash: 0xB888030 +# CHECK-NEXT: String: {{.+}} "int" +# CHECK-NEXT: Entry @ {{.+}} { +# CHECK-NEXT: Abbrev: [[ABBREV3]] +# CHECK-NEXT: Tag: DW_TAG_base_type +# CHECK-NEXT: DW_IDX_compile_unit: 0x01 +# CHECK-NEXT: DW_IDX_die_offset: 0x00000036 +# CHECK-NEXT: DW_IDX_parent: +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: Bucket 4 [ +# CHECK-NEXT: Name 4 { +# CHECK-NEXT: Hash: 0xB887389 +# CHECK-NEXT: String: {{.+}} "foo" +# CHECK-NEXT: Entry @ {{.+}} { +# CHECK-NEXT: Abbrev: [[ABBREV1]] +# CHECK-NEXT: Tag: DW_TAG_subprogram +# CHECK-NEXT: DW_IDX_compile_unit: 0x01 +# CHECK-NEXT: DW_IDX_die_offset: 0x0000003a +# CHECK-NEXT: DW_IDX_parent: +# CHECK-NEXT: } +# CHECK-NEXT: Entry @ 0xc4 { +# CHECK-NEXT: Abbrev: [[ABBREV2]] +# CHECK-NEXT: Tag: DW_TAG_inlined_subroutine +# CHECK-NEXT: DW_IDX_compile_unit: 0x00 +# CHECK-NEXT: DW_IDX_die_offset: 0x00000054 +# CHECK-NEXT: DW_IDX_parent: Entry @ [[ENTRY]] +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: Name 5 { +# CHECK-NEXT: Hash: 0x7C952063 +# CHECK-NEXT: String: {{.+}} "char" +# CHECK-NEXT: Entry @ {{.+}} { +# CHECK-NEXT: Abbrev: [[ABBREV3]] +# CHECK-NEXT: Tag: DW_TAG_base_type +# CHECK-NEXT: DW_IDX_compile_unit: 0x00 +# CHECK-NEXT: DW_IDX_die_offset: 0x00000075 +# CHECK-NEXT: DW_IDX_parent: +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } + +## clang++ -g2 -gpubnames -S -emit-llvm main.cpp -o main.ll +## clang++ -g2 -gpubnames -S -emit-llvm helper.cpp -o helper.ll +## llvm-link main.ll helper.ll -o combined.ll +## clang++ -g2 -gpubnames combined.ll -emit-llvm -S -o combined.opt.ll +## llc -dwarf-version=5 -filetype=asm -mtriple x86_64-unknown-linux combined.opt.ll -o combined.s +## main.cpp +## extern int foo(int); +## int main(int argc, char* argv[]) { +## int i = 0; +## [[clang::always_inline]] i = foo(argc); +## return i; +## } +## helper.cpp +## int foo(int i) { +## return i ++; +## } + + .text + .file "llvm-link" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 1 "/home" "main.cpp" md5 0x24fb0b4c3900e91fece1ac87ed73ff3b + .loc 1 2 0 # main.cpp:2: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, -16(%rbp) + movl %edi, -12(%rbp) + movq %rsi, -24(%rbp) +.Ltmp0: + .loc 1 3 7 prologue_end # main.cpp:3:7 + movl $0, -4(%rbp) + .loc 1 4 36 # main.cpp:4:36 + movl -12(%rbp), %eax + movl %eax, -8(%rbp) +.Ltmp1: + .file 2 "/home" "helper.cpp" md5 0x7d4429e24d8c74d7ee22c1889ad46d6b + .loc 2 2 12 # helper.cpp:2:12 + movl -8(%rbp), %eax + movl %eax, %ecx + addl $1, %ecx + movl %ecx, -8(%rbp) +.Ltmp2: + .loc 1 4 30 # main.cpp:4:30 + movl %eax, -4(%rbp) + .loc 1 5 10 # main.cpp:5:10 + movl -4(%rbp), %eax + .loc 1 5 3 epilogue_begin is_stmt 0 # main.cpp:5:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp3: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .globl _Z3fooi # -- Begin function _Z3fooi + .p2align 4, 0x90 + .type _Z3fooi,@function +_Z3fooi: # @_Z3fooi +.Lfunc_begin1: + .loc 2 1 0 is_stmt 1 # helper.cpp:1: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 %edi, -4(%rbp) +.Ltmp4: + .loc 2 2 12 prologue_end # helper.cpp:2:12 + movl -4(%rbp), %eax + movl %eax, %ecx + addl $1, %ecx + movl %ecx, -4(%rbp) + .loc 2 2 3 epilogue_begin is_stmt 0 # helper.cpp:2:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp5: +.Lfunc_end1: + .size _Z3fooi, .Lfunc_end1-_Z3fooi + .cfi_endproc + # -- End function + .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 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 16 # DW_FORM_ref_addr + .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 16 # DW_FORM_ref_addr + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # 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 5 # 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 16 # DW_FORM_ref_addr + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 29 # DW_TAG_inlined_subroutine + .byte 1 # DW_CHILDREN_yes + .byte 49 # DW_AT_abstract_origin + .byte 16 # DW_FORM_ref_addr + .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 7 # 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 16 # DW_FORM_ref_addr + .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 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 10 # 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 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .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 11 # 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 12 # 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 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 13 # 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 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:0x6d 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_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 2 # Abbrev [2] 0x23:0x47 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 8 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long .debug_info+174 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x32:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 116 + .byte 9 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long .debug_info+174 # DW_AT_type + .byte 4 # Abbrev [4] 0x3d:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 104 + .byte 10 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 106 # DW_AT_type + .byte 5 # Abbrev [5] 0x48:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 124 + .byte 7 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long .debug_info+174 # DW_AT_type + .byte 6 # Abbrev [6] 0x53:0x16 DW_TAG_inlined_subroutine + .long .debug_info+156 # DW_AT_abstract_origin + .byte 1 # DW_AT_low_pc + .long .Ltmp2-.Ltmp1 # DW_AT_high_pc + .byte 1 # DW_AT_call_file + .byte 4 # DW_AT_call_line + .byte 32 # DW_AT_call_column + .byte 7 # Abbrev [7] 0x60:0x8 DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .long .debug_info+165 # DW_AT_abstract_origin + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark + .byte 8 # Abbrev [8] 0x6a:0x5 DW_TAG_pointer_type + .long 111 # DW_AT_type + .byte 8 # Abbrev [8] 0x6f:0x5 DW_TAG_pointer_type + .long 116 # DW_AT_type + .byte 9 # Abbrev [9] 0x74: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: +.Lcu_begin1: + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .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:0x43 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 3 # 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 2 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 10 # Abbrev [10] 0x23:0x12 DW_TAG_subprogram + .byte 4 # DW_AT_linkage_name + .byte 5 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 53 # DW_AT_type + # DW_AT_external + # DW_AT_inline + .byte 11 # Abbrev [11] 0x2c:0x8 DW_TAG_formal_parameter + .byte 7 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 53 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 9 # Abbrev [9] 0x35:0x4 DW_TAG_base_type + .byte 6 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 12 # Abbrev [12] 0x39:0x15 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 86 + .long 35 # DW_AT_abstract_origin + .byte 13 # Abbrev [13] 0x45:0x8 DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 124 + .long 44 # DW_AT_abstract_origin + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .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 19.0.0git" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=24 +.Linfo_string2: + .asciz "/home/ayermolo/local/tasks/T182867349" # string offset=33 +.Linfo_string3: + .asciz "helper.cpp" # string offset=71 +.Linfo_string4: + .asciz "_Z3fooi" # string offset=82 +.Linfo_string5: + .asciz "foo" # string offset=90 +.Linfo_string6: + .asciz "int" # string offset=94 +.Linfo_string7: + .asciz "i" # string offset=98 +.Linfo_string8: + .asciz "main" # string offset=100 +.Linfo_string9: + .asciz "argc" # string offset=105 +.Linfo_string10: + .asciz "argv" # string offset=110 +.Linfo_string11: + .asciz "char" # string offset=115 + .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 .Ltmp1 + .quad .Lfunc_begin1 +.Ldebug_addr_end0: + .section .debug_names,"",@progbits + .long .Lnames_end0-.Lnames_start0 # Header: unit length +.Lnames_start0: + .short 5 # Header: version + .short 0 # Header: padding + .long 2 # Header: compilation unit count + .long 0 # Header: local type unit count + .long 0 # Header: foreign type unit count + .long 5 # Header: bucket count + .long 5 # Header: name count + .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size + .long 8 # Header: augmentation string size + .ascii "LLVM0700" # Header: augmentation string + .long .Lcu_begin0 # Compilation unit 0 + .long .Lcu_begin1 # Compilation unit 1 + .long 0 # Bucket 0 + .long 1 # Bucket 1 + .long 0 # Bucket 2 + .long 3 # Bucket 3 + .long 4 # Bucket 4 + .long 2090499946 # Hash in Bucket 1 + .long -1257882370 # Hash in Bucket 1 + .long 193495088 # Hash in Bucket 3 + .long 193491849 # Hash in Bucket 4 + .long 2090147939 # Hash in Bucket 4 + .long .Linfo_string8 # String in Bucket 1: main + .long .Linfo_string4 # String in Bucket 1: _Z3fooi + .long .Linfo_string6 # String in Bucket 3: int + .long .Linfo_string5 # String in Bucket 4: foo + .long .Linfo_string11 # String in Bucket 4: char + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 1 + .long .Lnames3-.Lnames_entries0 # Offset in Bucket 1 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 3 + .long .Lnames2-.Lnames_entries0 # Offset in Bucket 4 + .long .Lnames4-.Lnames_entries0 # Offset in Bucket 4 +.Lnames_abbrev_start0: + .byte 1 # Abbrev code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_IDX_compile_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 2 # Abbrev code + .byte 29 # DW_TAG_inlined_subroutine + .byte 1 # DW_IDX_compile_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 19 # DW_FORM_ref4 + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 3 # Abbrev code + .byte 36 # DW_TAG_base_type + .byte 1 # DW_IDX_compile_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames1: +.L3: + .byte 1 # Abbreviation code + .byte 0 # DW_IDX_compile_unit + .long 35 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: main +.Lnames3: +.L0: + .byte 1 # Abbreviation code + .byte 1 # DW_IDX_compile_unit + .long 57 # DW_IDX_die_offset +.L2: # DW_IDX_parent + .byte 2 # Abbreviation code + .byte 0 # DW_IDX_compile_unit + .long 83 # DW_IDX_die_offset + .long .L3-.Lnames_entries0 # DW_IDX_parent + .byte 0 # End of list: _Z3fooi +.Lnames0: +.L4: + .byte 3 # Abbreviation code + .byte 1 # DW_IDX_compile_unit + .long 53 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: int +.Lnames2: + .byte 1 # Abbreviation code + .byte 1 # DW_IDX_compile_unit + .long 57 # DW_IDX_die_offset + .byte 2 # DW_IDX_parent + # Abbreviation code + .byte 0 # DW_IDX_compile_unit + .long 83 # DW_IDX_die_offset + .long .L3-.Lnames_entries0 # DW_IDX_parent + .byte 0 # End of list: foo +.Lnames4: +.L1: + .byte 3 # Abbreviation code + .byte 0 # DW_IDX_compile_unit + .long 116 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: char + .p2align 2, 0x0 +.Lnames_end0: + .ident "clang version 19.0.0git" + .ident "clang version 19.0.0git" + .section ".note.GNU-stack","",@progbits + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/dwarf5-label-low-pc.s b/bolt/test/X86/dwarf5-label-low-pc.s index 890d9e024d1a0c1f1609d7cd33ea85076a10a2bf..1e3fc17ad516acb70410e60e4b860c0702f379ea 100644 --- a/bolt/test/X86/dwarf5-label-low-pc.s +++ b/bolt/test/X86/dwarf5-label-low-pc.s @@ -8,9 +8,10 @@ # 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: llvm-objdump -d %t.bolt >> %t.txt # RUN: cat %t.txt | FileCheck --check-prefix=POSTCHECK %s -# This test checks that we correctly handle DW_AT_low_pc [DW_FORM_addrx] that is part of DW_TAG_label. +## This test checks that we correctly handle DW_AT_low_pc [DW_FORM_addrx] that is part of DW_TAG_label. # PRECHECK: version = 0x0005 # PRECHECK: DW_TAG_label @@ -28,8 +29,8 @@ # POSTCHECK: Addrs: [ # POSTCHECK-NEXT: 0x # POSTCHECK-NEXT: 0x -# POSTCHECK-NEXT: 0x[[#%.16x,ADDR:]] -# POSTCHECK-NEXT: 0x[[#%.16x,ADDR2:]] +# POSTCHECK-NEXT: 0x[[ADDR:[1-9a-f]*]] +# POSTCHECK-NEXT: 0x[[ADDR2:[1-9a-f]*]] # POSTCHECK: version = 0x0005 # POSTCHECK: DW_TAG_label @@ -37,25 +38,28 @@ # POSTCHECK-NEXT: DW_AT_decl_file # POSTCHECK-NEXT: DW_AT_decl_line # POSTCHECK-NEXT:DW_AT_low_pc [DW_FORM_addrx] (indexed (00000002) -# POSTCHECK-SAME: 0x[[#ADDR]] +# POSTCHECK-SAME: 0x[[ADDR]] # POSTCHECK: DW_TAG_label # POSTCHECK-NEXT: DW_AT_name # POSTCHECK-NEXT: DW_AT_decl_file # POSTCHECK-NEXT: DW_AT_decl_line # POSTCHECK-NEXT:DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) -# POSTCHECK-SAME: 0x[[#ADDR2]] +# POSTCHECK-SAME: 0x[[ADDR2]] -# clang++ main.cpp -g -S -# int main() { -# int a = 4; -# if (a == 5) -# goto LABEL1; -# else -# goto LABEL2; -# LABEL1:a++; -# LABEL2:a--; -# return 0; -# } +# POSTCHECK: [[ADDR]]: 8b 45 f8 +# POSTCHECK: [[ADDR2]]: 8b 45 f8 + +## clang++ main.cpp -g -S +## int main() { +## int a = 4; +## if (a == 5) +## goto LABEL1; +## else +## goto LABEL2; +## LABEL1:a++; +## LABEL2:a--; +## return 0; +## } .text .file "main.cpp" diff --git a/bolt/test/X86/linux-alt-instruction.s b/bolt/test/X86/linux-alt-instruction.s index 5dcc6fe3ab0c81f178bd447be064529d79f11593..2cdf31519682a8e300a05efe46ccd4a867ddd133 100644 --- a/bolt/test/X86/linux-alt-instruction.s +++ b/bolt/test/X86/linux-alt-instruction.s @@ -6,8 +6,8 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ # RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie -# RUN: llvm-bolt %t.exe --print-normalized --keep-nops -o %t.out \ -# RUN: --alt-inst-feature-size=2 | FileCheck %s +# RUN: llvm-bolt %t.exe --print-normalized --alt-inst-feature-size=2 -o %t.out \ +# RUN: | FileCheck %s ## Older kernels used to have padlen field in alt_instr. Check compatibility. @@ -15,8 +15,8 @@ # RUN: %s -o %t.o # RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ # RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie -# RUN: llvm-bolt %t.exe --print-normalized --keep-nops --alt-inst-has-padlen \ -# RUN: -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --print-normalized --alt-inst-has-padlen -o %t.out \ +# RUN: | FileCheck %s ## Check with a larger size of "feature" field in alt_instr. @@ -24,13 +24,12 @@ # RUN: --defsym FEATURE_SIZE_4=1 %s -o %t.o # RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ # RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie -# RUN: llvm-bolt %t.exe --print-normalized --keep-nops \ -# RUN: --alt-inst-feature-size=4 -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --print-normalized --alt-inst-feature-size=4 -o %t.out \ +# RUN: | FileCheck %s ## Check that out-of-bounds read is handled properly. -# RUN: not llvm-bolt %t.exe --print-normalized --keep-nops \ -# RUN: --alt-inst-feature-size=2 -o %t.out +# RUN: not llvm-bolt %t.exe --print-normalized --alt-inst-feature-size=2 -o %t.out # CHECK: BOLT-INFO: Linux kernel binary detected # CHECK: BOLT-INFO: parsed 2 alternative instruction entries diff --git a/bolt/test/X86/linux-orc.s b/bolt/test/X86/linux-orc.s index 4da19989408e2458c156c6cc97e95147d1419326..5f2096278e92d6a10c04bb387b74d52833d2a540 100644 --- a/bolt/test/X86/linux-orc.s +++ b/bolt/test/X86/linux-orc.s @@ -27,7 +27,7 @@ ## Verify ORC bindings to instructions. # RUN: llvm-bolt %t.exe --print-normalized --dump-orc --print-orc -o %t.out \ -# RUN: --bolt-info=0 |& FileCheck %s +# RUN: --keep-nops=0 --bolt-info=0 |& FileCheck %s ## Verify ORC bindings after rewrite. @@ -37,7 +37,7 @@ ## Verify ORC binding after rewrite when some of the functions are skipped. -# RUN: llvm-bolt %t.exe -o %t.out --skip-funcs=bar --bolt-info=0 +# RUN: llvm-bolt %t.exe -o %t.out --skip-funcs=bar --bolt-info=0 --keep-nops=0 # RUN: llvm-bolt %t.out -o %t.out.1 --print-normalized --print-orc \ # RUN: |& FileCheck %s diff --git a/bolt/test/X86/linux-parainstructions.s b/bolt/test/X86/linux-parainstructions.s index 4bdfde5fb7f24bf505ae4537b988fa8321d6db20..07fca6bbedafaba54b44106519634d93712dad7e 100644 --- a/bolt/test/X86/linux-parainstructions.s +++ b/bolt/test/X86/linux-parainstructions.s @@ -8,7 +8,7 @@ ## Verify paravirtual bindings to instructions. -# RUN: llvm-bolt %t.exe --print-normalized -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --print-normalized -o %t.out --keep-nops=0 | FileCheck %s # CHECK: BOLT-INFO: Linux kernel binary detected # CHECK: BOLT-INFO: parsed 2 paravirtual patch sites diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index 40ac6918faf40786b1add8fb16e1c5933d76ca2e..b877ea06dc05cd78b5536155efb25afa4ae32906 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -233,7 +233,7 @@ public: if (!tooling::applyAllReplacements(Replacements.get(), Rewrite)) { llvm::errs() << "Can't apply replacements for file " << File << "\n"; } - AnyNotWritten &= Rewrite.overwriteChangedFiles(); + AnyNotWritten |= Rewrite.overwriteChangedFiles(); } if (AnyNotWritten) { diff --git a/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp index 16f43128d55e87ed43a0f16a227bc16a07297959..9b3b01eb02683324d16ee91050116332c9281a1f 100644 --- a/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp @@ -31,6 +31,10 @@ void IncDecInConditionsCheck::registerMatchers(MatchFinder *Finder) { anyOf(binaryOperator(anyOf(isComparisonOperator(), isLogicalOperator())), cxxOperatorCallExpr(isComparisonOperator()))); + auto IsInUnevaluatedContext = + expr(anyOf(hasAncestor(expr(matchers::hasUnevaluatedContext())), + hasAncestor(typeLoc()))); + Finder->addMatcher( expr( OperatorMatcher, unless(isExpansionInSystemHeader()), @@ -42,12 +46,14 @@ void IncDecInConditionsCheck::registerMatchers(MatchFinder *Finder) { cxxOperatorCallExpr( isPrePostOperator(), hasUnaryOperand(expr().bind("operand")))), + unless(IsInUnevaluatedContext), hasAncestor( expr(equalsBoundNode("parent"), hasDescendant( expr(unless(equalsBoundNode("operand")), matchers::isStatementIdenticalToBoundNode( - "operand")) + "operand"), + unless(IsInUnevaluatedContext)) .bind("second"))))) .bind("operator"))), this); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index a604e9276668aecfab23cd583b83fcb71682a958..2392ccaf65754f6c907aea8eefd3022104bcf888 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -139,6 +139,10 @@ Changes in existing checks ` check by detecting side effect from calling a method with non-const reference parameters. +- Improved :doc:`bugprone-inc-dec-in-conditions + ` check to ignore code + within unevaluated contexts, such as ``decltype``. + - Improved :doc:`bugprone-non-zero-enum-to-bool-conversion ` check by eliminating false positives resulting from direct usage of bitwise operators diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp index 82af039973c3bb76dab22c57bb0e0f7c2e703d6a..91de013138f0deea472742be633bec41e34417aa 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp @@ -68,3 +68,13 @@ bool doubleCheck(Container x) { // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: decrementing and referencing a variable in a complex condition can cause unintended side-effects due to C++'s order of evaluation, consider moving the modification outside of the condition to avoid misunderstandings [bugprone-inc-dec-in-conditions] // CHECK-MESSAGES: :[[@LINE-2]]:31: warning: incrementing and referencing a variable in a complex condition can cause unintended side-effects due to C++'s order of evaluation, consider moving the modification outside of the condition to avoid misunderstandings [bugprone-inc-dec-in-conditions] } + +namespace PR85838 { + void test() + { + auto foo = 0; + auto bar = 0; + if (++foo < static_cast(bar)) {} + if (static_cast(bar) < foo) {} + } +} diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 761dab8c28c1346014fb6d55a37a95a2adf80cf4..284b2af24ddaa0405398e8ea1826856e93401ba6 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -13,8 +13,16 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) set(CLANG_BUILT_STANDALONE TRUE) endif() +# Make sure that our source directory is on the current cmake module path so that +# we can include cmake files from this directory. +list(INSERT CMAKE_MODULE_PATH 0 + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" + "${LLVM_COMMON_CMAKE_UTILS}/Modules" + ) + # Must go below project(..) include(GNUInstallDirs) +include(GetDarwinLinkerVersion) if(CLANG_BUILT_STANDALONE) set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to") @@ -140,13 +148,6 @@ if(CLANG_BUILT_STANDALONE) endif() # LLVM_INCLUDE_TESTS endif() # standalone -# Make sure that our source directory is on the current cmake module path so that -# we can include cmake files from this directory. -list(INSERT CMAKE_MODULE_PATH 0 - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" - "${LLVM_COMMON_CMAKE_UTILS}/Modules" - ) - # This allows disabling clang's XML dependency even if LLVM finds libxml2. # By default, clang depends on libxml2 if LLVM does. option(CLANG_ENABLE_LIBXML2 "Whether libclang may depend on libxml2" @@ -346,20 +347,7 @@ endif () # Determine HOST_LINK_VERSION on Darwin. set(HOST_LINK_VERSION) if (APPLE AND NOT CMAKE_LINKER MATCHES ".*lld.*") - set(LD_V_OUTPUT) - execute_process( - COMMAND sh -c "${CMAKE_LINKER} -v 2>&1 | head -1" - RESULT_VARIABLE HAD_ERROR - OUTPUT_VARIABLE LD_V_OUTPUT - ) - if (HAD_ERROR) - message(FATAL_ERROR "${CMAKE_LINKER} failed with status ${HAD_ERROR}") - endif() - if ("${LD_V_OUTPUT}" MATCHES ".*ld64-([0-9.]+).*") - string(REGEX REPLACE ".*ld64-([0-9.]+).*" "\\1" HOST_LINK_VERSION ${LD_V_OUTPUT}) - elseif ("${LD_V_OUTPUT}" MATCHES "[^0-9]*([0-9.]+).*") - string(REGEX REPLACE "[^0-9]*([0-9.]+).*" "\\1" HOST_LINK_VERSION ${LD_V_OUTPUT}) - endif() + get_darwin_linker_version(HOST_LINK_VERSION) message(STATUS "Host linker version: ${HOST_LINK_VERSION}") endif() diff --git a/clang/cmake/caches/HLSL.cmake b/clang/cmake/caches/HLSL.cmake index 71f81e53f6bd351f18e8d23cbc1ec24ced9622ac..84850c86f12cd7ab92237452ce8b2bd8fdfb0dce 100644 --- a/clang/cmake/caches/HLSL.cmake +++ b/clang/cmake/caches/HLSL.cmake @@ -4,7 +4,7 @@ set(LLVM_TARGETS_TO_BUILD Native CACHE STRING "") # Include the DirectX target for DXIL code generation, eventually we'll include # SPIR-V here too. -set(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD DirectX CACHE STRING "") +set(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD "DirectX;SPIRV" CACHE STRING "") # HLSL support is currently limted to clang, eventually it will expand to # clang-tools-extra too. diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index be021dfc5c084cde660d1d6b4628dedbe8cf57f2..2ee36f24d7ce4b37c4bdf56ba318549b48696a80 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -955,6 +955,151 @@ the configuration (without a prefix: ``Auto``). } +.. _AlignConsecutiveTableGenBreakingDAGArgColons: + +**AlignConsecutiveTableGenBreakingDAGArgColons** (``AlignConsecutiveStyle``) :versionbadge:`clang-format 19` :ref:`¶ ` + Style of aligning consecutive TableGen DAGArg operator colons. + If enabled, align the colon inside DAGArg which have line break inside. + This works only when TableGenBreakInsideDAGArg is BreakElements or + BreakAll and the DAGArg is not excepted by + TableGenBreakingDAGArgOperators's effect. + + .. code-block:: c++ + + let dagarg = (ins + a :$src1, + aa :$src2, + aaa:$src3 + ) + + Nested configuration flags: + + Alignment options. + + They can also be read as a whole for compatibility. The choices are: + - None + - Consecutive + - AcrossEmptyLines + - AcrossComments + - AcrossEmptyLinesAndComments + + For example, to align across empty lines and not across comments, either + of these work. + + .. code-block:: c++ + + AlignConsecutiveTableGenBreakingDAGArgColons: AcrossEmptyLines + + AlignConsecutiveTableGenBreakingDAGArgColons: + Enabled: true + AcrossEmptyLines: true + AcrossComments: false + + * ``bool Enabled`` Whether aligning is enabled. + + .. code-block:: c++ + + #define SHORT_NAME 42 + #define LONGER_NAME 0x007f + #define EVEN_LONGER_NAME (2) + #define foo(x) (x * x) + #define bar(y, z) (y + z) + + int a = 1; + int somelongname = 2; + double c = 3; + + int aaaa : 1; + int b : 12; + int ccc : 8; + + int aaaa = 12; + float b = 23; + std::string ccc; + + * ``bool AcrossEmptyLines`` Whether to align across empty lines. + + .. code-block:: c++ + + true: + int a = 1; + int somelongname = 2; + double c = 3; + + int d = 3; + + false: + int a = 1; + int somelongname = 2; + double c = 3; + + int d = 3; + + * ``bool AcrossComments`` Whether to align across comments. + + .. code-block:: c++ + + true: + int d = 3; + /* A comment. */ + double e = 4; + + false: + int d = 3; + /* A comment. */ + double e = 4; + + * ``bool AlignCompound`` Only for ``AlignConsecutiveAssignments``. Whether compound assignments + like ``+=`` are aligned along with ``=``. + + .. code-block:: c++ + + true: + a &= 2; + bbb = 2; + + false: + a &= 2; + bbb = 2; + + * ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are + aligned. + + .. code-block:: c++ + + true: + unsigned i; + int &r; + int *p; + int (*f)(); + + false: + unsigned i; + int &r; + int *p; + int (*f)(); + + * ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment + operators are left-padded to the same length as long ones in order to + put all assignment operators to the right of the left hand side. + + .. code-block:: c++ + + true: + a >>= 2; + bbb = 2; + + a = 2; + bbb >>= 2; + + false: + a >>= 2; + bbb = 2; + + a = 2; + bbb >>= 2; + + .. _AlignConsecutiveTableGenCondOperatorColons: **AlignConsecutiveTableGenCondOperatorColons** (``AlignConsecutiveStyle``) :versionbadge:`clang-format 19` :ref:`¶ ` diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index fd12bb41be47a3e16f28e477b425b6b367e49173..7fbe2fec6ca06580363fbadd2536b691bcf33a56 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -57,6 +57,12 @@ ABI Changes in This Version inline member function that contains a static local variable with a dynamic initializer is declared with ``__declspec(dllimport)``. (#GH83616). +- Fixed Microsoft name mangling of lifetime extended temporary objects. This + change corrects missing back reference registrations that could result in + incorrect back reference indexes and suprising demangled name results. Since + MSVC uses a different mangling for these objects, compatibility is not affected. + (#GH85423). + AST Dumping Potentially Breaking Changes ---------------------------------------- @@ -437,6 +443,8 @@ Bug Fixes to C++ Support - Clang's __builtin_bit_cast will now produce a constant value for records with empty bases. See: (#GH82383) - Fix a crash when instantiating a lambda that captures ``this`` outside of its context. Fixes (#GH85343). +- Fix an issue where a namespace alias could be defined using a qualified name (all name components + following the first `::` were ignored). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -520,6 +528,7 @@ RISC-V Support ^^^^^^^^^^^^^^ - ``__attribute__((rvv_vector_bits(N)))`` is now supported for RVV vbool*_t types. +- Profile names in ``-march`` option are now supported. CUDA/HIP Language Changes ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -576,6 +585,7 @@ Static Analyzer - Fixed crashing on loops if the loop variable was declared in switch blocks but not under any case blocks if ``unroll-loops=true`` analyzer config is set. (#GH68819) +- Support C++23 static operator calls. (#GH84972) New features ^^^^^^^^^^^^ diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index fe2115149142723724feea43e0af6d285d9dd604..66da1c7b35f28b507d11ccfab4aa6ccad958edb1 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -340,6 +340,51 @@ cplusplus C++ Checkers. +.. _cplusplus-ArrayDelete: + +cplusplus.ArrayDelete (C++) +""""""""""""""""""""""""""" + +Reports destructions of arrays of polymorphic objects that are destructed as +their base class. If the dynamic type of the array is different from its static +type, calling `delete[]` is undefined. + +This checker corresponds to the SEI CERT rule `EXP51-CPP: Do not delete an array through a pointer of the incorrect type `_. + +.. code-block:: cpp + + class Base { + public: + virtual ~Base() {} + }; + class Derived : public Base {}; + + Base *create() { + Base *x = new Derived[10]; // note: Casting from 'Derived' to 'Base' here + return x; + } + + void foo() { + Base *x = create(); + delete[] x; // warn: Deleting an array of 'Derived' objects as their base class 'Base' is undefined + } + +**Limitations** + +The checker does not emit note tags when casting to and from reference types, +even though the pointer values are tracked across references. + +.. code-block:: cpp + + void foo() { + Derived *d = new Derived[10]; + Derived &dref = *d; + + Base &bref = static_cast(dref); // no note + Base *b = &bref; + delete[] b; // warn: Deleting an array of 'Derived' objects as their base class 'Base' is undefined + } + .. _cplusplus-InnerPointer: cplusplus.InnerPointer (C++) @@ -2139,30 +2184,6 @@ Either the comparison is useless or there is division by zero. alpha.cplusplus ^^^^^^^^^^^^^^^ -.. _alpha-cplusplus-ArrayDelete: - -alpha.cplusplus.ArrayDelete (C++) -""""""""""""""""""""""""""""""""" -Reports destructions of arrays of polymorphic objects that are destructed as their base class. -This checker corresponds to the CERT rule `EXP51-CPP: Do not delete an array through a pointer of the incorrect type `_. - -.. code-block:: cpp - - class Base { - virtual ~Base() {} - }; - class Derived : public Base {} - - Base *create() { - Base *x = new Derived[10]; // note: Casting from 'Derived' to 'Base' here - return x; - } - - void foo() { - Base *x = create(); - delete[] x; // warn: Deleting an array of 'Derived' objects as their base class 'Base' is undefined - } - .. _alpha-cplusplus-DeleteWithNonVirtualDtor: alpha.cplusplus.DeleteWithNonVirtualDtor (C++) diff --git a/clang/include/clang/Analysis/PathDiagnostic.h b/clang/include/clang/Analysis/PathDiagnostic.h index 90559e7efb06f05f341cc1f79798de561155f765..5907df022e449d5be5c74230e3f189c63ecbc481 100644 --- a/clang/include/clang/Analysis/PathDiagnostic.h +++ b/clang/include/clang/Analysis/PathDiagnostic.h @@ -780,6 +780,9 @@ class PathDiagnostic : public llvm::FoldingSetNode { PathDiagnosticLocation UniqueingLoc; const Decl *UniqueingDecl; + /// The top-level entry point from which this issue was discovered. + const Decl *AnalysisEntryPoint = nullptr; + /// Lines executed in the path. std::unique_ptr ExecutedLines; @@ -788,7 +791,7 @@ public: PathDiagnostic(StringRef CheckerName, const Decl *DeclWithIssue, StringRef bugtype, StringRef verboseDesc, StringRef shortDesc, StringRef category, PathDiagnosticLocation LocationToUnique, - const Decl *DeclToUnique, + const Decl *DeclToUnique, const Decl *AnalysisEntryPoint, std::unique_ptr ExecutedLines); ~PathDiagnostic(); @@ -852,6 +855,9 @@ public: return *ExecutedLines; } + /// Get the top-level entry point from which this issue was discovered. + const Decl *getAnalysisEntryPoint() const { return AnalysisEntryPoint; } + /// Return the semantic context where an issue occurred. If the /// issue occurs along a path, this represents the "central" area /// where the bug manifests. diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def index 61ec8b79bf054daa03e02fddca3c4edb2da75088..4153b316c22b1d25103a009a976db6fcc0e6b3fa 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -432,13 +432,15 @@ TARGET_BUILTIN(__builtin_amdgcn_s_wakeup_barrier, "vi", "n", "gfx12-insts") TARGET_BUILTIN(__builtin_amdgcn_s_barrier_leave, "b", "n", "gfx12-insts") TARGET_BUILTIN(__builtin_amdgcn_s_get_barrier_state, "Uii", "n", "gfx12-insts") -TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v2i32, "V2iV2i*1", "nc", "gfx12-insts,wavefrontsize32") -TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v8i16, "V8sV8s*1", "nc", "gfx12-insts,wavefrontsize32") -TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v8f16, "V8hV8h*1", "nc", "gfx12-insts,wavefrontsize32") - -TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_i32, "ii*1", "nc", "gfx12-insts,wavefrontsize64") -TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v4i16, "V4sV4s*1", "nc", "gfx12-insts,wavefrontsize64") -TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v4f16, "V4hV4h*1", "nc", "gfx12-insts,wavefrontsize64") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b64_v2i32, "V2iV2i*1", "nc", "gfx12-insts,wavefrontsize32") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v8i16, "V8sV8s*1", "nc", "gfx12-insts,wavefrontsize32") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v8f16, "V8hV8h*1", "nc", "gfx12-insts,wavefrontsize32") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v8bf16, "V8yV8y*1", "nc", "gfx12-insts,wavefrontsize32") + +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b64_i32, "ii*1", "nc", "gfx12-insts,wavefrontsize64") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v4i16, "V4sV4s*1", "nc", "gfx12-insts,wavefrontsize64") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v4f16, "V4hV4h*1", "nc", "gfx12-insts,wavefrontsize64") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v4bf16, "V4yV4y*1", "nc", "gfx12-insts,wavefrontsize64") //===----------------------------------------------------------------------===// // WMMA builtins. diff --git a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td index f99a5fca64cb4659d29ead47dc1b1e5658f30b30..27df731fa28627b32359a4c6a51ed23d23b02f5e 100644 --- a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td +++ b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td @@ -15,6 +15,9 @@ let CategoryName = "Command line" in { def err_cannot_write_file : Error<"cannot write file '%0': %1">; def err_no_install_name : Error<"no install name specified: add -install_name ">; def err_no_output_file: Error<"no output file specified">; +def err_no_such_header_file : Error<"no such %select{public|private|project}1 header file: '%0'">; +def warn_no_such_excluded_header_file : Warning<"no such excluded %select{public|private}0 header file: '%1'">, InGroup; +def warn_glob_did_not_match: Warning<"glob '%0' did not match any header file">, InGroup; } // end of command line category. let CategoryName = "Verification" in { @@ -26,6 +29,7 @@ def warn_library_hidden_symbol : Warning<"declaration has external linkage, but def warn_header_hidden_symbol : Warning<"symbol exported in dynamic library, but marked hidden in declaration '%0'">, InGroup; def err_header_hidden_symbol : Error<"symbol exported in dynamic library, but marked hidden in declaration '%0'">; def err_header_symbol_missing : Error<"no declaration found for exported symbol '%0' in dynamic library">; +def warn_header_symbol_missing : Warning<"no declaration was found for exported symbol '%0' in dynamic library">, InGroup; def warn_header_availability_mismatch : Warning<"declaration '%0' is marked %select{available|unavailable}1," " but symbol is %select{not |}2exported in dynamic library">, InGroup; def err_header_availability_mismatch : Error<"declaration '%0' is marked %select{available|unavailable}1," diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 48de5e2ef5f4af2c121e1a3bbfda1aac0cc28227..46a44418a3153bc75df0ac7327bab65ac1528bc3 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -268,6 +268,8 @@ def err_expected_semi_after_namespace_name : Error< "expected ';' after namespace name">; def err_unexpected_namespace_attributes_alias : Error< "attributes cannot be specified on namespace alias">; +def err_unexpected_qualified_namespace_alias : Error< + "namespace alias must be a single identifier">; def err_unexpected_nested_namespace_attribute : Error< "attributes cannot be specified on a nested namespace definition">; def err_inline_namespace_alias : Error<"namespace alias cannot be inline">; diff --git a/clang/include/clang/Basic/LangStandard.h b/clang/include/clang/Basic/LangStandard.h index 199e24c67316030d167f4c2b2b4e02fb44f897da..8e25afc833661c42ab94f1d3426f25455929215c 100644 --- a/clang/include/clang/Basic/LangStandard.h +++ b/clang/include/clang/Basic/LangStandard.h @@ -26,8 +26,9 @@ enum class Language : uint8_t { /// Assembly: we accept this only so that we can preprocess it. Asm, - /// LLVM IR: we accept this so that we can run the optimizer on it, - /// and compile it to assembly or object code. + /// LLVM IR & CIR: we accept these so that we can run the optimizer on them, + /// and compile them to assembly or object code (or LLVM for CIR). + CIR, LLVM_IR, ///@{ Languages that the frontend can parse and compile. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 4a954258ce40b6a7050c66a478f7bcc9d866b9cf..b0d90c776b58a9620e3b3de416623805964c7c81 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -6688,6 +6688,9 @@ def analyzer_opt_analyze_headers : Flag<["-"], "analyzer-opt-analyze-headers">, def analyzer_display_progress : Flag<["-"], "analyzer-display-progress">, HelpText<"Emit verbose output about the analyzer's progress">, MarshallingInfoFlag>; +def analyzer_note_analysis_entry_points : Flag<["-"], "analyzer-note-analysis-entry-points">, + HelpText<"Add a note for each bug report to denote their analysis entry points">, + MarshallingInfoFlag>; def analyze_function : Separate<["-"], "analyze-function">, HelpText<"Run analysis on specific function (for C++ include parameters in name)">, MarshallingInfoString>; diff --git a/clang/include/clang/Driver/Types.def b/clang/include/clang/Driver/Types.def index f72c27e1ee701931484792524a85f74050087e98..0e0cae5fb7068dec6561eb376fa37cd5db83316e 100644 --- a/clang/include/clang/Driver/Types.def +++ b/clang/include/clang/Driver/Types.def @@ -90,6 +90,7 @@ TYPE("ir", LLVM_BC, INVALID, "bc", phases TYPE("lto-ir", LTO_IR, INVALID, "s", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("lto-bc", LTO_BC, INVALID, "o", phases::Compile, phases::Backend, phases::Assemble, phases::Link) +TYPE("cir", CIR, INVALID, "cir", phases::Compile, phases::Backend, phases::Assemble, phases::Link) // Misc. TYPE("ast", AST, INVALID, "ast", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("ifs", IFS, INVALID, "ifs", phases::IfsMerge) diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 7ad2579bf7773b76643efef6b960dba66184c9fc..0720c8283cd75c4b778f010df50569530958ee15 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -414,6 +414,21 @@ struct FormatStyle { /// \version 17 ShortCaseStatementsAlignmentStyle AlignConsecutiveShortCaseStatements; + /// Style of aligning consecutive TableGen DAGArg operator colons. + /// If enabled, align the colon inside DAGArg which have line break inside. + /// This works only when TableGenBreakInsideDAGArg is BreakElements or + /// BreakAll and the DAGArg is not excepted by + /// TableGenBreakingDAGArgOperators's effect. + /// \code + /// let dagarg = (ins + /// a :$src1, + /// aa :$src2, + /// aaa:$src3 + /// ) + /// \endcode + /// \version 19 + AlignConsecutiveStyle AlignConsecutiveTableGenBreakingDAGArgColons; + /// Style of aligning consecutive TableGen cond operator colons. /// Align the colons of cases inside !cond operators. /// \code @@ -4879,6 +4894,8 @@ struct FormatStyle { AlignConsecutiveMacros == R.AlignConsecutiveMacros && AlignConsecutiveShortCaseStatements == R.AlignConsecutiveShortCaseStatements && + AlignConsecutiveTableGenBreakingDAGArgColons == + R.AlignConsecutiveTableGenBreakingDAGArgColons && AlignConsecutiveTableGenCondOperatorColons == R.AlignConsecutiveTableGenCondOperatorColons && AlignConsecutiveTableGenDefinitionColons == diff --git a/clang/include/clang/InstallAPI/DylibVerifier.h b/clang/include/clang/InstallAPI/DylibVerifier.h index bbfa8711313e478e0a74fcd8f72039e2e00a5297..49de24763f1f938d88ba6e2f2ab41d593fc34a38 100644 --- a/clang/include/clang/InstallAPI/DylibVerifier.h +++ b/clang/include/clang/InstallAPI/DylibVerifier.h @@ -28,7 +28,7 @@ enum class VerificationMode { /// lifetime of InstallAPI. /// As declarations are collected during AST traversal, they are /// compared as symbols against what is available in the binary dylib. -class DylibVerifier { +class DylibVerifier : llvm::MachO::RecordVisitor { private: struct SymbolContext; @@ -72,6 +72,9 @@ public: Result verify(ObjCIVarRecord *R, const FrontendAttrs *FA, const StringRef SuperClass); + // Scan through dylib slices and report any remaining missing exports. + Result verifyRemainingSymbols(); + /// Initialize target for verification. void setTarget(const Target &T); @@ -128,6 +131,14 @@ private: /// Find matching dylib slice for target triple that is being parsed. void assignSlice(const Target &T); + /// Shared implementation for verifying exported symbols in dylib. + void visitSymbolInDylib(const Record &R, SymbolContext &SymCtx); + + void visitGlobal(const GlobalRecord &R) override; + void visitObjCInterface(const ObjCInterfaceRecord &R) override; + void visitObjCCategory(const ObjCCategoryRecord &R) override; + void visitObjCIVar(const ObjCIVarRecord &R, const StringRef Super); + /// Gather annotations for symbol for error reporting. std::string getAnnotatedName(const Record *R, SymbolContext &SymCtx, bool ValidSourceLoc = true); diff --git a/clang/include/clang/InstallAPI/HeaderFile.h b/clang/include/clang/InstallAPI/HeaderFile.h index 70e83bbb3e76f6bb91030fb6edca023aa5450e36..235b4da3add840e8eabe8064f7ce0253aa05e2ab 100644 --- a/clang/include/clang/InstallAPI/HeaderFile.h +++ b/clang/include/clang/InstallAPI/HeaderFile.h @@ -13,7 +13,9 @@ #ifndef LLVM_CLANG_INSTALLAPI_HEADERFILE_H #define LLVM_CLANG_INSTALLAPI_HEADERFILE_H +#include "clang/Basic/FileManager.h" #include "clang/Basic/LangStandard.h" +#include "clang/InstallAPI/MachO.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Regex.h" @@ -56,6 +58,10 @@ class HeaderFile { std::string IncludeName; /// Supported language mode for header. std::optional Language; + /// Exclude header file from processing. + bool Excluded{false}; + /// Add header file to processing. + bool Extra{false}; public: HeaderFile() = delete; @@ -71,17 +77,48 @@ public: StringRef getIncludeName() const { return IncludeName; } StringRef getPath() const { return FullPath; } + void setExtra(bool V = true) { Extra = V; } + void setExcluded(bool V = true) { Excluded = V; } + bool isExtra() const { return Extra; } + bool isExcluded() const { return Excluded; } + bool useIncludeName() const { return Type != HeaderType::Project && !IncludeName.empty(); } bool operator==(const HeaderFile &Other) const { - return std::tie(Type, FullPath, IncludeName, Language) == + return std::tie(Type, FullPath, IncludeName, Language, Excluded, Extra) == std::tie(Other.Type, Other.FullPath, Other.IncludeName, - Other.Language); + Other.Language, Other.Excluded, Other.Extra); } }; +/// Glob that represents a pattern of header files to retreive. +class HeaderGlob { +private: + std::string GlobString; + llvm::Regex Rule; + HeaderType Type; + bool FoundMatch{false}; + +public: + HeaderGlob(StringRef GlobString, llvm::Regex &&, HeaderType Type); + + /// Create a header glob from string for the header access level. + static llvm::Expected> + create(StringRef GlobString, HeaderType Type); + + /// Query if provided header matches glob. + bool match(const HeaderFile &Header); + + /// Query if a header was matched in the glob, used primarily for error + /// reporting. + bool didMatch() { return FoundMatch; } + + /// Provide back input glob string. + StringRef str() { return GlobString; } +}; + /// Assemble expected way header will be included by clients. /// As in what maps inside the brackets of `#include ` /// For example, @@ -93,6 +130,19 @@ public: std::optional createIncludeHeaderName(const StringRef FullPath); using HeaderSeq = std::vector; +/// Determine if Path is a header file. +/// It does not touch the file system. +/// +/// \param Path File path to file. +bool isHeaderFile(StringRef Path); + +/// Given input directory, collect all header files. +/// +/// \param FM FileManager for finding input files. +/// \param Directory Path to directory file. +llvm::Expected enumerateFiles(clang::FileManager &FM, + StringRef Directory); + } // namespace clang::installapi #endif // LLVM_CLANG_INSTALLAPI_HEADERFILE_H diff --git a/clang/include/clang/InstallAPI/MachO.h b/clang/include/clang/InstallAPI/MachO.h index f0dea8bbd24ccd6ac34cc7b43fa128c696838e1c..4961c596fd68ae2fb41d672b831140f9afc505da 100644 --- a/clang/include/clang/InstallAPI/MachO.h +++ b/clang/include/clang/InstallAPI/MachO.h @@ -40,6 +40,7 @@ using SymbolSet = llvm::MachO::SymbolSet; using SimpleSymbol = llvm::MachO::SimpleSymbol; using FileType = llvm::MachO::FileType; using PackedVersion = llvm::MachO::PackedVersion; +using PathSeq = llvm::MachO::PathSeq; using Target = llvm::MachO::Target; using TargetList = llvm::MachO::TargetList; diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 1dcba1ef967980b7aa6297316b78912b3dbdb21d..970e0245417b5198b03b32f5ba4ee20ffe218128 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -30,6 +30,7 @@ namespace llvm { namespace orc { class LLJIT; +class LLJITBuilder; class ThreadSafeContext; } // namespace orc } // namespace llvm @@ -127,6 +128,13 @@ protected: // custom runtime. virtual std::unique_ptr FindRuntimeInterface(); + // Lazily construct thev ORCv2 JITBuilder. This called when the internal + // IncrementalExecutor is created. The default implementation populates an + // in-process JIT with debugging support. Override this to configure the JIT + // engine used for execution. + virtual llvm::Expected> + CreateJITBuilder(CompilerInstance &CI); + public: virtual ~Interpreter(); diff --git a/clang/include/clang/Interpreter/Value.h b/clang/include/clang/Interpreter/Value.h index c380cd91550defa524d87e5b074d9e0a130760eb..d70e8f8719026b9dfc17c573451a3c8fc9c9545d 100644 --- a/clang/include/clang/Interpreter/Value.h +++ b/clang/include/clang/Interpreter/Value.h @@ -76,6 +76,7 @@ class QualType; X(bool, Bool) \ X(char, Char_S) \ X(signed char, SChar) \ + X(unsigned char, Char_U) \ X(unsigned char, UChar) \ X(short, Short) \ X(unsigned short, UShort) \ diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 686e5e99f4a62c4a2649ea40849998968aa3e92b..bf46766d44b39126026c13b72646393f922ad794 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -622,6 +622,11 @@ def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">, let ParentPackage = Cplusplus in { +def ArrayDeleteChecker : Checker<"ArrayDelete">, + HelpText<"Reports destructions of arrays of polymorphic objects that are " + "destructed as their base class.">, + Documentation; + def InnerPointerChecker : Checker<"InnerPointer">, HelpText<"Check for inner pointers of C++ containers used after " "re/deallocation">, @@ -777,11 +782,6 @@ def ContainerModeling : Checker<"ContainerModeling">, Documentation, Hidden; -def CXXArrayDeleteChecker : Checker<"ArrayDelete">, - HelpText<"Reports destructions of arrays of polymorphic objects that are " - "destructed as their base class.">, - Documentation; - def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">, HelpText<"Reports destructions of polymorphic objects with a non-virtual " "destructor in their base class">, diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 276d11e80a5b21c78acd293650fadeddcf4bd1c3..3a3c1a13d67dd554bc39684ceeb8b6898073c5c5 100644 --- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -227,6 +227,7 @@ public: unsigned ShouldEmitErrorsOnInvalidConfigValue : 1; unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; + unsigned AnalyzerNoteAnalysisEntryPoints : 1; unsigned eagerlyAssumeBinOpBifurcation : 1; @@ -291,10 +292,10 @@ public: ShowCheckerOptionDeveloperList(false), ShowEnabledCheckerList(false), ShowConfigOptionsList(false), ShouldEmitErrorsOnInvalidConfigValue(false), AnalyzeAll(false), - AnalyzerDisplayProgress(false), eagerlyAssumeBinOpBifurcation(false), - TrimGraph(false), visualizeExplodedGraphWithGraphViz(false), - UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false), - AnalyzerWerror(false) {} + AnalyzerDisplayProgress(false), AnalyzerNoteAnalysisEntryPoints(false), + eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), + visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false), + PrintStats(false), NoRetryExhausted(false), AnalyzerWerror(false) {} /// Interprets an option's string value as a boolean. The "true" string is /// interpreted as true and the "false" string is interpreted as false. diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index e762f7548e0b54186883f140bcc793378913a67b..ead96ce6891c39a261fc47fe73b0753611d5eaaa 100644 --- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -586,6 +586,9 @@ class BugReporter { private: BugReporterData& D; + /// The top-level entry point for the issue to be reported. + const Decl *AnalysisEntryPoint = nullptr; + /// Generate and flush the diagnostics for the given bug report. void FlushReport(BugReportEquivClass& EQ); @@ -623,6 +626,14 @@ public: Preprocessor &getPreprocessor() { return D.getPreprocessor(); } + /// Get the top-level entry point for the issue to be reported. + const Decl *getAnalysisEntryPoint() const { return AnalysisEntryPoint; } + + void setAnalysisEntryPoint(const Decl *EntryPoint) { + assert(EntryPoint); + AnalysisEntryPoint = EntryPoint; + } + /// Add the given report to the set of reports tracked by BugReporter. /// /// The reports are usually generated by the checkers. Further, they are @@ -713,6 +724,7 @@ public: virtual ~BugReporterContext() = default; PathSensitiveBugReporter& getBugReporter() { return BR; } + const PathSensitiveBugReporter &getBugReporter() const { return BR; } ProgramStateManager& getStateManager() const { return BR.getStateManager(); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h index 3432d2648633c25a575e93087c766688bcd6ede6..b4e1636130ca7c2d10586749bff69519e8363ed1 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h @@ -41,12 +41,8 @@ public: /// - We also accept calls where the number of arguments or parameters is /// greater than the specified value. /// For the exact heuristics, see CheckerContext::isCLibraryFunction(). - /// Note that functions whose declaration context is not a TU (e.g. - /// methods, functions in namespaces) are not accepted as C library - /// functions. - /// FIXME: If I understand it correctly, this discards calls where C++ code - /// refers a C library function through the namespace `std::` via headers - /// like . + /// (This mode only matches functions that are declared either directly + /// within a TU or in the namespace `std`.) CLibrary, /// Matches "simple" functions that are not methods. (Static methods are diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index 0d36587484bf9c30c567ba242ab0df647ebc020d..549c864dc91ef2f74984122155f62c27152afe86 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -59,6 +59,7 @@ namespace ento { enum CallEventKind { CE_Function, + CE_CXXStaticOperator, CE_CXXMember, CE_CXXMemberOperator, CE_CXXDestructor, @@ -709,6 +710,77 @@ public: } }; +/// Represents a static C++ operator call. +/// +/// "A" in this example. +/// However, "B" and "C" are represented by SimpleFunctionCall. +/// \code +/// struct S { +/// int pad; +/// static void operator()(int x, int y); +/// }; +/// S s{10}; +/// void (*fptr)(int, int) = &S::operator(); +/// +/// s(1, 2); // A +/// S::operator()(1, 2); // B +/// fptr(1, 2); // C +/// \endcode +class CXXStaticOperatorCall : public SimpleFunctionCall { + friend class CallEventManager; + +protected: + CXXStaticOperatorCall(const CXXOperatorCallExpr *CE, ProgramStateRef St, + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : SimpleFunctionCall(CE, St, LCtx, ElemRef) {} + CXXStaticOperatorCall(const CXXStaticOperatorCall &Other) = default; + + void cloneTo(void *Dest) const override { + new (Dest) CXXStaticOperatorCall(*this); + } + +public: + const CXXOperatorCallExpr *getOriginExpr() const override { + return cast(SimpleFunctionCall::getOriginExpr()); + } + + unsigned getNumArgs() const override { + // Ignore the object parameter that is not used for static member functions. + assert(getOriginExpr()->getNumArgs() > 0); + return getOriginExpr()->getNumArgs() - 1; + } + + const Expr *getArgExpr(unsigned Index) const override { + // Ignore the object parameter that is not used for static member functions. + return getOriginExpr()->getArg(Index + 1); + } + + std::optional + getAdjustedParameterIndex(unsigned ASTArgumentIndex) const override { + // Ignore the object parameter that is not used for static member functions. + if (ASTArgumentIndex == 0) + return std::nullopt; + return ASTArgumentIndex - 1; + } + + unsigned getASTArgumentIndex(unsigned CallArgumentIndex) const override { + // Account for the object parameter for the static member function. + return CallArgumentIndex + 1; + } + + OverloadedOperatorKind getOverloadedOperator() const { + return getOriginExpr()->getOperator(); + } + + Kind getKind() const override { return CE_CXXStaticOperator; } + StringRef getKindAsString() const override { return "CXXStaticOperatorCall"; } + + static bool classof(const CallEvent *CA) { + return CA->getKind() == CE_CXXStaticOperator; + } +}; + /// Represents a non-static C++ member function call. /// /// Example: \c obj.fun() diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h index 60421e5437d82f7d35e2b3da4473098735d2c7dc..d053a97189123afbbb9da502e1397b83f19f9763 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h @@ -15,7 +15,6 @@ #include "ProgramState_Fwd.h" #include "SVals.h" - #include "clang/AST/OperationKinds.h" #include "clang/AST/Stmt.h" #include "clang/Basic/OperatorKinds.h" @@ -113,8 +112,7 @@ public: OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK, bool IsBinary); -std::optional getPointeeDefVal(SVal PtrSVal, - ProgramStateRef State); +std::optional getPointeeVal(SVal PtrSVal, ProgramStateRef State); } // namespace ento diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 859c1497d7e6db8f0f6bd6cfda62025ecc69cc36..e38a3bb56ece26f6b0ea326dcc364b5c79415f97 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -187,6 +187,8 @@ public: /// Returns true if there is still simulation state on the worklist. bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) { + assert(L->inTopFrame()); + BR.setAnalysisEntryPoint(L->getDecl()); return Engine.ExecuteWorkList(L, Steps, nullptr); } diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h index 846fdc7253977f99f03d0359b909d1f6a99b0938..9a522a3e2fe252082e1b2ee5b839c3d1d519cb63 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -242,6 +242,8 @@ class EntryRef { /// The underlying cached entry. const CachedFileSystemEntry &Entry; + friend class DependencyScanningWorkerFilesystem; + public: EntryRef(StringRef Name, const CachedFileSystemEntry &Entry) : Filename(Name), Entry(Entry) {} @@ -300,14 +302,15 @@ public: /// /// Attempts to use the local and shared caches first, then falls back to /// using the underlying filesystem. - llvm::ErrorOr - getOrCreateFileSystemEntry(StringRef Filename, - bool DisableDirectivesScanning = false); + llvm::ErrorOr getOrCreateFileSystemEntry(StringRef Filename); -private: - /// Check whether the file should be scanned for preprocessor directives. - bool shouldScanForDirectives(StringRef Filename); + /// Ensure the directive tokens are populated for this file entry. + /// + /// Returns true if the directive tokens are populated for this file entry, + /// false if not (i.e. this entry is not a file or its scan fails). + bool ensureDirectiveTokensArePopulated(EntryRef Entry); +private: /// For a filename that's not yet associated with any entry in the caches, /// uses the underlying filesystem to either look up the entry based in the /// shared cache indexed by unique ID, or creates new entry from scratch. @@ -317,11 +320,6 @@ private: computeAndStoreResult(StringRef OriginalFilename, StringRef FilenameForLookup); - /// Scan for preprocessor directives for the given entry if necessary and - /// returns a wrapper object with reference semantics. - EntryRef scanForDirectivesIfNecessary(const CachedFileSystemEntry &Entry, - StringRef Filename, bool Disable); - /// Represents a filesystem entry that has been stat-ed (and potentially read) /// and that's about to be inserted into the cache as `CachedFileSystemEntry`. struct TentativeEntry { diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index aa26bb7ed46f482cfa4b7e02dee65c0f69a303b0..cf9c2093a8f6a1eb6a336fb5f5928abc53451a20 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -3911,7 +3911,8 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary( msvc_hashing_ostream MHO(Out); MicrosoftCXXNameMangler Mangler(*this, MHO); - Mangler.getStream() << "?$RT" << ManglingNumber << '@'; + Mangler.getStream() << "?"; + Mangler.mangleSourceName("$RT" + llvm::utostr(ManglingNumber)); Mangler.mangle(VD, ""); } diff --git a/clang/lib/Analysis/FlowSensitive/AdornedCFG.cpp b/clang/lib/Analysis/FlowSensitive/AdornedCFG.cpp index daa73bed1bd9f5cefc81186d40cfec73b7d1bb1b..255543021a998c9dcb1801b9821b0ae37bd1bf14 100644 --- a/clang/lib/Analysis/FlowSensitive/AdornedCFG.cpp +++ b/clang/lib/Analysis/FlowSensitive/AdornedCFG.cpp @@ -144,7 +144,7 @@ llvm::Expected AdornedCFG::build(const Decl &D, Stmt &S, // The shape of certain elements of the AST can vary depending on the // language. We currently only support C++. - if (!C.getLangOpts().CPlusPlus) + if (!C.getLangOpts().CPlusPlus || C.getLangOpts().ObjC) return llvm::createStringError( std::make_error_code(std::errc::invalid_argument), "Can only analyze C++"); diff --git a/clang/lib/Analysis/PathDiagnostic.cpp b/clang/lib/Analysis/PathDiagnostic.cpp index 79f337a91ec8fafd581e89d1205e58ad3611e3ac..35472e705cfd8d55ac227733a957b58f33abb69f 100644 --- a/clang/lib/Analysis/PathDiagnostic.cpp +++ b/clang/lib/Analysis/PathDiagnostic.cpp @@ -115,14 +115,17 @@ PathDiagnostic::PathDiagnostic( StringRef CheckerName, const Decl *declWithIssue, StringRef bugtype, StringRef verboseDesc, StringRef shortDesc, StringRef category, PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique, + const Decl *AnalysisEntryPoint, std::unique_ptr ExecutedLines) : CheckerName(CheckerName), DeclWithIssue(declWithIssue), BugType(StripTrailingDots(bugtype)), VerboseDesc(StripTrailingDots(verboseDesc)), ShortDesc(StripTrailingDots(shortDesc)), Category(StripTrailingDots(category)), UniqueingLoc(LocationToUnique), - UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)), - path(pathImpl) {} + UniqueingDecl(DeclToUnique), AnalysisEntryPoint(AnalysisEntryPoint), + ExecutedLines(std::move(ExecutedLines)), path(pathImpl) { + assert(AnalysisEntryPoint); +} void PathDiagnosticConsumer::anchor() {} diff --git a/clang/lib/Basic/LangStandards.cpp b/clang/lib/Basic/LangStandards.cpp index cb2c07723499827ca256a16e44c042c34cfe4bff..c8c9292abcb22b6cde2f78c9b88151460aa1041b 100644 --- a/clang/lib/Basic/LangStandards.cpp +++ b/clang/lib/Basic/LangStandards.cpp @@ -21,6 +21,8 @@ StringRef clang::languageToString(Language L) { return "Asm"; case Language::LLVM_IR: return "LLVM IR"; + case Language::CIR: + return "ClangIR"; case Language::C: return "C"; case Language::CXX: @@ -92,6 +94,7 @@ LangStandard::Kind clang::getDefaultLanguageStandard(clang::Language Lang, switch (Lang) { case Language::Unknown: case Language::LLVM_IR: + case Language::CIR: llvm_unreachable("Invalid input kind!"); case Language::OpenCL: return LangStandard::lang_opencl12; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index e14e890882821853378fd7e814bb3bdb1093ecc2..8f4817258e3b1877d318ed363c9800ccf4c5c6af 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18066,15 +18066,22 @@ llvm::Value *CodeGenFunction::EmitScalarOrConstFoldImmArg(unsigned ICEArguments, return Arg; } -Intrinsic::ID getDotProductIntrinsic(QualType QT) { +Intrinsic::ID getDotProductIntrinsic(QualType QT, int elementCount) { + if (QT->hasFloatingRepresentation()) { + switch (elementCount) { + case 2: + return Intrinsic::dx_dot2; + case 3: + return Intrinsic::dx_dot3; + case 4: + return Intrinsic::dx_dot4; + } + } if (QT->hasSignedIntegerRepresentation()) return Intrinsic::dx_sdot; - if (QT->hasUnsignedIntegerRepresentation()) - return Intrinsic::dx_udot; - assert(QT->hasFloatingRepresentation()); - return Intrinsic::dx_dot; - ; + assert(QT->hasUnsignedIntegerRepresentation()); + return Intrinsic::dx_udot; } Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, @@ -18128,8 +18135,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, assert(T0->getScalarType() == T1->getScalarType() && "Dot product of vectors need the same element types."); - [[maybe_unused]] auto *VecTy0 = - E->getArg(0)->getType()->getAs(); + auto *VecTy0 = E->getArg(0)->getType()->getAs(); [[maybe_unused]] auto *VecTy1 = E->getArg(1)->getType()->getAs(); // A HLSLVectorTruncation should have happend @@ -18138,7 +18144,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return Builder.CreateIntrinsic( /*ReturnType=*/T0->getScalarType(), - getDotProductIntrinsic(E->getArg(0)->getType()), + getDotProductIntrinsic(E->getArg(0)->getType(), + VecTy0->getNumElements()), ArrayRef{Op0, Op1}, nullptr, "dx.dot"); } break; case Builtin::BI__builtin_hlsl_lerp: { @@ -18531,35 +18538,45 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, llvm::Function *F = CGM.getIntrinsic(IID, {ArgTy}); return Builder.CreateCall(F, {Addr, Val, ZeroI32, ZeroI32, ZeroI1}); } - case AMDGPU::BI__builtin_amdgcn_global_load_tr_i32: - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v2i32: - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4f16: - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4i16: - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8f16: - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8i16: { + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_i32: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_v2i32: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4bf16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4f16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4i16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8bf16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8f16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8i16: { llvm::Type *ArgTy; switch (BuiltinID) { - case AMDGPU::BI__builtin_amdgcn_global_load_tr_i32: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_i32: ArgTy = llvm::Type::getInt32Ty(getLLVMContext()); break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v2i32: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_v2i32: ArgTy = llvm::FixedVectorType::get( llvm::Type::getInt32Ty(getLLVMContext()), 2); break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4f16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4bf16: + ArgTy = llvm::FixedVectorType::get( + llvm::Type::getBFloatTy(getLLVMContext()), 4); + break; + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4f16: ArgTy = llvm::FixedVectorType::get( llvm::Type::getHalfTy(getLLVMContext()), 4); break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4i16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4i16: ArgTy = llvm::FixedVectorType::get( llvm::Type::getInt16Ty(getLLVMContext()), 4); break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8f16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8bf16: + ArgTy = llvm::FixedVectorType::get( + llvm::Type::getBFloatTy(getLLVMContext()), 8); + break; + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8f16: ArgTy = llvm::FixedVectorType::get( llvm::Type::getHalfTy(getLLVMContext()), 8); break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8i16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8i16: ArgTy = llvm::FixedVectorType::get( llvm::Type::getInt16Ty(getLLVMContext()), 8); break; diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp index d3f2573fd5e38abd8e87b88a07dc2c7970638a45..b756318c46a900abc16eb9f01b2a0947749e57c3 100644 --- a/clang/lib/CodeGen/CGCUDANV.cpp +++ b/clang/lib/CodeGen/CGCUDANV.cpp @@ -605,20 +605,10 @@ llvm::Function *CGNVCUDARuntime::makeRegisterGlobalsFn() { uint64_t VarSize = CGM.getDataLayout().getTypeAllocSize(Var->getValueType()); if (Info.Flags.isManaged()) { - auto *ManagedVar = new llvm::GlobalVariable( - CGM.getModule(), Var->getType(), - /*isConstant=*/false, Var->getLinkage(), - /*Init=*/Var->isDeclaration() - ? nullptr - : llvm::ConstantPointerNull::get(Var->getType()), - /*Name=*/"", /*InsertBefore=*/nullptr, - llvm::GlobalVariable::NotThreadLocal); - ManagedVar->setDSOLocal(Var->isDSOLocal()); - ManagedVar->setVisibility(Var->getVisibility()); - ManagedVar->setExternallyInitialized(true); - ManagedVar->takeName(Var); - Var->setName(Twine(ManagedVar->getName() + ".managed")); - replaceManagedVar(Var, ManagedVar); + assert(Var->getName().ends_with(".managed") && + "HIP managed variables not transformed"); + auto *ManagedVar = CGM.getModule().getNamedGlobal( + Var->getName().drop_back(StringRef(".managed").size())); llvm::Value *Args[] = { &GpuBinaryHandlePtr, ManagedVar, @@ -1093,7 +1083,9 @@ void CGNVCUDARuntime::transformManagedVars() { : llvm::ConstantPointerNull::get(Var->getType()), /*Name=*/"", /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, - CGM.getContext().getTargetAddressSpace(LangAS::cuda_device)); + CGM.getContext().getTargetAddressSpace(CGM.getLangOpts().CUDAIsDevice + ? LangAS::cuda_device + : LangAS::Default)); ManagedVar->setDSOLocal(Var->isDSOLocal()); ManagedVar->setVisibility(Var->getVisibility()); ManagedVar->setExternallyInitialized(true); @@ -1102,7 +1094,7 @@ void CGNVCUDARuntime::transformManagedVars() { Var->setName(Twine(ManagedVar->getName()) + ".managed"); // Keep managed variables even if they are not used in device code since // they need to be allocated by the runtime. - if (!Var->isDeclaration()) { + if (CGM.getLangOpts().CUDAIsDevice && !Var->isDeclaration()) { assert(!ManagedVar->isDeclaration()); CGM.addCompilerUsedGlobal(Var); CGM.addCompilerUsedGlobal(ManagedVar); @@ -1160,9 +1152,8 @@ void CGNVCUDARuntime::createOffloadingEntries() { // Returns module constructor to be added. llvm::Function *CGNVCUDARuntime::finalizeModule() { + transformManagedVars(); if (CGM.getLangOpts().CUDAIsDevice) { - transformManagedVars(); - // Mark ODR-used device variables as compiler used to prevent it from being // eliminated by optimization. This is necessary for device variables // ODR-used by host functions. Sema correctly marks them as ODR-used no diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 07ecaa81c47d84999e7f0a37a2fd3ad5e6d6f8f8..7453ed14aef4141ae316ebd78aa9a408fb2a07c0 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -3463,6 +3463,9 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { case Type::BTFTagAttributed: T = cast(T)->getWrappedType(); break; + case Type::CountAttributed: + T = cast(T)->desugar(); + break; case Type::Elaborated: T = cast(T)->getNamedType(); break; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index cb153066b28dd10eaaa3c6f2dafb35ebf4d77fdf..ac81df8cf7adfed9a4ba3c3bea367006e2f7eacb 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3711,7 +3711,8 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // Forward declarations are emitted lazily on first use. if (!FD->doesThisDeclarationHaveABody()) { - if (!FD->doesDeclarationForceExternallyVisibleDefinition()) + if (!FD->doesDeclarationForceExternallyVisibleDefinition() && + !FD->isTargetVersionMultiVersion()) return; StringRef MangledName = getMangledName(GD); @@ -4092,6 +4093,23 @@ llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM, return llvm::GlobalValue::WeakODRLinkage; } +static FunctionDecl *createDefaultTargetVersionFrom(const FunctionDecl *FD) { + DeclContext *DeclCtx = FD->getASTContext().getTranslationUnitDecl(); + TypeSourceInfo *TInfo = FD->getTypeSourceInfo(); + StorageClass SC = FD->getStorageClass(); + DeclarationName Name = FD->getNameInfo().getName(); + + FunctionDecl *NewDecl = + FunctionDecl::Create(FD->getASTContext(), DeclCtx, FD->getBeginLoc(), + FD->getEndLoc(), Name, TInfo->getType(), TInfo, SC); + + NewDecl->setIsMultiVersion(); + NewDecl->addAttr(TargetVersionAttr::CreateImplicit( + NewDecl->getASTContext(), "default", NewDecl->getSourceRange())); + + return NewDecl; +} + void CodeGenModule::emitMultiVersionFunctions() { std::vector MVFuncsToEmit; MultiVersionFuncs.swap(MVFuncsToEmit); @@ -4099,70 +4117,54 @@ void CodeGenModule::emitMultiVersionFunctions() { const auto *FD = cast(GD.getDecl()); assert(FD && "Expected a FunctionDecl"); - bool EmitResolver = !FD->isTargetVersionMultiVersion(); + auto createFunction = [&](const FunctionDecl *Decl, unsigned MVIdx = 0) { + GlobalDecl CurGD{Decl->isDefined() ? Decl->getDefinition() : Decl, MVIdx}; + StringRef MangledName = getMangledName(CurGD); + llvm::Constant *Func = GetGlobalValue(MangledName); + if (!Func) { + if (Decl->isDefined()) { + EmitGlobalFunctionDefinition(CurGD, nullptr); + Func = GetGlobalValue(MangledName); + } else { + const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(CurGD); + llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); + Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false, + /*DontDefer=*/false, ForDefinition); + } + assert(Func && "This should have just been created"); + } + return cast(Func); + }; + + bool HasDefaultDecl = !FD->isTargetVersionMultiVersion(); + bool ShouldEmitResolver = !FD->isTargetVersionMultiVersion(); SmallVector Options; if (FD->isTargetMultiVersion()) { getContext().forEachMultiversionedFunctionVersion( - FD, [this, &GD, &Options, &EmitResolver](const FunctionDecl *CurFD) { - GlobalDecl CurGD{ - (CurFD->isDefined() ? CurFD->getDefinition() : CurFD)}; - StringRef MangledName = getMangledName(CurGD); - llvm::Constant *Func = GetGlobalValue(MangledName); - if (!Func) { - if (CurFD->isDefined()) { - EmitGlobalFunctionDefinition(CurGD, nullptr); - Func = GetGlobalValue(MangledName); - } else { - const CGFunctionInfo &FI = - getTypes().arrangeGlobalDeclaration(GD); - llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); - Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false, - /*DontDefer=*/false, ForDefinition); - } - assert(Func && "This should have just been created"); - } - if (CurFD->getMultiVersionKind() == MultiVersionKind::Target) { - const auto *TA = CurFD->getAttr(); - llvm::SmallVector Feats; + FD, [&](const FunctionDecl *CurFD) { + llvm::SmallVector Feats; + llvm::Function *Func = createFunction(CurFD); + + if (const auto *TA = CurFD->getAttr()) { TA->getAddedFeatures(Feats); - Options.emplace_back(cast(Func), - TA->getArchitecture(), Feats); - } else { - const auto *TVA = CurFD->getAttr(); - if (CurFD->isUsed() || (TVA->isDefaultVersion() && - CurFD->doesThisDeclarationHaveABody())) - EmitResolver = true; - llvm::SmallVector Feats; + Options.emplace_back(Func, TA->getArchitecture(), Feats); + } else if (const auto *TVA = CurFD->getAttr()) { + bool HasDefaultDef = TVA->isDefaultVersion() && + CurFD->doesThisDeclarationHaveABody(); + HasDefaultDecl |= TVA->isDefaultVersion(); + ShouldEmitResolver |= (CurFD->isUsed() || HasDefaultDef); TVA->getFeatures(Feats); - Options.emplace_back(cast(Func), - /*Architecture*/ "", Feats); - } + Options.emplace_back(Func, /*Architecture*/ "", Feats); + } else + llvm_unreachable("unexpected MultiVersionKind"); }); - } else if (FD->isTargetClonesMultiVersion()) { - const auto *TC = FD->getAttr(); - for (unsigned VersionIndex = 0; VersionIndex < TC->featuresStrs_size(); - ++VersionIndex) { - if (!TC->isFirstOfVersion(VersionIndex)) + } else if (const auto *TC = FD->getAttr()) { + for (unsigned I = 0; I < TC->featuresStrs_size(); ++I) { + if (!TC->isFirstOfVersion(I)) continue; - GlobalDecl CurGD{(FD->isDefined() ? FD->getDefinition() : FD), - VersionIndex}; - StringRef Version = TC->getFeatureStr(VersionIndex); - StringRef MangledName = getMangledName(CurGD); - llvm::Constant *Func = GetGlobalValue(MangledName); - if (!Func) { - if (FD->isDefined()) { - EmitGlobalFunctionDefinition(CurGD, nullptr); - Func = GetGlobalValue(MangledName); - } else { - const CGFunctionInfo &FI = - getTypes().arrangeGlobalDeclaration(CurGD); - llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); - Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false, - /*DontDefer=*/false, ForDefinition); - } - assert(Func && "This should have just been created"); - } + llvm::Function *Func = createFunction(FD, I); + StringRef Version = TC->getFeatureStr(I); StringRef Architecture; llvm::SmallVector Feature; @@ -4180,16 +4182,23 @@ void CodeGenModule::emitMultiVersionFunctions() { Feature.push_back(Version); } - Options.emplace_back(cast(Func), Architecture, Feature); + Options.emplace_back(Func, Architecture, Feature); } } else { assert(0 && "Expected a target or target_clones multiversion function"); continue; } - if (!EmitResolver) + if (!ShouldEmitResolver) continue; + if (!HasDefaultDecl) { + FunctionDecl *NewFD = createDefaultTargetVersionFrom(FD); + llvm::Function *Func = createFunction(NewFD); + llvm::SmallVector Feats; + Options.emplace_back(Func, /*Architecture*/ "", Feats); + } + llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver(GD); if (auto *IFunc = dyn_cast(ResolverConstant)) { ResolverConstant = IFunc->getResolver(); @@ -4480,7 +4489,9 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( if (FD->isMultiVersion()) { UpdateMultiVersionNames(GD, FD, MangledName); - if (!IsForDefinition) + if (FD->isTargetVersionMultiVersion() && !FD->isUsed()) + AddDeferredMultiVersionResolverToEmit(GD); + else if (!IsForDefinition) return GetOrCreateMultiVersionResolver(GD); } } diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 4478865313636d964003035eccbac16911bfda3a..6b1fbba7abd031574e306805ef2fddceb9503c7f 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1142,7 +1142,11 @@ void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, options::OPT_fno_rtlib_add_rpath, false)) return; - for (const auto &CandidateRPath : TC.getArchSpecificLibPaths()) { + SmallVector CandidateRPaths(TC.getArchSpecificLibPaths()); + if (const auto CandidateRPath = TC.getStdlibPath()) + CandidateRPaths.emplace_back(*CandidateRPath); + + for (const auto &CandidateRPath : CandidateRPaths) { if (TC.getVFS().exists(CandidateRPath)) { CmdArgs.push_back("-rpath"); CmdArgs.push_back(Args.MakeArgString(CandidateRPath)); diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 349b93e2a2326f77b34b56aa4ee51f89038e1612..545860acb7db804fbe99321698b28db30ecc1eac 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -208,6 +208,7 @@ StringRef getLanguageName(Language Lang) { case Language::Unknown: case Language::Asm: case Language::LLVM_IR: + case Language::CIR: llvm_unreachable("Unsupported language kind"); } diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 63ec3a88978dd914bc06b6e2759ac4039338221c..46ed5baaeaceadc7ad739e657de60a2c6eb63641 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -895,6 +895,8 @@ template <> struct MappingTraits { IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros); IO.mapOptional("AlignConsecutiveShortCaseStatements", Style.AlignConsecutiveShortCaseStatements); + IO.mapOptional("AlignConsecutiveTableGenBreakingDAGArgColons", + Style.AlignConsecutiveTableGenBreakingDAGArgColons); IO.mapOptional("AlignConsecutiveTableGenCondOperatorColons", Style.AlignConsecutiveTableGenCondOperatorColons); IO.mapOptional("AlignConsecutiveTableGenDefinitionColons", @@ -1408,6 +1410,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AlignConsecutiveDeclarations = {}; LLVMStyle.AlignConsecutiveMacros = {}; LLVMStyle.AlignConsecutiveShortCaseStatements = {}; + LLVMStyle.AlignConsecutiveTableGenBreakingDAGArgColons = {}; LLVMStyle.AlignConsecutiveTableGenCondOperatorColons = {}; LLVMStyle.AlignConsecutiveTableGenDefinitionColons = {}; LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right; diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index 06f567059c3576deaf2df63fe0f7dfaa50987b9a..2ddcd5259446f6e4ba08d7892fbd93612454c49c 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -152,6 +152,7 @@ namespace format { TYPE(TableGenCondOperatorComma) \ TYPE(TableGenDAGArgCloser) \ TYPE(TableGenDAGArgListColon) \ + TYPE(TableGenDAGArgListColonToAlign) \ TYPE(TableGenDAGArgListComma) \ TYPE(TableGenDAGArgListCommaToBreak) \ TYPE(TableGenDAGArgOpener) \ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 94d2266555f6b9ad141b713e51a6582b95116333..4c83a7a3a323be59d4c11445665c854a3205f018 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -975,12 +975,15 @@ private: // DagArg ::= Value [":" TokVarName] | TokVarName // Appears as a part of SimpleValue6. - bool parseTableGenDAGArg() { + bool parseTableGenDAGArg(bool AlignColon = false) { if (tryToParseTableGenTokVar()) return true; if (parseTableGenValue()) { if (CurrentToken && CurrentToken->is(tok::colon)) { - CurrentToken->setType(TT_TableGenDAGArgListColon); + if (AlignColon) + CurrentToken->setType(TT_TableGenDAGArgListColonToAlign); + else + CurrentToken->setType(TT_TableGenDAGArgListColon); skipToNextNonComment(); return tryToParseTableGenTokVar(); } @@ -1051,8 +1054,11 @@ private: skipToNextNonComment(); return true; } - if (!parseTableGenDAGArg()) + if (!parseTableGenDAGArg( + BreakInside && + Style.AlignConsecutiveTableGenBreakingDAGArgColons.Enabled)) { return false; + } FirstDAGArgListElm = false; } return false; @@ -2747,10 +2753,9 @@ private: } // Heuristically try to determine whether the parentheses contain a type. - auto IsQualifiedPointerOrReference = [this](FormatToken *T) { + auto IsQualifiedPointerOrReference = [](FormatToken *T, bool IsCpp) { // This is used to handle cases such as x = (foo *const)&y; assert(!T->isTypeName(IsCpp) && "Should have already been checked"); - (void)IsCpp; // Avoid -Wunused-lambda-capture when assertion is disabled. // Strip trailing qualifiers such as const or volatile when checking // whether the parens could be a cast to a pointer/reference type. while (T) { @@ -2783,7 +2788,7 @@ private: !Tok.Previous || Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) || Tok.Previous->isTypeName(IsCpp) || - IsQualifiedPointerOrReference(Tok.Previous); + IsQualifiedPointerOrReference(Tok.Previous, IsCpp); bool ParensCouldEndDecl = Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater); if (ParensAreType && !ParensCouldEndDecl) @@ -4351,9 +4356,11 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, if (Left.is(tok::kw_auto) && Right.isOneOf(tok::l_paren, tok::l_brace)) return false; + const auto *BeforeLeft = Left.Previous; + // operator co_await(x) - if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && Left.Previous && - Left.Previous->is(tok::kw_operator)) { + if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && BeforeLeft && + BeforeLeft->is(tok::kw_operator)) { return false; } // co_await (x), co_yield (x), co_return (x) @@ -4388,8 +4395,10 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, } if (Left.is(tok::colon)) return Left.isNot(TT_ObjCMethodExpr); - if (Left.is(tok::coloncolon)) - return false; + if (Left.is(tok::coloncolon)) { + return Right.is(tok::star) && Right.is(TT_PointerOrReference) && + Style.PointerAlignment != FormatStyle::PAS_Left; + } if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) { if (Style.Language == FormatStyle::LK_TextProto || (Style.Language == FormatStyle::LK_Proto && @@ -4404,8 +4413,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, return false; } if (Right.is(tok::ellipsis)) { - return Left.Tok.isLiteral() || (Left.is(tok::identifier) && Left.Previous && - Left.Previous->is(tok::kw_case)); + return Left.Tok.isLiteral() || (Left.is(tok::identifier) && BeforeLeft && + BeforeLeft->is(tok::kw_case)); } if (Left.is(tok::l_square) && Right.is(tok::amp)) return Style.SpacesInSquareBrackets; @@ -4473,8 +4482,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, if (Right.is(tok::l_brace) && Right.is(BK_Block)) return true; // for (auto a = 0, b = 0; const auto& c : {1, 2, 3}) - if (Left.Previous && Left.Previous->isTypeOrIdentifier(IsCpp) && - Right.Next && Right.Next->is(TT_RangeBasedForLoopColon)) { + if (BeforeLeft && BeforeLeft->isTypeOrIdentifier(IsCpp) && Right.Next && + Right.Next->is(TT_RangeBasedForLoopColon)) { return getTokenPointerOrReferenceAlignment(Left) != FormatStyle::PAS_Right; } @@ -4496,12 +4505,17 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, startsWithInitStatement(Line)))) { return false; } - return Left.Previous && !Left.Previous->isOneOf( - tok::l_paren, tok::coloncolon, tok::l_square); + if (!BeforeLeft) + return false; + if (BeforeLeft->is(tok::coloncolon)) { + return Left.is(tok::star) && + Style.PointerAlignment != FormatStyle::PAS_Right; + } + return !BeforeLeft->isOneOf(tok::l_paren, tok::l_square); } // Ensure right pointer alignment with ellipsis e.g. int *...P - if (Left.is(tok::ellipsis) && Left.Previous && - Left.Previous->isPointerOrReference()) { + if (Left.is(tok::ellipsis) && BeforeLeft && + BeforeLeft->isPointerOrReference()) { return Style.PointerAlignment != FormatStyle::PAS_Right; } @@ -4663,13 +4677,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName || spaceRequiredBeforeParens(Right); } - if (!Left.Previous || !Left.Previous->isOneOf(tok::period, tok::arrow)) { + if (!BeforeLeft || !BeforeLeft->isOneOf(tok::period, tok::arrow)) { if (Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch)) { return Style.SpaceBeforeParensOptions.AfterControlStatements || spaceRequiredBeforeParens(Right); } if (Left.isOneOf(tok::kw_new, tok::kw_delete)) { - return ((!Line.MightBeFunctionDecl || !Left.Previous) && + return ((!Line.MightBeFunctionDecl || !BeforeLeft) && Style.SpaceBeforeParens != FormatStyle::SBPO_Never) || spaceRequiredBeforeParens(Right); } @@ -5130,8 +5144,10 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, if (Left.is(tok::r_brace) && Right.is(tok::r_square)) return true; // Do not insert around colon in DAGArg and cond operator. - if (Right.is(TT_TableGenDAGArgListColon) || - Left.is(TT_TableGenDAGArgListColon)) { + if (Right.isOneOf(TT_TableGenDAGArgListColon, + TT_TableGenDAGArgListColonToAlign) || + Left.isOneOf(TT_TableGenDAGArgListColon, + TT_TableGenDAGArgListColonToAlign)) { return false; } if (Right.is(TT_TableGenCondOperatorColon)) diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index 753be25bfd67585380ad61be9c00fa7167ca9764..710bf8d8a8ec700d8323435436f9ea02006acd06 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -112,6 +112,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() { alignConsecutiveBitFields(); alignConsecutiveAssignments(); if (Style.isTableGen()) { + alignConsecutiveTableGenBreakingDAGArgColons(); alignConsecutiveTableGenCondOperatorColons(); alignConsecutiveTableGenDefinitions(); } @@ -981,6 +982,11 @@ void WhitespaceManager::alignConsecutiveShortCaseStatements() { Changes); } +void WhitespaceManager::alignConsecutiveTableGenBreakingDAGArgColons() { + alignConsecutiveColons(Style.AlignConsecutiveTableGenBreakingDAGArgColons, + TT_TableGenDAGArgListColonToAlign); +} + void WhitespaceManager::alignConsecutiveTableGenCondOperatorColons() { alignConsecutiveColons(Style.AlignConsecutiveTableGenCondOperatorColons, TT_TableGenCondOperatorColon); @@ -1485,7 +1491,7 @@ WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start, : Cell); // Go to the next non-comment and ensure there is a break in front const auto *NextNonComment = C.Tok->getNextNonComment(); - while (NextNonComment->is(tok::comma)) + while (NextNonComment && NextNonComment->is(tok::comma)) NextNonComment = NextNonComment->getNextNonComment(); auto j = i; while (j < End && Changes[j].Tok != NextNonComment) diff --git a/clang/lib/Format/WhitespaceManager.h b/clang/lib/Format/WhitespaceManager.h index 0ebc6cf8377cdb293a6895a851c25e117001ae93..98cf4a260cc46891ed7844fbca370c6d8921787e 100644 --- a/clang/lib/Format/WhitespaceManager.h +++ b/clang/lib/Format/WhitespaceManager.h @@ -235,6 +235,9 @@ private: /// Align consecutive short case statements over all \c Changes. void alignConsecutiveShortCaseStatements(); + /// Align consecutive TableGen DAGArg colon over all \c Changes. + void alignConsecutiveTableGenBreakingDAGArgColons(); + /// Align consecutive TableGen cond operator colon over all \c Changes. void alignConsecutiveTableGenCondOperatorColons(); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 0df6a82ccd893316ea65b819977501bd5f42c270..7bd91d4791ecf0b9d9657c9937c0d71940b8837e 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2757,6 +2757,9 @@ static void GenerateFrontendArgs(const FrontendOptions &Opts, case Language::HLSL: Lang = "hlsl"; break; + case Language::CIR: + Lang = "cir"; + break; } GenerateArg(Consumer, OPT_x, @@ -2958,6 +2961,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, .Cases("ast", "pcm", "precompiled-header", InputKind(Language::Unknown, InputKind::Precompiled)) .Case("ir", Language::LLVM_IR) + .Case("cir", Language::CIR) .Default(Language::Unknown); if (DashX.isUnknown()) @@ -3323,6 +3327,7 @@ static bool IsInputCompatibleWithStandard(InputKind IK, switch (IK.getLanguage()) { case Language::Unknown: case Language::LLVM_IR: + case Language::CIR: llvm_unreachable("should not parse language flags for this input"); case Language::C: @@ -3388,6 +3393,8 @@ static StringRef GetInputKindName(InputKind IK) { return "Asm"; case Language::LLVM_IR: return "LLVM IR"; + case Language::CIR: + return "Clang IR"; case Language::HLSL: return "HLSL"; @@ -3403,7 +3410,8 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, const llvm::Triple &T, InputKind IK) { if (IK.getFormat() == InputKind::Precompiled || - IK.getLanguage() == Language::LLVM_IR) { + IK.getLanguage() == Language::LLVM_IR || + IK.getLanguage() == Language::CIR) { if (Opts.ObjCAutoRefCount) GenerateArg(Consumer, OPT_fobjc_arc); if (Opts.PICLevel != 0) @@ -3689,7 +3697,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, unsigned NumErrorsBefore = Diags.getNumErrors(); if (IK.getFormat() == InputKind::Precompiled || - IK.getLanguage() == Language::LLVM_IR) { + IK.getLanguage() == Language::LLVM_IR || + IK.getLanguage() == Language::CIR) { // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the // PassManager in BackendUtil.cpp. They need to be initialized no matter // what the input type is. diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 81fcd8d5ae9bd30d9605a9cb6d37d87b4b7c35ec..3fd1cdd3b4794262979ae19f7baed673e8dbc220 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -1083,6 +1083,7 @@ void PrintPreambleAction::ExecuteAction() { case Language::CUDA: case Language::HIP: case Language::HLSL: + case Language::CIR: break; case Language::Unknown: diff --git a/clang/lib/Frontend/FrontendOptions.cpp b/clang/lib/Frontend/FrontendOptions.cpp index bf83b27c1367efdff086d77a98fe839bf33bd976..32ed99571e85d2cb35c9b6aa4926ac1cd442deb0 100644 --- a/clang/lib/Frontend/FrontendOptions.cpp +++ b/clang/lib/Frontend/FrontendOptions.cpp @@ -34,5 +34,6 @@ InputKind FrontendOptions::getInputKindForExtension(StringRef Extension) { .Case("hip", Language::HIP) .Cases("ll", "bc", Language::LLVM_IR) .Case("hlsl", Language::HLSL) + .Case("cir", Language::CIR) .Default(Language::Unknown); } diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 5e703772b7ee4f539d21efba95ece7b3737af31f..fcb64fde1b91f19e184ac6d2cdfc8f133f635ca8 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -737,15 +737,6 @@ float3 log(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_log) float4 log(float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log) -double log(double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log) -double2 log(double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log) -double3 log(double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log) -double4 log(double4); - //===----------------------------------------------------------------------===// // log10 builtins //===----------------------------------------------------------------------===// @@ -779,15 +770,6 @@ float3 log10(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_log10) float4 log10(float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log10) -double log10(double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log10) -double2 log10(double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log10) -double3 log10(double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log10) -double4 log10(double4); - //===----------------------------------------------------------------------===// // log2 builtins //===----------------------------------------------------------------------===// @@ -821,15 +803,6 @@ float3 log2(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_log2) float4 log2(float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log2) -double log2(double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log2) -double2 log2(double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log2) -double3 log2(double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log2) -double4 log2(double4); - //===----------------------------------------------------------------------===// // mad builtins //===----------------------------------------------------------------------===// @@ -1174,15 +1147,6 @@ float3 pow(float3, float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_pow) float4 pow(float4, float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_pow) -double pow(double, double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_pow) -double2 pow(double2, double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_pow) -double3 pow(double3, double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_pow) -double4 pow(double4, double4); - //===----------------------------------------------------------------------===// // reversebits builtins //===----------------------------------------------------------------------===// @@ -1393,15 +1357,6 @@ float3 sin(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_sin) float4 sin(float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sin) -double sin(double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sin) -double2 sin(double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sin) -double3 sin(double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sin) -double4 sin(double4); - //===----------------------------------------------------------------------===// // sqrt builtins //===----------------------------------------------------------------------===// @@ -1411,14 +1366,26 @@ double4 sin(double4); /// \param Val The input value. _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_sqrtf16) -half sqrt(half In); - -_HLSL_BUILTIN_ALIAS(__builtin_sqrtf) -float sqrt(float In); +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +half sqrt(half); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +half2 sqrt(half2); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +half3 sqrt(half3); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +half4 sqrt(half4); -_HLSL_BUILTIN_ALIAS(__builtin_sqrt) -double sqrt(double In); +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +float sqrt(float); +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +float2 sqrt(float2); +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +float3 sqrt(float3); +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +float4 sqrt(float4); //===----------------------------------------------------------------------===// // trunc builtins @@ -1450,15 +1417,6 @@ float3 trunc(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_trunc) float4 trunc(float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_trunc) -double trunc(double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_trunc) -double2 trunc(double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_trunc) -double3 trunc(double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_trunc) -double4 trunc(double4); - //===----------------------------------------------------------------------===// // Wave* builtins //===----------------------------------------------------------------------===// diff --git a/clang/lib/Headers/mmintrin.h b/clang/lib/Headers/mmintrin.h index 962d24738e7aa48e338e57141952ebf5d359c492..4e154e2d85935303eddf0dbaf0f62c7401adc09d 100644 --- a/clang/lib/Headers/mmintrin.h +++ b/clang/lib/Headers/mmintrin.h @@ -1141,7 +1141,7 @@ _mm_xor_si64(__m64 __m1, __m64 __m2) /// [8 x i8] to determine if the element of the first vector is equal to the /// corresponding element of the second vector. /// -/// The comparison yields 0 for false, 0xFF for true. +/// Each comparison returns 0 for false, 0xFF for true. /// /// \headerfile /// @@ -1163,7 +1163,7 @@ _mm_cmpeq_pi8(__m64 __m1, __m64 __m2) /// [4 x i16] to determine if the element of the first vector is equal to the /// corresponding element of the second vector. /// -/// The comparison yields 0 for false, 0xFFFF for true. +/// Each comparison returns 0 for false, 0xFFFF for true. /// /// \headerfile /// @@ -1185,7 +1185,7 @@ _mm_cmpeq_pi16(__m64 __m1, __m64 __m2) /// [2 x i32] to determine if the element of the first vector is equal to the /// corresponding element of the second vector. /// -/// The comparison yields 0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0 for false, 0xFFFFFFFF for true. /// /// \headerfile /// @@ -1207,7 +1207,7 @@ _mm_cmpeq_pi32(__m64 __m1, __m64 __m2) /// [8 x i8] to determine if the element of the first vector is greater than /// the corresponding element of the second vector. /// -/// The comparison yields 0 for false, 0xFF for true. +/// Each comparison returns 0 for false, 0xFF for true. /// /// \headerfile /// @@ -1229,7 +1229,7 @@ _mm_cmpgt_pi8(__m64 __m1, __m64 __m2) /// [4 x i16] to determine if the element of the first vector is greater than /// the corresponding element of the second vector. /// -/// The comparison yields 0 for false, 0xFFFF for true. +/// Each comparison returns 0 for false, 0xFFFF for true. /// /// \headerfile /// @@ -1251,7 +1251,7 @@ _mm_cmpgt_pi16(__m64 __m1, __m64 __m2) /// [2 x i32] to determine if the element of the first vector is greater than /// the corresponding element of the second vector. /// -/// The comparison yields 0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0 for false, 0xFFFFFFFF for true. /// /// \headerfile /// diff --git a/clang/lib/Headers/smmintrin.h b/clang/lib/Headers/smmintrin.h index 9fb9cc9b01348cae2302249e55020fc0c36a58fb..b3fec474e35a1e03e7b4de6e434355a959caeb25 100644 --- a/clang/lib/Headers/smmintrin.h +++ b/clang/lib/Headers/smmintrin.h @@ -1188,7 +1188,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_testnzc_si128(__m128i __M, /// Compares each of the corresponding 64-bit values of the 128-bit /// integer vectors for equality. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. /// /// \headerfile /// @@ -2303,7 +2303,7 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_minpos_epu16(__m128i __V) { /// integer vectors to determine if the values in the first operand are /// greater than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. /// /// \headerfile /// diff --git a/clang/lib/Headers/xmmintrin.h b/clang/lib/Headers/xmmintrin.h index 040194786a27998610bdd3e770055f6e3785a85f..1ef89de9c9f5622d60b63fa19c06ddf7589488ef 100644 --- a/clang/lib/Headers/xmmintrin.h +++ b/clang/lib/Headers/xmmintrin.h @@ -484,7 +484,7 @@ _mm_xor_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands for equality. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// The comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector [4 x float]. /// If either value in a comparison is NaN, returns false. /// @@ -509,7 +509,7 @@ _mm_cmpeq_ss(__m128 __a, __m128 __b) /// Compares each of the corresponding 32-bit float values of the /// 128-bit vectors of [4 x float] for equality. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. /// If either value in a comparison is NaN, returns false. /// /// \headerfile @@ -531,7 +531,7 @@ _mm_cmpeq_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is less than the /// corresponding value in the second operand. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// The comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. /// If either value in a comparison is NaN, returns false. /// @@ -557,7 +557,7 @@ _mm_cmplt_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are less than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. /// If either value in a comparison is NaN, returns false. /// /// \headerfile @@ -579,7 +579,7 @@ _mm_cmplt_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is less than or /// equal to the corresponding value in the second operand. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true, in +/// The comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true, in /// the low-order bits of a vector of [4 x float]. /// If either value in a comparison is NaN, returns false. /// @@ -605,7 +605,7 @@ _mm_cmple_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are less than or equal to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. /// If either value in a comparison is NaN, returns false. /// /// \headerfile @@ -627,7 +627,7 @@ _mm_cmple_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is greater than /// the corresponding value in the second operand. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// The comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. /// If either value in a comparison is NaN, returns false. /// @@ -655,7 +655,7 @@ _mm_cmpgt_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are greater than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. /// If either value in a comparison is NaN, returns false. /// /// \headerfile @@ -677,7 +677,7 @@ _mm_cmpgt_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is greater than /// or equal to the corresponding value in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. /// If either value in a comparison is NaN, returns false. /// @@ -705,7 +705,7 @@ _mm_cmpge_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are greater than or equal to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. /// If either value in a comparison is NaN, returns false. /// /// \headerfile @@ -726,7 +726,7 @@ _mm_cmpge_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both operands /// for inequality. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// The comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. /// If either value in a comparison is NaN, returns true. /// @@ -752,7 +752,7 @@ _mm_cmpneq_ss(__m128 __a, __m128 __b) /// Compares each of the corresponding 32-bit float values of the /// 128-bit vectors of [4 x float] for inequality. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. /// If either value in a comparison is NaN, returns true. /// /// \headerfile @@ -775,7 +775,7 @@ _mm_cmpneq_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is not less than /// the corresponding value in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. /// If either value in a comparison is NaN, returns true. /// @@ -802,7 +802,7 @@ _mm_cmpnlt_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are not less than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. /// If either value in a comparison is NaN, returns true. /// /// \headerfile @@ -825,7 +825,7 @@ _mm_cmpnlt_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is not less than /// or equal to the corresponding value in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. /// If either value in a comparison is NaN, returns true. /// @@ -852,7 +852,7 @@ _mm_cmpnle_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are not less than or equal to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. /// If either value in a comparison is NaN, returns true. /// /// \headerfile @@ -875,7 +875,7 @@ _mm_cmpnle_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is not greater /// than the corresponding value in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. /// If either value in a comparison is NaN, returns true. /// @@ -904,7 +904,7 @@ _mm_cmpngt_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are not greater than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. /// If either value in a comparison is NaN, returns true. /// /// \headerfile @@ -927,7 +927,7 @@ _mm_cmpngt_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is not greater /// than or equal to the corresponding value in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. /// If either value in a comparison is NaN, returns true. /// @@ -956,7 +956,7 @@ _mm_cmpnge_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are not greater than or equal to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. /// If either value in a comparison is NaN, returns true. /// /// \headerfile @@ -3061,7 +3061,7 @@ _mm_movemask_ps(__m128 __a) /// [4 x float], using the operation specified by the immediate integer /// operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. /// If either value in a comparison is NaN, comparisons that are ordered /// return false, and comparisons that are unordered return true. /// @@ -3096,7 +3096,7 @@ _mm_movemask_ps(__m128 __a) /// vectors of [4 x float], using the operation specified by the immediate /// integer operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. /// If either value in a comparison is NaN, comparisons that are ordered /// return false, and comparisons that are unordered return true. /// diff --git a/clang/lib/InstallAPI/DylibVerifier.cpp b/clang/lib/InstallAPI/DylibVerifier.cpp index 24e0d0addf2f460b91da8914c4f0875ed0e9e4bd..94b8e9cd3233a9213562b243d204208ef1e268e4 100644 --- a/clang/lib/InstallAPI/DylibVerifier.cpp +++ b/clang/lib/InstallAPI/DylibVerifier.cpp @@ -66,17 +66,15 @@ std::string DylibVerifier::getAnnotatedName(const Record *R, Annotation += "(tlv) "; // Check if symbol represents only part of a @interface declaration. - const bool IsAnnotatedObjCClass = - ((SymCtx.ObjCIFKind != ObjCIFSymbolKind::None) && - (SymCtx.ObjCIFKind <= ObjCIFSymbolKind::EHType)); - - if (IsAnnotatedObjCClass) { - if (SymCtx.ObjCIFKind == ObjCIFSymbolKind::EHType) - Annotation += "Exception Type of "; - if (SymCtx.ObjCIFKind == ObjCIFSymbolKind::MetaClass) - Annotation += "Metaclass of "; - if (SymCtx.ObjCIFKind == ObjCIFSymbolKind::Class) - Annotation += "Class of "; + switch (SymCtx.ObjCIFKind) { + default: + break; + case ObjCIFSymbolKind::EHType: + return Annotation + "Exception Type of " + PrettyName; + case ObjCIFSymbolKind::MetaClass: + return Annotation + "Metaclass of " + PrettyName; + case ObjCIFSymbolKind::Class: + return Annotation + "Class of " + PrettyName; } // Only print symbol type prefix or leading "_" if there is no source location @@ -90,9 +88,6 @@ std::string DylibVerifier::getAnnotatedName(const Record *R, return Annotation + PrettyName; } - if (IsAnnotatedObjCClass) - return Annotation + PrettyName; - switch (SymCtx.Kind) { case EncodeKind::GlobalSymbol: return Annotation + PrettyName; @@ -332,9 +327,9 @@ bool DylibVerifier::compareSymbolFlags(const Record *R, SymbolContext &SymCtx, } if (!DR->isThreadLocalValue() && R->isThreadLocalValue()) { Ctx.emitDiag([&]() { - SymCtx.FA->D->getLocation(), - Ctx.Diag->Report(diag::err_header_symbol_flags_mismatch) - << getAnnotatedName(DR, SymCtx) << R->isThreadLocalValue(); + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::err_header_symbol_flags_mismatch) + << getAnnotatedName(R, SymCtx) << R->isThreadLocalValue(); }); return false; } @@ -520,5 +515,147 @@ void DylibVerifier::VerifierContext::emitDiag( Report(); } +// The existence of weak-defined RTTI can not always be inferred from the +// header files because they can be generated as part of an implementation +// file. +// InstallAPI doesn't warn about weak-defined RTTI, because this doesn't affect +// static linking and so can be ignored for text-api files. +static bool shouldIgnoreCpp(StringRef Name, bool IsWeakDef) { + return (IsWeakDef && + (Name.starts_with("__ZTI") || Name.starts_with("__ZTS"))); +} +void DylibVerifier::visitSymbolInDylib(const Record &R, SymbolContext &SymCtx) { + // Undefined symbols should not be in InstallAPI generated text-api files. + if (R.isUndefined()) { + updateState(Result::Valid); + return; + } + + // Internal symbols should not be in InstallAPI generated text-api files. + if (R.isInternal()) { + updateState(Result::Valid); + return; + } + + // Allow zippered symbols with potentially mismatching availability + // between macOS and macCatalyst in the final text-api file. + const StringRef SymbolName(SymCtx.SymbolName); + if (const Symbol *Sym = Exports->findSymbol(SymCtx.Kind, SymCtx.SymbolName, + SymCtx.ObjCIFKind)) { + if (Sym->hasArchitecture(Ctx.Target.Arch)) { + updateState(Result::Ignore); + return; + } + } + + if (shouldIgnoreCpp(SymbolName, R.isWeakDefined())) { + updateState(Result::Valid); + return; + } + + // All checks at this point classify as some kind of violation that should be + // reported. + + // Regardless of verification mode, error out on mismatched special linker + // symbols. + if (SymbolName.starts_with("$ld$")) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(diag::err_header_symbol_missing) + << getAnnotatedName(&R, SymCtx, /*ValidSourceLoc=*/false); + }); + updateState(Result::Invalid); + return; + } + + // Missing declarations for exported symbols are hard errors on Pedantic mode. + if (Mode == VerificationMode::Pedantic) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(diag::err_header_symbol_missing) + << getAnnotatedName(&R, SymCtx, /*ValidSourceLoc=*/false); + }); + updateState(Result::Invalid); + return; + } + + // Missing declarations for exported symbols are warnings on ErrorsAndWarnings + // mode. + if (Mode == VerificationMode::ErrorsAndWarnings) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(diag::warn_header_symbol_missing) + << getAnnotatedName(&R, SymCtx, /*ValidSourceLoc=*/false); + }); + updateState(Result::Ignore); + return; + } + + // Missing declarations are dropped for ErrorsOnly mode. It is the last + // remaining mode. + updateState(Result::Ignore); + return; +} + +void DylibVerifier::visitGlobal(const GlobalRecord &R) { + if (R.isVerified()) + return; + SymbolContext SymCtx; + SimpleSymbol Sym = parseSymbol(R.getName()); + SymCtx.SymbolName = Sym.Name; + SymCtx.Kind = Sym.Kind; + visitSymbolInDylib(R, SymCtx); +} + +void DylibVerifier::visitObjCIVar(const ObjCIVarRecord &R, + const StringRef Super) { + if (R.isVerified()) + return; + SymbolContext SymCtx; + SymCtx.SymbolName = ObjCIVarRecord::createScopedName(Super, R.getName()); + SymCtx.Kind = EncodeKind::ObjectiveCInstanceVariable; + visitSymbolInDylib(R, SymCtx); +} + +void DylibVerifier::visitObjCInterface(const ObjCInterfaceRecord &R) { + if (R.isVerified()) + return; + SymbolContext SymCtx; + SymCtx.SymbolName = R.getName(); + SymCtx.ObjCIFKind = assignObjCIFSymbolKind(&R); + if (SymCtx.ObjCIFKind > ObjCIFSymbolKind::EHType) { + if (R.hasExceptionAttribute()) { + SymCtx.Kind = EncodeKind::ObjectiveCClassEHType; + visitSymbolInDylib(R, SymCtx); + } + SymCtx.Kind = EncodeKind::ObjectiveCClass; + visitSymbolInDylib(R, SymCtx); + } else { + SymCtx.Kind = R.hasExceptionAttribute() ? EncodeKind::ObjectiveCClassEHType + : EncodeKind::ObjectiveCClass; + visitSymbolInDylib(R, SymCtx); + } + + for (const ObjCIVarRecord *IV : R.getObjCIVars()) + visitObjCIVar(*IV, R.getName()); +} + +void DylibVerifier::visitObjCCategory(const ObjCCategoryRecord &R) { + for (const ObjCIVarRecord *IV : R.getObjCIVars()) + visitObjCIVar(*IV, R.getSuperClassName()); +} + +DylibVerifier::Result DylibVerifier::verifyRemainingSymbols() { + if (getState() == Result::NoVerify) + return Result::NoVerify; + assert(!Dylib.empty() && "No binary to verify against"); + + Ctx.DiscoveredFirstError = false; + Ctx.PrintArch = true; + for (std::shared_ptr Slice : Dylib) { + Ctx.Target = Slice->getTarget(); + Ctx.DylibSlice = Slice.get(); + Slice->visit(*this); + } + return getState(); +} + } // namespace installapi } // namespace clang diff --git a/clang/lib/InstallAPI/Frontend.cpp b/clang/lib/InstallAPI/Frontend.cpp index 12cd5fcbc22bf73fd40225d8c2b3457efeacf2c7..e07ccb14e0b80a4e4f87ccf804387832e64ab669 100644 --- a/clang/lib/InstallAPI/Frontend.cpp +++ b/clang/lib/InstallAPI/Frontend.cpp @@ -138,6 +138,8 @@ std::unique_ptr createInputBuffer(InstallAPIContext &Ctx) { SmallString<4096> Contents; raw_svector_ostream OS(Contents); for (const HeaderFile &H : Ctx.InputHeaders) { + if (H.isExcluded()) + continue; if (H.getType() != Ctx.Type) continue; if (Ctx.LangMode == Language::C || Ctx.LangMode == Language::CXX) diff --git a/clang/lib/InstallAPI/HeaderFile.cpp b/clang/lib/InstallAPI/HeaderFile.cpp index c2d8372741ee07e801dff5d4c3edd5f4963e88f8..0b7041ec8147eb95fc96ad6899d065aa5b6dd185 100644 --- a/clang/lib/InstallAPI/HeaderFile.cpp +++ b/clang/lib/InstallAPI/HeaderFile.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "clang/InstallAPI/HeaderFile.h" +#include "llvm/TextAPI/Utils.h" using namespace llvm; namespace clang::installapi { @@ -34,4 +35,54 @@ std::optional createIncludeHeaderName(const StringRef FullPath) { return Matches[1].drop_front(Matches[1].rfind('/') + 1).str() + "/" + Matches[3].str(); } + +bool isHeaderFile(StringRef Path) { + return StringSwitch(sys::path::extension(Path)) + .Cases(".h", ".H", ".hh", ".hpp", ".hxx", true) + .Default(false); +} + +llvm::Expected enumerateFiles(FileManager &FM, StringRef Directory) { + PathSeq Files; + std::error_code EC; + auto &FS = FM.getVirtualFileSystem(); + for (llvm::vfs::recursive_directory_iterator i(FS, Directory, EC), ie; + i != ie; i.increment(EC)) { + if (EC) + return errorCodeToError(EC); + + // Skip files that do not exist. This usually happens for broken symlinks. + if (FS.status(i->path()) == std::errc::no_such_file_or_directory) + continue; + + StringRef Path = i->path(); + if (isHeaderFile(Path)) + Files.emplace_back(Path); + } + + return Files; +} + +HeaderGlob::HeaderGlob(StringRef GlobString, Regex &&Rule, HeaderType Type) + : GlobString(GlobString), Rule(std::move(Rule)), Type(Type) {} + +bool HeaderGlob::match(const HeaderFile &Header) { + if (Header.getType() != Type) + return false; + + bool Match = Rule.match(Header.getPath()); + if (Match) + FoundMatch = true; + return Match; +} + +Expected> HeaderGlob::create(StringRef GlobString, + HeaderType Type) { + auto Rule = MachO::createRegexFromGlob(GlobString); + if (!Rule) + return Rule.takeError(); + + return std::make_unique(GlobString, std::move(*Rule), Type); +} + } // namespace clang::installapi diff --git a/clang/lib/InstallAPI/Visitor.cpp b/clang/lib/InstallAPI/Visitor.cpp index 452c8f2fb1e489b76666b1657ceb213834524612..f8f5d8d53d5691b0b9657f200d67660add514667 100644 --- a/clang/lib/InstallAPI/Visitor.cpp +++ b/clang/lib/InstallAPI/Visitor.cpp @@ -205,9 +205,10 @@ bool InstallAPIVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { const ObjCInterfaceDecl *InterfaceD = D->getClassInterface(); const StringRef InterfaceName = InterfaceD->getName(); - auto [Category, FA] = Ctx.Slice->addObjCCategory(InterfaceName, CategoryName, - Avail, D, *Access); - recordObjCInstanceVariables(D->getASTContext(), Category, InterfaceName, + std::pair Category = + Ctx.Slice->addObjCCategory(InterfaceName, CategoryName, Avail, D, + *Access); + recordObjCInstanceVariables(D->getASTContext(), Category.first, InterfaceName, D->ivars()); return true; } diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp index 40bcef94797d43d7b847a51691d6c06fbbc2bd90..6f036107c14a9c51143323ad7f59766aaac1fbd8 100644 --- a/clang/lib/Interpreter/IncrementalExecutor.cpp +++ b/clang/lib/Interpreter/IncrementalExecutor.cpp @@ -20,6 +20,7 @@ #include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h" @@ -36,26 +37,28 @@ LLVM_ATTRIBUTE_USED void linkComponents() { namespace clang { +llvm::Expected> +IncrementalExecutor::createDefaultJITBuilder( + llvm::orc::JITTargetMachineBuilder JTMB) { + auto JITBuilder = std::make_unique(); + JITBuilder->setJITTargetMachineBuilder(std::move(JTMB)); + JITBuilder->setPrePlatformSetup([](llvm::orc::LLJIT &J) { + // Try to enable debugging of JIT'd code (only works with JITLink for + // ELF and MachO). + consumeError(llvm::orc::enableDebuggerSupport(J)); + return llvm::Error::success(); + }); + return std::move(JITBuilder); +} + IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, - llvm::Error &Err, - const clang::TargetInfo &TI) + llvm::orc::LLJITBuilder &JITBuilder, + llvm::Error &Err) : TSCtx(TSC) { using namespace llvm::orc; llvm::ErrorAsOutParameter EAO(&Err); - auto JTMB = JITTargetMachineBuilder(TI.getTriple()); - JTMB.addFeatures(TI.getTargetOpts().Features); - LLJITBuilder Builder; - Builder.setJITTargetMachineBuilder(JTMB); - Builder.setPrePlatformSetup( - [](LLJIT &J) { - // Try to enable debugging of JIT'd code (only works with JITLink for - // ELF and MachO). - consumeError(enableDebuggerSupport(J)); - return llvm::Error::success(); - }); - - if (auto JitOrErr = Builder.create()) + if (auto JitOrErr = JITBuilder.create()) Jit = std::move(*JitOrErr); else { Err = JitOrErr.takeError(); diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h index dd0a210a0614154f3d81db726de059375533d6d6..b4347209e14fe33b782bcdf036b2ead590726a1b 100644 --- a/clang/lib/Interpreter/IncrementalExecutor.h +++ b/clang/lib/Interpreter/IncrementalExecutor.h @@ -23,7 +23,9 @@ namespace llvm { class Error; namespace orc { +class JITTargetMachineBuilder; class LLJIT; +class LLJITBuilder; class ThreadSafeContext; } // namespace orc } // namespace llvm @@ -44,8 +46,8 @@ class IncrementalExecutor { public: enum SymbolNameKind { IRName, LinkerName }; - IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, llvm::Error &Err, - const clang::TargetInfo &TI); + IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, + llvm::orc::LLJITBuilder &JITBuilder, llvm::Error &Err); ~IncrementalExecutor(); llvm::Error addModule(PartialTranslationUnit &PTU); @@ -56,6 +58,9 @@ public: getSymbolAddress(llvm::StringRef Name, SymbolNameKind NameKind) const; llvm::orc::LLJIT &GetExecutionEngine() { return *Jit; } + + static llvm::Expected> + createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB); }; } // end namespace clang diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 7fa52f2f15fc4951da35e5700deb54ecc4e6b64d..cf31456b6950ac51de7c220c65d7f374c63ea781 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -372,15 +372,35 @@ Interpreter::Parse(llvm::StringRef Code) { return IncrParser->Parse(Code); } +static llvm::Expected +createJITTargetMachineBuilder(const std::string &TT) { + if (TT == llvm::sys::getProcessTriple()) + // This fails immediately if the target backend is not registered + return llvm::orc::JITTargetMachineBuilder::detectHost(); + + // If the target backend is not registered, LLJITBuilder::create() will fail + return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT)); +} + +llvm::Expected> +Interpreter::CreateJITBuilder(CompilerInstance &CI) { + auto JTMB = createJITTargetMachineBuilder(CI.getTargetOpts().Triple); + if (!JTMB) + return JTMB.takeError(); + return IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB)); +} + llvm::Error Interpreter::CreateExecutor() { - const clang::TargetInfo &TI = - getCompilerInstance()->getASTContext().getTargetInfo(); if (IncrExecutor) return llvm::make_error("Operation failed. " "Execution engine exists", std::error_code()); + llvm::Expected> JB = + CreateJITBuilder(*getCompilerInstance()); + if (!JB) + return JB.takeError(); llvm::Error Err = llvm::Error::success(); - auto Executor = std::make_unique(*TSCtx, Err, TI); + auto Executor = std::make_unique(*TSCtx, **JB, Err); if (!Err) IncrExecutor = std::move(Executor); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 77d2382ea6d907ae94d1caeefb7b0d0e8756331d..63fe678cbb29e232b49191f82db1ce0023109b56 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -140,6 +140,14 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, SkipUntil(tok::semi); return nullptr; } + if (!ExtraNSs.empty()) { + Diag(ExtraNSs.front().NamespaceLoc, + diag::err_unexpected_qualified_namespace_alias) + << SourceRange(ExtraNSs.front().NamespaceLoc, + ExtraNSs.back().IdentLoc); + SkipUntil(tok::semi); + return nullptr; + } if (attrLoc.isValid()) Diag(attrLoc, diag::err_unexpected_namespace_attributes_alias); if (InlineLoc.isValid()) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index aa754d47a0c43a0620753b427b33314175b5294a..73ea155053d737f31d9500db4737b17a5b23b0c1 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11441,9 +11441,9 @@ static bool CheckMultiVersionFirstFunction(Sema &S, FunctionDecl *FD) { "Function lacks multiversion attribute"); const auto *TA = FD->getAttr(); const auto *TVA = FD->getAttr(); - // Target and target_version only causes MV if it is default, otherwise this - // is a normal function. - if ((TA && !TA->isDefaultVersion()) || (TVA && !TVA->isDefaultVersion())) + // The target attribute only causes MV if this declaration is the default, + // otherwise it is treated as a normal function. + if (TA && !TA->isDefaultVersion()) return false; if ((TA || TVA) && CheckMultiVersionValue(S, FD)) { diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index f6bd85bdc64692e3de882b9006694bdf40e505eb..51450e486eaeb45b8ea3e913d7a0ecde6ac268f9 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6865,6 +6865,32 @@ static bool IsAcceptableNonMemberOperatorCandidate(ASTContext &Context, return false; } +static bool isNonViableMultiVersionOverload(FunctionDecl *FD) { + if (FD->isTargetMultiVersionDefault()) + return false; + + if (!FD->getASTContext().getTargetInfo().getTriple().isAArch64()) + return FD->isTargetMultiVersion(); + + if (!FD->isMultiVersion()) + return false; + + // Among multiple target versions consider either the default, + // or the first non-default in the absence of default version. + unsigned SeenAt = 0; + unsigned I = 0; + bool HasDefault = false; + FD->getASTContext().forEachMultiversionedFunctionVersion( + FD, [&](const FunctionDecl *CurFD) { + if (FD == CurFD) + SeenAt = I; + else if (CurFD->isTargetMultiVersionDefault()) + HasDefault = true; + ++I; + }); + return HasDefault || SeenAt != 0; +} + /// AddOverloadCandidate - Adds the given function to the set of /// candidate functions, using the given function call arguments. If /// @p SuppressUserConversions, then don't allow user-defined @@ -6970,11 +6996,7 @@ void Sema::AddOverloadCandidate( } } - if (Function->isMultiVersion() && - ((Function->hasAttr() && - !Function->getAttr()->isDefaultVersion()) || - (Function->hasAttr() && - !Function->getAttr()->isDefaultVersion()))) { + if (isNonViableMultiVersionOverload(Function)) { Candidate.Viable = false; Candidate.FailureKind = ovl_non_default_multiversion_function; return; @@ -7637,11 +7659,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, return; } - if (Method->isMultiVersion() && - ((Method->hasAttr() && - !Method->getAttr()->isDefaultVersion()) || - (Method->hasAttr() && - !Method->getAttr()->isDefaultVersion()))) { + if (isNonViableMultiVersionOverload(Method)) { Candidate.Viable = false; Candidate.FailureKind = ovl_non_default_multiversion_function; } @@ -8127,11 +8145,7 @@ void Sema::AddConversionCandidate( return; } - if (Conversion->isMultiVersion() && - ((Conversion->hasAttr() && - !Conversion->getAttr()->isDefaultVersion()) || - (Conversion->hasAttr() && - !Conversion->getAttr()->isDefaultVersion()))) { + if (isNonViableMultiVersionOverload(Conversion)) { Candidate.Viable = false; Candidate.FailureKind = ovl_non_default_multiversion_function; } diff --git a/clang/lib/StaticAnalyzer/Checkers/CXXDeleteChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CXXDeleteChecker.cpp index b4dee1e300e886369d43c374d63b72e4aa6d88cb..1b1226a7f1a71d861ce262e572822a24e0a660f1 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CXXDeleteChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CXXDeleteChecker.cpp @@ -220,11 +220,11 @@ CXXDeleteChecker::PtrCastVisitor::VisitNode(const ExplodedNode *N, /*addPosRange=*/true); } -void ento::registerCXXArrayDeleteChecker(CheckerManager &mgr) { +void ento::registerArrayDeleteChecker(CheckerManager &mgr) { mgr.registerChecker(); } -bool ento::shouldRegisterCXXArrayDeleteChecker(const CheckerManager &mgr) { +bool ento::shouldRegisterArrayDeleteChecker(const CheckerManager &mgr) { return true; } diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 03cb7696707fe2f215db6192ee244e4a22784c50..88fb42b6625aa48eb796ad149576dca2c68d7986 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -394,8 +394,10 @@ private: const CallEvent &Call, CheckerContext &C)>; const CallDescriptionMap PreFnMap{ - {{{"getline"}, 3}, &MallocChecker::preGetdelim}, - {{{"getdelim"}, 4}, &MallocChecker::preGetdelim}, + // NOTE: the following CallDescription also matches the C++ standard + // library function std::getline(); the callback will filter it out. + {{CDM::CLibrary, {"getline"}, 3}, &MallocChecker::preGetdelim}, + {{CDM::CLibrary, {"getdelim"}, 4}, &MallocChecker::preGetdelim}, }; const CallDescriptionMap FreeingMemFnMap{ @@ -446,8 +448,11 @@ private: std::bind(&MallocChecker::checkRealloc, _1, _2, _3, false)}, {{{"g_realloc_n"}, 3}, &MallocChecker::checkReallocN}, {{{"g_try_realloc_n"}, 3}, &MallocChecker::checkReallocN}, - {{{"getline"}, 3}, &MallocChecker::checkGetdelim}, - {{{"getdelim"}, 4}, &MallocChecker::checkGetdelim}, + + // NOTE: the following CallDescription also matches the C++ standard + // library function std::getline(); the callback will filter it out. + {{CDM::CLibrary, {"getline"}, 3}, &MallocChecker::checkGetdelim}, + {{CDM::CLibrary, {"getdelim"}, 4}, &MallocChecker::checkGetdelim}, }; bool isMemCall(const CallEvent &Call) const; @@ -1435,13 +1440,21 @@ void MallocChecker::checkGMallocN0(const CallEvent &Call, C.addTransition(State); } +static bool isFromStdNamespace(const CallEvent &Call) { + const Decl *FD = Call.getDecl(); + assert(FD && "a CallDescription cannot match a call without a Decl"); + return FD->isInStdNamespace(); +} + void MallocChecker::preGetdelim(const CallEvent &Call, CheckerContext &C) const { - if (!Call.isGlobalCFunction()) + // Discard calls to the C++ standard library function std::getline(), which + // is completely unrelated to the POSIX getline() that we're checking. + if (isFromStdNamespace(Call)) return; ProgramStateRef State = C.getState(); - const auto LinePtr = getPointeeDefVal(Call.getArgSVal(0), State); + const auto LinePtr = getPointeeVal(Call.getArgSVal(0), State); if (!LinePtr) return; @@ -1458,7 +1471,9 @@ void MallocChecker::preGetdelim(const CallEvent &Call, void MallocChecker::checkGetdelim(const CallEvent &Call, CheckerContext &C) const { - if (!Call.isGlobalCFunction()) + // Discard calls to the C++ standard library function std::getline(), which + // is completely unrelated to the POSIX getline() that we're checking. + if (isFromStdNamespace(Call)) return; ProgramStateRef State = C.getState(); @@ -1470,8 +1485,10 @@ void MallocChecker::checkGetdelim(const CallEvent &Call, SValBuilder &SVB = C.getSValBuilder(); - const auto LinePtr = getPointeeDefVal(Call.getArgSVal(0), State); - const auto Size = getPointeeDefVal(Call.getArgSVal(1), State); + const auto LinePtr = + getPointeeVal(Call.getArgSVal(0), State)->getAs(); + const auto Size = + getPointeeVal(Call.getArgSVal(1), State)->getAs(); if (!LinePtr || !Size || !LinePtr->getAsRegion()) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 10972158f3986232db1dd2d9c0a5a0415a6b9e97..902c42a2799be46da90a4d179743cea8d5c5d5b1 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -1200,10 +1200,25 @@ void StreamChecker::evalGetdelim(const FnDescription *Desc, // Add transition for the successful state. NonLoc RetVal = makeRetVal(C, E.CE).castAs(); - ProgramStateRef StateNotFailed = - State->BindExpr(E.CE, C.getLocationContext(), RetVal); + ProgramStateRef StateNotFailed = E.bindReturnValue(State, C, RetVal); StateNotFailed = E.assumeBinOpNN(StateNotFailed, BO_GE, RetVal, E.getZeroVal(Call)); + + // On success, a buffer is allocated. + auto NewLinePtr = getPointeeVal(Call.getArgSVal(0), State); + if (NewLinePtr && isa(*NewLinePtr)) + StateNotFailed = StateNotFailed->assume( + NewLinePtr->castAs(), true); + + // The buffer size `*n` must be enough to hold the whole line, and + // greater than the return value, since it has to account for '\0'. + SVal SizePtrSval = Call.getArgSVal(1); + auto NVal = getPointeeVal(SizePtrSval, State); + if (NVal && isa(*NVal)) { + StateNotFailed = E.assumeBinOpNN(StateNotFailed, BO_GT, + NVal->castAs(), RetVal); + StateNotFailed = E.bindReturnValue(StateNotFailed, C, RetVal); + } if (!StateNotFailed) return; C.addTransition(StateNotFailed); @@ -1217,6 +1232,10 @@ void StreamChecker::evalGetdelim(const FnDescription *Desc, E.isStreamEof() ? ErrorFEof : ErrorFEof | ErrorFError; StateFailed = E.setStreamState( StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof())); + // On failure, the content of the buffer is undefined. + if (auto NewLinePtr = getPointeeVal(Call.getArgSVal(0), State)) + StateFailed = StateFailed->bindLoc(*NewLinePtr, UndefinedVal(), + C.getLocationContext()); C.addTransition(StateFailed, E.getFailureNoteTag(this, C)); } diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index 19f1ca2dc824c9c61e2904876e0a873efe5854c3..da2d16ca9b5dd74dd5192cb97ad948693052e4b6 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -17,8 +17,10 @@ #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -41,25 +43,38 @@ enum class OpenVariant { namespace { class UnixAPIMisuseChecker - : public Checker, - check::ASTDecl> { + : public Checker> { const BugType BT_open{this, "Improper use of 'open'", categories::UnixAPI}; + const BugType BT_getline{this, "Improper use of getdelim", + categories::UnixAPI}; const BugType BT_pthreadOnce{this, "Improper use of 'pthread_once'", categories::UnixAPI}; + const BugType BT_ArgumentNull{this, "NULL pointer", categories::UnixAPI}; mutable std::optional Val_O_CREAT; + ProgramStateRef + EnsurePtrNotNull(SVal PtrVal, const Expr *PtrExpr, CheckerContext &C, + ProgramStateRef State, const StringRef PtrDescr, + std::optional> BT = + std::nullopt) const; + + ProgramStateRef EnsureGetdelimBufferAndSizeCorrect( + SVal LinePtrPtrSVal, SVal SizePtrSVal, const Expr *LinePtrPtrExpr, + const Expr *SizePtrExpr, CheckerContext &C, ProgramStateRef State) const; + public: void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager &Mgr, BugReporter &BR) const; - void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; + void checkPreCall(const CallEvent &Call, CheckerContext &C) const; - void CheckOpen(CheckerContext &C, const CallExpr *CE) const; - void CheckOpenAt(CheckerContext &C, const CallExpr *CE) const; - void CheckPthreadOnce(CheckerContext &C, const CallExpr *CE) const; + void CheckOpen(CheckerContext &C, const CallEvent &Call) const; + void CheckOpenAt(CheckerContext &C, const CallEvent &Call) const; + void CheckGetDelim(CheckerContext &C, const CallEvent &Call) const; + void CheckPthreadOnce(CheckerContext &C, const CallEvent &Call) const; - void CheckOpenVariant(CheckerContext &C, - const CallExpr *CE, OpenVariant Variant) const; + void CheckOpenVariant(CheckerContext &C, const CallEvent &Call, + OpenVariant Variant) const; void ReportOpenBug(CheckerContext &C, ProgramStateRef State, const char *Msg, SourceRange SR) const; @@ -95,6 +110,30 @@ private: } // end anonymous namespace +ProgramStateRef UnixAPIMisuseChecker::EnsurePtrNotNull( + SVal PtrVal, const Expr *PtrExpr, CheckerContext &C, ProgramStateRef State, + const StringRef PtrDescr, + std::optional> BT) const { + const auto Ptr = PtrVal.getAs(); + if (!Ptr) + return State; + + const auto [PtrNotNull, PtrNull] = State->assume(*Ptr); + if (!PtrNotNull && PtrNull) { + if (ExplodedNode *N = C.generateErrorNode(PtrNull)) { + auto R = std::make_unique( + BT.value_or(std::cref(BT_ArgumentNull)), + (PtrDescr + " pointer might be NULL.").str(), N); + if (PtrExpr) + bugreporter::trackExpressionValue(N, PtrExpr, *R); + C.emitReport(std::move(R)); + } + return nullptr; + } + + return PtrNotNull; +} + void UnixAPIMisuseChecker::checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager &Mgr, BugReporter &) const { @@ -113,9 +152,9 @@ void UnixAPIMisuseChecker::checkASTDecl(const TranslationUnitDecl *TU, // "open" (man 2 open) //===----------------------------------------------------------------------===/ -void UnixAPIMisuseChecker::checkPreStmt(const CallExpr *CE, +void UnixAPIMisuseChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const { - const FunctionDecl *FD = C.getCalleeDecl(CE); + const FunctionDecl *FD = dyn_cast_if_present(Call.getDecl()); if (!FD || FD->getKind() != Decl::Function) return; @@ -130,13 +169,16 @@ void UnixAPIMisuseChecker::checkPreStmt(const CallExpr *CE, return; if (FName == "open") - CheckOpen(C, CE); + CheckOpen(C, Call); else if (FName == "openat") - CheckOpenAt(C, CE); + CheckOpenAt(C, Call); else if (FName == "pthread_once") - CheckPthreadOnce(C, CE); + CheckPthreadOnce(C, Call); + + else if (is_contained({"getdelim", "getline"}, FName)) + CheckGetDelim(C, Call); } void UnixAPIMisuseChecker::ReportOpenBug(CheckerContext &C, ProgramStateRef State, @@ -152,17 +194,17 @@ void UnixAPIMisuseChecker::ReportOpenBug(CheckerContext &C, } void UnixAPIMisuseChecker::CheckOpen(CheckerContext &C, - const CallExpr *CE) const { - CheckOpenVariant(C, CE, OpenVariant::Open); + const CallEvent &Call) const { + CheckOpenVariant(C, Call, OpenVariant::Open); } void UnixAPIMisuseChecker::CheckOpenAt(CheckerContext &C, - const CallExpr *CE) const { - CheckOpenVariant(C, CE, OpenVariant::OpenAt); + const CallEvent &Call) const { + CheckOpenVariant(C, Call, OpenVariant::OpenAt); } void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, - const CallExpr *CE, + const CallEvent &Call, OpenVariant Variant) const { // The index of the argument taking the flags open flags (O_RDONLY, // O_WRONLY, O_CREAT, etc.), @@ -191,11 +233,11 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, ProgramStateRef state = C.getState(); - if (CE->getNumArgs() < MinArgCount) { + if (Call.getNumArgs() < MinArgCount) { // The frontend should issue a warning for this case. Just return. return; - } else if (CE->getNumArgs() == MaxArgCount) { - const Expr *Arg = CE->getArg(CreateModeArgIndex); + } else if (Call.getNumArgs() == MaxArgCount) { + const Expr *Arg = Call.getArgExpr(CreateModeArgIndex); QualType QT = Arg->getType(); if (!QT->isIntegerType()) { SmallString<256> SBuf; @@ -209,15 +251,14 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, Arg->getSourceRange()); return; } - } else if (CE->getNumArgs() > MaxArgCount) { + } else if (Call.getNumArgs() > MaxArgCount) { SmallString<256> SBuf; llvm::raw_svector_ostream OS(SBuf); OS << "Call to '" << VariantName << "' with more than " << MaxArgCount << " arguments"; - ReportOpenBug(C, state, - SBuf.c_str(), - CE->getArg(MaxArgCount)->getSourceRange()); + ReportOpenBug(C, state, SBuf.c_str(), + Call.getArgExpr(MaxArgCount)->getSourceRange()); return; } @@ -226,8 +267,8 @@ 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); + const Expr *oflagsEx = Call.getArgExpr(FlagsArgIndex); + const SVal V = Call.getArgSVal(FlagsArgIndex); 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. @@ -253,7 +294,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, if (!(trueState && !falseState)) return; - if (CE->getNumArgs() < MaxArgCount) { + if (Call.getNumArgs() < MaxArgCount) { SmallString<256> SBuf; llvm::raw_svector_ostream OS(SBuf); OS << "Call to '" << VariantName << "' requires a " @@ -266,23 +307,110 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, } } +//===----------------------------------------------------------------------===// +// getdelim and getline +//===----------------------------------------------------------------------===// + +ProgramStateRef UnixAPIMisuseChecker::EnsureGetdelimBufferAndSizeCorrect( + SVal LinePtrPtrSVal, SVal SizePtrSVal, const Expr *LinePtrPtrExpr, + const Expr *SizePtrExpr, CheckerContext &C, ProgramStateRef State) const { + static constexpr llvm::StringLiteral SizeGreaterThanBufferSize = + "The buffer from the first argument is smaller than the size " + "specified by the second parameter"; + static constexpr llvm::StringLiteral SizeUndef = + "The buffer from the first argument is not NULL, but the size specified " + "by the second parameter is undefined."; + + auto EmitBugReport = [this, &C, SizePtrExpr, LinePtrPtrExpr]( + ProgramStateRef BugState, StringRef ErrMsg) { + if (ExplodedNode *N = C.generateErrorNode(BugState)) { + auto R = std::make_unique(BT_getline, ErrMsg, N); + bugreporter::trackExpressionValue(N, SizePtrExpr, *R); + bugreporter::trackExpressionValue(N, LinePtrPtrExpr, *R); + C.emitReport(std::move(R)); + } + }; + + // We have a pointer to a pointer to the buffer, and a pointer to the size. + // We want what they point at. + auto LinePtrSVal = getPointeeVal(LinePtrPtrSVal, State)->getAs(); + auto NSVal = getPointeeVal(SizePtrSVal, State); + if (!LinePtrSVal || !NSVal || NSVal->isUnknown()) + return nullptr; + + assert(LinePtrPtrExpr && SizePtrExpr); + + const auto [LinePtrNotNull, LinePtrNull] = State->assume(*LinePtrSVal); + if (LinePtrNotNull && !LinePtrNull) { + // If `*lineptr` is not null, but `*n` is undefined, there is UB. + if (NSVal->isUndef()) { + EmitBugReport(LinePtrNotNull, SizeUndef); + return nullptr; + } + + // If it is defined, and known, its size must be less than or equal to + // the buffer size. + auto NDefSVal = NSVal->getAs(); + auto &SVB = C.getSValBuilder(); + auto LineBufSize = + getDynamicExtent(LinePtrNotNull, LinePtrSVal->getAsRegion(), SVB); + auto LineBufSizeGtN = SVB.evalBinOp(LinePtrNotNull, BO_GE, LineBufSize, + *NDefSVal, SVB.getConditionType()) + .getAs(); + if (!LineBufSizeGtN) + return LinePtrNotNull; + if (auto LineBufSizeOk = LinePtrNotNull->assume(*LineBufSizeGtN, true)) + return LineBufSizeOk; + + EmitBugReport(LinePtrNotNull, SizeGreaterThanBufferSize); + return nullptr; + } + return State; +} + +void UnixAPIMisuseChecker::CheckGetDelim(CheckerContext &C, + const CallEvent &Call) const { + ProgramStateRef State = C.getState(); + + // The parameter `n` must not be NULL. + SVal SizePtrSval = Call.getArgSVal(1); + State = EnsurePtrNotNull(SizePtrSval, Call.getArgExpr(1), C, State, "Size"); + if (!State) + return; + + // The parameter `lineptr` must not be NULL. + SVal LinePtrPtrSVal = Call.getArgSVal(0); + State = + EnsurePtrNotNull(LinePtrPtrSVal, Call.getArgExpr(0), C, State, "Line"); + if (!State) + return; + + State = EnsureGetdelimBufferAndSizeCorrect(LinePtrPtrSVal, SizePtrSval, + Call.getArgExpr(0), + Call.getArgExpr(1), C, State); + if (!State) + return; + + C.addTransition(State); +} + //===----------------------------------------------------------------------===// // pthread_once //===----------------------------------------------------------------------===// void UnixAPIMisuseChecker::CheckPthreadOnce(CheckerContext &C, - const CallExpr *CE) const { + const CallEvent &Call) const { // This is similar to 'CheckDispatchOnce' in the MacOSXAPIChecker. // They can possibly be refactored. - if (CE->getNumArgs() < 1) + if (Call.getNumArgs() < 1) return; // Check if the first argument is stack allocated. If so, issue a warning // because that's likely to be bad news. ProgramStateRef state = C.getState(); - const MemRegion *R = C.getSVal(CE->getArg(0)).getAsRegion(); + const MemRegion *R = Call.getArgSVal(0).getAsRegion(); if (!R || !isa(R->getMemorySpace())) return; @@ -304,7 +432,7 @@ void UnixAPIMisuseChecker::CheckPthreadOnce(CheckerContext &C, auto report = std::make_unique(BT_pthreadOnce, os.str(), N); - report->addRange(CE->getArg(0)->getSourceRange()); + report->addRange(Call.getArgExpr(0)->getSourceRange()); C.emitReport(std::move(report)); } diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 3617fdd778e3ca048834dd1d1f62b5ee27888a45..14ca507a16d5503c8d794a34a820e47906696fc8 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -138,7 +138,8 @@ public: public: PathDiagnosticConstruct(const PathDiagnosticConsumer *PDC, const ExplodedNode *ErrorNode, - const PathSensitiveBugReport *R); + const PathSensitiveBugReport *R, + const Decl *AnalysisEntryPoint); /// \returns the location context associated with the current position in the /// bug path. @@ -1323,24 +1324,26 @@ void PathDiagnosticBuilder::generatePathDiagnosticsForNode( } static std::unique_ptr -generateDiagnosticForBasicReport(const BasicBugReport *R) { +generateDiagnosticForBasicReport(const BasicBugReport *R, + const Decl *AnalysisEntryPoint) { const BugType &BT = R->getBugType(); return std::make_unique( BT.getCheckerName(), R->getDeclWithIssue(), BT.getDescription(), R->getDescription(), R->getShortDescription(/*UseFallback=*/false), BT.getCategory(), R->getUniqueingLocation(), R->getUniqueingDecl(), - std::make_unique()); + AnalysisEntryPoint, std::make_unique()); } static std::unique_ptr generateEmptyDiagnosticForReport(const PathSensitiveBugReport *R, - const SourceManager &SM) { + const SourceManager &SM, + const Decl *AnalysisEntryPoint) { const BugType &BT = R->getBugType(); return std::make_unique( BT.getCheckerName(), R->getDeclWithIssue(), BT.getDescription(), R->getDescription(), R->getShortDescription(/*UseFallback=*/false), BT.getCategory(), R->getUniqueingLocation(), R->getUniqueingDecl(), - findExecutedLines(SM, R->getErrorNode())); + AnalysisEntryPoint, findExecutedLines(SM, R->getErrorNode())); } static const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) { @@ -1976,10 +1979,11 @@ static void updateExecutedLinesWithDiagnosticPieces(PathDiagnostic &PD) { PathDiagnosticConstruct::PathDiagnosticConstruct( const PathDiagnosticConsumer *PDC, const ExplodedNode *ErrorNode, - const PathSensitiveBugReport *R) + const PathSensitiveBugReport *R, const Decl *AnalysisEntryPoint) : Consumer(PDC), CurrentNode(ErrorNode), SM(CurrentNode->getCodeDecl().getASTContext().getSourceManager()), - PD(generateEmptyDiagnosticForReport(R, getSourceManager())) { + PD(generateEmptyDiagnosticForReport(R, getSourceManager(), + AnalysisEntryPoint)) { LCM[&PD->getActivePath()] = ErrorNode->getLocationContext(); } @@ -1993,13 +1997,14 @@ PathDiagnosticBuilder::PathDiagnosticBuilder( std::unique_ptr PathDiagnosticBuilder::generate(const PathDiagnosticConsumer *PDC) const { - PathDiagnosticConstruct Construct(PDC, ErrorNode, R); + const Decl *EntryPoint = getBugReporter().getAnalysisEntryPoint(); + PathDiagnosticConstruct Construct(PDC, ErrorNode, R, EntryPoint); const SourceManager &SM = getSourceManager(); const AnalyzerOptions &Opts = getAnalyzerOptions(); if (!PDC->shouldGenerateDiagnostics()) - return generateEmptyDiagnosticForReport(R, getSourceManager()); + return generateEmptyDiagnosticForReport(R, getSourceManager(), EntryPoint); // Construct the final (warning) event for the bug report. auto EndNotes = VisitorsDiagnostics->find(ErrorNode); @@ -3123,6 +3128,16 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) { Pieces.back()->addFixit(I); updateExecutedLinesWithDiagnosticPieces(*PD); + + // If we are debugging, let's have the entry point as the first note. + if (getAnalyzerOptions().AnalyzerDisplayProgress || + getAnalyzerOptions().AnalyzerNoteAnalysisEntryPoints) { + const Decl *EntryPoint = getAnalysisEntryPoint(); + Pieces.push_front(std::make_shared( + PathDiagnosticLocation{EntryPoint->getLocation(), getSourceManager()}, + "[debug] analyzing from " + + AnalysisDeclContext::getFunctionName(EntryPoint))); + } Consumer->HandlePathDiagnostic(std::move(PD)); } } @@ -3211,7 +3226,8 @@ BugReporter::generateDiagnosticForConsumerMap( auto *basicReport = cast(exampleReport); auto Out = std::make_unique(); for (auto *Consumer : consumers) - (*Out)[Consumer] = generateDiagnosticForBasicReport(basicReport); + (*Out)[Consumer] = + generateDiagnosticForBasicReport(basicReport, AnalysisEntryPoint); return Out; } diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp index bc14aea27f6736e8e0c9b3a4344fdaff65d83fb5..0e317ec765ec09d87ca419354994f59ca17a0480 100644 --- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -1408,9 +1408,12 @@ CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State, if (const auto *OpCE = dyn_cast(CE)) { const FunctionDecl *DirectCallee = OpCE->getDirectCallee(); - if (const auto *MD = dyn_cast(DirectCallee)) + if (const auto *MD = dyn_cast(DirectCallee)) { if (MD->isImplicitObjectMemberFunction()) return create(OpCE, State, LCtx, ElemRef); + if (MD->isStatic()) + return create(OpCE, State, LCtx, ElemRef); + } } else if (CE->getCallee()->getType()->isBlockPointerType()) { return create(CE, State, LCtx, ElemRef); diff --git a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp index d6d4cec9dd3d4d01dd5ab2ffb9fbbeab337e4ddb..1a9bff529e9bb124eff2747629b93e52c0535c75 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp @@ -87,9 +87,11 @@ bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD, if (!II) return false; - // Look through 'extern "C"' and anything similar invented in the future. - // If this function is not in TU directly, it is not a C library function. - if (!FD->getDeclContext()->getRedeclContext()->isTranslationUnit()) + // C library functions are either declared directly within a TU (the common + // case) or they are accessed through the namespace `std` (when they are used + // in C++ via headers like ). + const DeclContext *DC = FD->getDeclContext()->getRedeclContext(); + if (!(DC->isTranslationUnit() || DC->isStdNamespace())) return false; // If this function is not externally visible, it is not a C library function. diff --git a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp index 364c87e910b7b51a28c68705dbe8faadc6197cd1..d7137a915b3d3dda7e40afc16ae51a5e2835902b 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp @@ -183,10 +183,9 @@ OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK, } } -std::optional getPointeeDefVal(SVal PtrSVal, - ProgramStateRef State) { +std::optional getPointeeVal(SVal PtrSVal, ProgramStateRef State) { if (const auto *Ptr = PtrSVal.getAsRegion()) { - return State->getSVal(Ptr).getAs(); + return State->getSVal(Ptr); } return std::nullopt; } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 4755b6bfa6dc0ab1cb17108317377ddd5b3592ba..9d3e4fc944fb7b74ee5fe9beabab11f65c02e200 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -846,6 +846,7 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred, const StackFrameContext *CallerSFC = CurLC->getStackFrame(); switch (Call.getKind()) { case CE_Function: + case CE_CXXStaticOperator: case CE_Block: break; case CE_CXXMember: diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index b6ef40595e3c97a5e218516f84d5d325263a7540..03bc40804d73287319326af9a981e8bc8f4331af 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -527,7 +527,8 @@ static void reportAnalyzerFunctionMisuse(const AnalyzerOptions &Opts, void AnalysisConsumer::runAnalysisOnTranslationUnit(ASTContext &C) { BugReporter BR(*Mgr); - TranslationUnitDecl *TU = C.getTranslationUnitDecl(); + const TranslationUnitDecl *TU = C.getTranslationUnitDecl(); + BR.setAnalysisEntryPoint(TU); if (SyntaxCheckTimer) SyntaxCheckTimer->startTimer(); checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR); @@ -675,6 +676,7 @@ void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode, DisplayFunction(D, Mode, IMode); BugReporter BR(*Mgr); + BR.setAnalysisEntryPoint(D); if (Mode & AM_Syntax) { llvm::TimeRecord CheckerStartTime; diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp index 1b750cec41e1cc428b336b9e862595602eb410d7..9b7812a1adb9e32e8ec532d94eabbe494effe142 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -41,24 +41,25 @@ DependencyScanningWorkerFilesystem::readFile(StringRef Filename) { return TentativeEntry(Stat, std::move(Buffer)); } -EntryRef DependencyScanningWorkerFilesystem::scanForDirectivesIfNecessary( - const CachedFileSystemEntry &Entry, StringRef Filename, bool Disable) { - if (Entry.isError() || Entry.isDirectory() || Disable || - !shouldScanForDirectives(Filename)) - return EntryRef(Filename, Entry); +bool DependencyScanningWorkerFilesystem::ensureDirectiveTokensArePopulated( + EntryRef Ref) { + auto &Entry = Ref.Entry; + + if (Entry.isError() || Entry.isDirectory()) + return false; CachedFileContents *Contents = Entry.getCachedContents(); assert(Contents && "contents not initialized"); // Double-checked locking. if (Contents->DepDirectives.load()) - return EntryRef(Filename, Entry); + return true; std::lock_guard GuardLock(Contents->ValueLock); // Double-checked locking. if (Contents->DepDirectives.load()) - return EntryRef(Filename, Entry); + return true; SmallVector Directives; // Scan the file for preprocessor directives that might affect the @@ -69,16 +70,16 @@ EntryRef DependencyScanningWorkerFilesystem::scanForDirectivesIfNecessary( Contents->DepDirectiveTokens.clear(); // FIXME: Propagate the diagnostic if desired by the client. Contents->DepDirectives.store(new std::optional()); - return EntryRef(Filename, Entry); + return false; } // This function performed double-checked locking using `DepDirectives`. // Assigning it must be the last thing this function does, otherwise other - // threads may skip the - // critical section (`DepDirectives != nullptr`), leading to a data race. + // threads may skip the critical section (`DepDirectives != nullptr`), leading + // to a data race. Contents->DepDirectives.store( new std::optional(std::move(Directives))); - return EntryRef(Filename, Entry); + return true; } DependencyScanningFilesystemSharedCache:: @@ -161,34 +162,11 @@ DependencyScanningFilesystemSharedCache::CacheShard:: return *EntriesByFilename.insert({Filename, &Entry}).first->getValue(); } -/// Whitelist file extensions that should be minimized, treating no extension as -/// a source file that should be minimized. -/// -/// This is kinda hacky, it would be better if we knew what kind of file Clang -/// was expecting instead. -static bool shouldScanForDirectivesBasedOnExtension(StringRef Filename) { - StringRef Ext = llvm::sys::path::extension(Filename); - if (Ext.empty()) - return true; // C++ standard library - return llvm::StringSwitch(Ext) - .CasesLower(".c", ".cc", ".cpp", ".c++", ".cxx", true) - .CasesLower(".h", ".hh", ".hpp", ".h++", ".hxx", true) - .CasesLower(".m", ".mm", true) - .CasesLower(".i", ".ii", ".mi", ".mmi", true) - .CasesLower(".def", ".inc", true) - .Default(false); -} - static bool shouldCacheStatFailures(StringRef Filename) { StringRef Ext = llvm::sys::path::extension(Filename); if (Ext.empty()) return false; // This may be the module cache directory. - // Only cache stat failures on files that are not expected to change during - // the build. - StringRef FName = llvm::sys::path::filename(Filename); - if (FName == "module.modulemap" || FName == "module.map") - return true; - return shouldScanForDirectivesBasedOnExtension(Filename); + return true; } DependencyScanningWorkerFilesystem::DependencyScanningWorkerFilesystem( @@ -201,11 +179,6 @@ DependencyScanningWorkerFilesystem::DependencyScanningWorkerFilesystem( updateWorkingDirForCacheLookup(); } -bool DependencyScanningWorkerFilesystem::shouldScanForDirectives( - StringRef Filename) { - return shouldScanForDirectivesBasedOnExtension(Filename); -} - const CachedFileSystemEntry & DependencyScanningWorkerFilesystem::getOrEmplaceSharedEntryForUID( TentativeEntry TEntry) { @@ -259,7 +232,7 @@ DependencyScanningWorkerFilesystem::computeAndStoreResult( llvm::ErrorOr DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry( - StringRef OriginalFilename, bool DisableDirectivesScanning) { + StringRef OriginalFilename) { StringRef FilenameForLookup; SmallString<256> PathBuf; if (llvm::sys::path::is_absolute_gnu(OriginalFilename)) { @@ -276,15 +249,11 @@ DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry( assert(llvm::sys::path::is_absolute_gnu(FilenameForLookup)); if (const auto *Entry = findEntryByFilenameWithWriteThrough(FilenameForLookup)) - return scanForDirectivesIfNecessary(*Entry, OriginalFilename, - DisableDirectivesScanning) - .unwrapError(); + return EntryRef(OriginalFilename, *Entry).unwrapError(); auto MaybeEntry = computeAndStoreResult(OriginalFilename, FilenameForLookup); if (!MaybeEntry) return MaybeEntry.getError(); - return scanForDirectivesIfNecessary(*MaybeEntry, OriginalFilename, - DisableDirectivesScanning) - .unwrapError(); + return EntryRef(OriginalFilename, *MaybeEntry).unwrapError(); } llvm::ErrorOr diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 76f3d950a13b8100f27642dd24be405709d29399..33b43417a6613d8dda6a65d1924960abd86bca11 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -372,7 +372,8 @@ public: -> std::optional> { if (llvm::ErrorOr Entry = LocalDepFS->getOrCreateFileSystemEntry(File.getName())) - return Entry->getDirectiveTokens(); + if (LocalDepFS->ensureDirectiveTokensArePopulated(*Entry)) + return Entry->getDirectiveTokens(); return std::nullopt; }; } diff --git a/clang/test/Analysis/ArrayDelete.cpp b/clang/test/Analysis/ArrayDelete.cpp index 3b8d49552376ed9e1887ae8a408db5e5606cac9e..6887e0a35fb8bd882e3b1c6d38e48056aff44365 100644 --- a/clang/test/Analysis/ArrayDelete.cpp +++ b/clang/test/Analysis/ArrayDelete.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.ArrayDelete -std=c++11 -verify -analyzer-output=text %s +// RUN: %clang_cc1 -analyze -analyzer-checker=cplusplus.ArrayDelete -std=c++11 -verify -analyzer-output=text %s struct Base { virtual ~Base() = default; diff --git a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h index 3ef7af2ea6c6ab449b56c024ae43d990683bd9be..85db68d41a6c8040f229b3179607d2275ef35721 100644 --- a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h +++ b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h @@ -1106,11 +1106,20 @@ using ostream = basic_ostream; extern std::ostream cout; ostream &operator<<(ostream &, const string &); - #if __cplusplus >= 202002L template ostream &operator<<(ostream &, const std::unique_ptr &); #endif + +template +class basic_istream; + +using istream = basic_istream; + +extern std::istream cin; + +istream &getline(istream &, string &, char); +istream &getline(istream &, string &); } // namespace std #ifdef TEST_INLINABLE_ALLOCATORS diff --git a/clang/test/Analysis/analyzer-display-progress.cpp b/clang/test/Analysis/analyzer-display-progress.cpp index dc8e27a8c3b45c70e095fa66a102bf348229ca68..fa1860004d0319680512f5bad60c5471e286e20b 100644 --- a/clang/test/Analysis/analyzer-display-progress.cpp +++ b/clang/test/Analysis/analyzer-display-progress.cpp @@ -1,22 +1,46 @@ -// RUN: %clang_analyze_cc1 -analyzer-display-progress %s 2>&1 | FileCheck %s +// RUN: %clang_analyze_cc1 -verify %s 2>&1 \ +// RUN: -analyzer-display-progress \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-output=text \ +// RUN: | FileCheck %s -void f() {}; -void g() {}; -void h() {} +void clang_analyzer_warnIfReached(); + +// expected-note@+2 {{[debug] analyzing from f()}} +// expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} +void f() { clang_analyzer_warnIfReached(); } + +// expected-note@+2 {{[debug] analyzing from g()}} +// expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} +void g() { clang_analyzer_warnIfReached(); } + +// expected-note@+2 {{[debug] analyzing from h()}} +// expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} +void h() { clang_analyzer_warnIfReached(); } struct SomeStruct { - void f() {} + // expected-note@+2 {{[debug] analyzing from SomeStruct::f()}} + // expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} + void f() { clang_analyzer_warnIfReached(); } }; struct SomeOtherStruct { - void f() {} + // expected-note@+2 {{[debug] analyzing from SomeOtherStruct::f()}} + // expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} + void f() { clang_analyzer_warnIfReached(); } }; namespace ns { struct SomeStruct { - void f(int) {} - void f(float, ::SomeStruct) {} - void f(float, SomeStruct) {} + // expected-note@+2 {{[debug] analyzing from ns::SomeStruct::f(int)}} + // expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} + void f(int) { clang_analyzer_warnIfReached(); } + // expected-note@+2 {{[debug] analyzing from ns::SomeStruct::f(float, ::SomeStruct)}} + // expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} + void f(float, ::SomeStruct) { clang_analyzer_warnIfReached(); } + // expected-note@+2 {{[debug] analyzing from ns::SomeStruct::f(float, SomeStruct)}} + // expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} + void f(float, SomeStruct) { clang_analyzer_warnIfReached(); } }; } diff --git a/clang/test/Analysis/analyzer-display-progress.m b/clang/test/Analysis/analyzer-display-progress.m index 24414f659c39ac7c9b4acc914e051968ebb90bc0..90f223b3486153ff90a6dd0aed5320dc2592ebbb 100644 --- a/clang/test/Analysis/analyzer-display-progress.m +++ b/clang/test/Analysis/analyzer-display-progress.m @@ -1,8 +1,16 @@ -// RUN: %clang_analyze_cc1 -fblocks -analyzer-display-progress %s 2>&1 | FileCheck %s +// RUN: %clang_analyze_cc1 -fblocks -verify %s 2>&1 \ +// RUN: -analyzer-display-progress \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-output=text \ +// RUN: | FileCheck %s #include "Inputs/system-header-simulator-objc.h" -static void f(void) {} +void clang_analyzer_warnIfReached(); + +// expected-note@+2 {{[debug] analyzing from f}} +// expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} +static void f(void) { clang_analyzer_warnIfReached(); } @interface I: NSObject -(void)instanceMethod:(int)arg1 with:(int)arg2; @@ -10,21 +18,26 @@ static void f(void) {} @end @implementation I --(void)instanceMethod:(int)arg1 with:(int)arg2 {} -+(void)classMethod {} +// expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} +-(void)instanceMethod:(int)arg1 with:(int)arg2 { clang_analyzer_warnIfReached(); } + +// expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} ++(void)classMethod { clang_analyzer_warnIfReached(); } @end +// expected-note@+1 3 {{[debug] analyzing from g}} void g(I *i, int x, int y) { - [I classMethod]; - [i instanceMethod: x with: y]; + [I classMethod]; // expected-note {{Calling 'classMethod'}} + [i instanceMethod: x with: y]; // expected-note {{Calling 'instanceMethod:with:'}} void (^block)(void); - block = ^{}; - block(); + // expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} + block = ^{ clang_analyzer_warnIfReached(); }; + block(); // expected-note {{Calling anonymous block}} } // CHECK: analyzer-display-progress.m f // CHECK: analyzer-display-progress.m -[I instanceMethod:with:] // CHECK: analyzer-display-progress.m +[I classMethod] // CHECK: analyzer-display-progress.m g -// CHECK: analyzer-display-progress.m block (line: 22, col: 11) +// CHECK: analyzer-display-progress.m block (line: 35, col: 11) diff --git a/clang/test/Analysis/analyzer-note-analysis-entry-points.cpp b/clang/test/Analysis/analyzer-note-analysis-entry-points.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d321bfae61c9de0ee20151dac7e2e4d78d6935f --- /dev/null +++ b/clang/test/Analysis/analyzer-note-analysis-entry-points.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_analyze_cc1 -verify=common %s \ +// RUN: -analyzer-checker=deadcode.DeadStores,debug.ExprInspection \ +// RUN: -analyzer-note-analysis-entry-points + +// RUN: %clang_analyze_cc1 -verify=common,textout %s \ +// RUN: -analyzer-checker=deadcode.DeadStores,debug.ExprInspection \ +// RUN: -analyzer-note-analysis-entry-points \ +// RUN: -analyzer-output=text + +// Test the actual source locations/ranges of entry point notes. +// RUN: %clang_analyze_cc1 %s \ +// RUN: -analyzer-checker=deadcode.DeadStores,debug.ExprInspection \ +// RUN: -analyzer-note-analysis-entry-points \ +// RUN: -analyzer-output=text 2>&1 \ +// RUN: | FileCheck --strict-whitespace %s + + +void clang_analyzer_warnIfReached(); + +void other() { + // common-warning@+1 {{REACHABLE}} textout-note@+1 {{REACHABLE}} + clang_analyzer_warnIfReached(); +} + +struct SomeOtherStruct { + // CHECK: note: [debug] analyzing from SomeOtherStruct::f() + // CHECK-NEXT: | void f() { + // CHECK-NEXT: | ^ + // textout-note@+1 {{[debug] analyzing from SomeOtherStruct::f()}} + void f() { + other(); // textout-note {{Calling 'other'}} + } +}; + +// CHECK: note: [debug] analyzing from operator""_w(const char *) +// CHECK-NEXT: | unsigned operator ""_w(const char*) { +// CHECK-NEXT: | ^ +// textout-note@+1 {{[debug] analyzing from operator""_w(const char *)}} +unsigned operator ""_w(const char*) { + // common-warning@+1 {{REACHABLE}} textout-note@+1 {{REACHABLE}} + clang_analyzer_warnIfReached(); + return 404; +} + +// textout-note@+1 {{[debug] analyzing from checkASTCodeBodyHasAnalysisEntryPoints()}} +void checkASTCodeBodyHasAnalysisEntryPoints() { + int z = 1; + z = 2; + // common-warning@-1 {{Value stored to 'z' is never read}} + // textout-note@-2 {{Value stored to 'z' is never read}} +} + +void notInvokedLambdaScope() { + // CHECK: note: [debug] analyzing from notInvokedLambdaScope()::(anonymous class)::operator()() + // CHECK-NEXT: | auto notInvokedLambda = []() { + // CHECK-NEXT: | ^ + // textout-note@+1 {{[debug] analyzing from notInvokedLambdaScope()::(anonymous class)::operator()()}} + auto notInvokedLambda = []() { + // common-warning@+1 {{REACHABLE}} textout-note@+1 {{REACHABLE}} + clang_analyzer_warnIfReached(); + }; + (void)notInvokedLambda; // Not invoking the lambda. +} + +// CHECK: note: [debug] analyzing from invokedLambdaScope() +// CHECK-NEXT: | void invokedLambdaScope() { +// CHECK-NEXT: | ^ +// textout-note@+1 {{[debug] analyzing from invokedLambdaScope()}} +void invokedLambdaScope() { + auto invokedLambda = []() { + // common-warning@+1 {{REACHABLE}} textout-note@+1 {{REACHABLE}} + clang_analyzer_warnIfReached(); + }; + invokedLambda(); // textout-note {{Calling 'operator()'}} +} \ No newline at end of file diff --git a/clang/test/Analysis/cxx23-static-operator.cpp b/clang/test/Analysis/cxx23-static-operator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f380bd0dfa42819cac6d349b1851aefbb4f93b62 --- /dev/null +++ b/clang/test/Analysis/cxx23-static-operator.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_analyze_cc1 -std=c++2b -verify %s \ +// RUN: -analyzer-checker=core,debug.ExprInspection + +template void clang_analyzer_dump(T); + +struct Adder { + int data; + static int operator()(int x, int y) { + clang_analyzer_dump(x); // expected-warning {{1}} + clang_analyzer_dump(y); // expected-warning {{2}} + return x + y; + } +}; + +void static_operator_call_inlines() { + Adder s{10}; + clang_analyzer_dump(s(1, 2)); // expected-warning {{3}} +} + +struct DataWithCtor { + int x; + int y; + DataWithCtor(int parm) : x(parm + 10), y(parm + 20) { + clang_analyzer_dump(this); // expected-warning {{&v}} + } +}; + +struct StaticSubscript { + static void operator[](DataWithCtor v) { + clang_analyzer_dump(v.x); // expected-warning {{20}} + clang_analyzer_dump(v.y); // expected-warning {{30}} + } +}; + +void top() { + StaticSubscript s; + s[DataWithCtor{10}]; +} diff --git a/clang/test/Analysis/getline-cpp.cpp b/clang/test/Analysis/getline-cpp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ef9d3186009c7fa4920368f7ab27910562d71acf --- /dev/null +++ b/clang/test/Analysis/getline-cpp.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,debug.ExprInspection -verify %s + +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,alpha.unix,debug.ExprInspection -verify %s +// +// expected-no-diagnostics + +#include "Inputs/system-header-simulator-cxx.h" + +void test_std_getline() { + std::string userid, comment; + // MallocChecker should not confuse the POSIX function getline() and the + // unrelated C++ standard library function std::getline. + std::getline(std::cin, userid, ' '); // no-crash + std::getline(std::cin, comment); // no-crash +} diff --git a/clang/test/Analysis/getline-unixapi.c b/clang/test/Analysis/getline-unixapi.c new file mode 100644 index 0000000000000000000000000000000000000000..86635ed8499793ccf897696e713b7193a1d69b7a --- /dev/null +++ b/clang/test/Analysis/getline-unixapi.c @@ -0,0 +1,322 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,debug.ExprInspection -verify %s + +#include "Inputs/system-header-simulator.h" +#include "Inputs/system-header-simulator-for-malloc.h" +#include "Inputs/system-header-simulator-for-valist.h" + +void clang_analyzer_eval(int); +void clang_analyzer_dump_int(int); +void clang_analyzer_dump_ptr(void*); +void clang_analyzer_warnIfReached(); + +void test_getline_null_lineptr() { + FILE *F1 = tmpfile(); + if (!F1) + return; + + char **buffer = NULL; + size_t n = 0; + getline(buffer, &n, F1); // expected-warning {{Line pointer might be NULL}} + fclose(F1); +} + +void test_getline_null_size() { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + getline(&buffer, NULL, F1); // expected-warning {{Size pointer might be NULL}} + fclose(F1); +} + +void test_getline_null_buffer_size_gt0() { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + size_t n = 8; + getline(&buffer, &n, F1); // ok since posix 2018 + free(buffer); + fclose(F1); +} + +void test_getline_null_buffer_size_gt0_2(size_t n) { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + if (n > 0) { + getline(&buffer, &n, F1); // ok since posix 2018 + } + free(buffer); + fclose(F1); +} + +void test_getline_null_buffer_unknown_size(size_t n) { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + + getline(&buffer, &n, F1); // ok + fclose(F1); + free(buffer); +} + +void test_getline_null_buffer_undef_size() { + FILE *F1 = tmpfile(); + if (!F1) + return; + + char *buffer = NULL; + size_t n; + + getline(&buffer, &n, F1); // ok since posix 2018 + fclose(F1); + free(buffer); +} + +void test_getline_buffer_size_0() { + FILE *F1 = tmpfile(); + if (!F1) + return; + + char *buffer = malloc(10); + size_t n = 0; + if (buffer != NULL) + getline(&buffer, &n, F1); // ok, the buffer is enough for 0 character + fclose(F1); + free(buffer); +} + +void test_getline_buffer_bad_size() { + FILE *F1 = tmpfile(); + if (!F1) + return; + + char *buffer = malloc(10); + size_t n = 100; + if (buffer != NULL) + getline(&buffer, &n, F1); // expected-warning {{The buffer from the first argument is smaller than the size specified by the second parameter}} + fclose(F1); + free(buffer); +} + +void test_getline_buffer_smaller_size() { + FILE *F1 = tmpfile(); + if (!F1) + return; + + char *buffer = malloc(100); + size_t n = 10; + if (buffer != NULL) + getline(&buffer, &n, F1); // ok, there is enough space for 10 characters + fclose(F1); + free(buffer); +} + +void test_getline_buffer_undef_size() { + FILE *F1 = tmpfile(); + if (!F1) + return; + + char *buffer = malloc(100); + size_t n; + if (buffer != NULL) + getline(&buffer, &n, F1); // expected-warning {{The buffer from the first argument is not NULL, but the size specified by the second parameter is undefined}} + fclose(F1); + free(buffer); +} + + +void test_getline_null_buffer() { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + size_t n = 0; + ssize_t r = getline(&buffer, &n, F1); + // getline returns -1 on failure, number of char reads on success (>= 0) + if (r < -1) { + clang_analyzer_warnIfReached(); // must not happen + } else { + // The buffer could be allocated both on failure and success + clang_analyzer_dump_int(n); // expected-warning {{conj_$}} + clang_analyzer_dump_ptr(buffer); // expected-warning {{conj_$}} + } + free(buffer); + fclose(F1); +} + +void test_getdelim_null_size() { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + getdelim(&buffer, NULL, ',', F1); // expected-warning {{Size pointer might be NULL}} + fclose(F1); +} + +void test_getdelim_null_buffer_size_gt0() { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + size_t n = 8; + getdelim(&buffer, &n, ';', F1); // ok since posix 2018 + free(buffer); + fclose(F1); +} + +void test_getdelim_null_buffer_size_gt0_2(size_t n) { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + if (n > 0) { + getdelim(&buffer, &n, ' ', F1); // ok since posix 2018 + } + free(buffer); + fclose(F1); +} + +void test_getdelim_null_buffer_unknown_size(size_t n) { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + getdelim(&buffer, &n, '-', F1); // ok + fclose(F1); + free(buffer); +} + +void test_getdelim_null_buffer() { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + size_t n = 0; + ssize_t r = getdelim(&buffer, &n, '\r', F1); + // getdelim returns -1 on failure, number of char reads on success (>= 0) + if (r < -1) { + clang_analyzer_warnIfReached(); // must not happen + } + else { + // The buffer could be allocated both on failure and success + clang_analyzer_dump_int(n); // expected-warning {{conj_$}} + clang_analyzer_dump_ptr(buffer); // expected-warning {{conj_$}} + } + free(buffer); + fclose(F1); +} + +void test_getline_while() { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + char *line = NULL; + size_t len = 0; + ssize_t read; + + while ((read = getline(&line, &len, file)) != -1) { + printf("%s\n", line); + } + + free(line); + fclose(file); +} + +void test_getline_return_check() { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + char *line = NULL; + size_t len = 0; + ssize_t r = getline(&line, &len, file); + + if (r != -1) { + if (line[0] == '\0') {} // ok + } + free(line); + fclose(file); +} + +void test_getline_clear_eof() { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + size_t n = 10; + char *buffer = malloc(n); + ssize_t read = fread(buffer, n, 1, file); + if (feof(file)) { + clearerr(file); + getline(&buffer, &n, file); // ok + } + fclose(file); + free(buffer); +} + +void test_getline_not_null(char **buffer, size_t *size) { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + getline(buffer, size, file); + fclose(file); + + if (size == NULL || buffer == NULL) { + clang_analyzer_warnIfReached(); // must not happen + } +} + +void test_getline_size_constraint(size_t size) { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + size_t old_size = size; + char *buffer = malloc(10); + if (buffer != NULL) { + ssize_t r = getline(&buffer, &size, file); + if (r >= 0) { + // Since buffer has a size of 10, old_size must be less than or equal to 10. + // Otherwise, there would be UB. + clang_analyzer_eval(old_size <= 10); // expected-warning{{TRUE}} + } + } + fclose(file); + free(buffer); +} + +void test_getline_negative_buffer() { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + char *buffer = NULL; + size_t n = -1; + getline(&buffer, &n, file); // ok since posix 2018 + free(buffer); + fclose(file); +} + +void test_getline_negative_buffer_2(char *buffer) { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + size_t n = -1; + (void)getline(&buffer, &n, file); // ok + free(buffer); + fclose(file); +} diff --git a/clang/test/Analysis/stream.c b/clang/test/Analysis/stream.c index 7ba27740a93796a8e89066395a85a2bbb55afe7e..ba5e66a4102e3c869a601d66362dc7a718206ffc 100644 --- a/clang/test/Analysis/stream.c +++ b/clang/test/Analysis/stream.c @@ -4,6 +4,7 @@ // RUN: %clang_analyze_cc1 -triple=hexagon -analyzer-checker=core,alpha.unix.Stream,debug.ExprInspection -verify %s #include "Inputs/system-header-simulator.h" +#include "Inputs/system-header-simulator-for-malloc.h" #include "Inputs/system-header-simulator-for-valist.h" void clang_analyzer_eval(int); @@ -376,3 +377,75 @@ void fflush_on_open_failed_stream(void) { } fclose(F); } + +void getline_null_file() { + char *buffer = NULL; + size_t n = 0; + getline(&buffer, &n, NULL); // expected-warning {{Stream pointer might be NULL}} +} + +void getdelim_null_file() { + char *buffer = NULL; + size_t n = 0; + getdelim(&buffer, &n, '\n', NULL); // expected-warning {{Stream pointer might be NULL}} +} + +void getline_buffer_on_error() { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + char *line = NULL; + size_t len = 0; + if (getline(&line, &len, file) == -1) { + if (line[0] == '\0') {} // expected-warning {{The left operand of '==' is a garbage value}} + } else { + if (line[0] == '\0') {} // no warning + } + + free(line); + fclose(file); +} + +void getline_ret_value() { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + size_t n = 0; + char *buffer = NULL; + ssize_t r = getline(&buffer, &n, file); + + if (r > -1) { + // The return value does *not* include the terminating null byte. + // The buffer must be large enough to include it. + clang_analyzer_eval(n > r); // expected-warning{{TRUE}} + clang_analyzer_eval(buffer != NULL); // expected-warning{{TRUE}} + } + + fclose(file); + free(buffer); +} + + +void getline_buffer_size_negative() { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + size_t n = -1; + clang_analyzer_eval((ssize_t)n >= 0); // expected-warning{{FALSE}} + char *buffer = NULL; + ssize_t r = getline(&buffer, &n, file); + + if (r > -1) { + clang_analyzer_eval((ssize_t)n > r); // expected-warning{{TRUE}} + clang_analyzer_eval(buffer != NULL); // expected-warning{{TRUE}} + } + + free(buffer); + fclose(file); +} diff --git a/clang/test/C/C11/n1282.c b/clang/test/C/C11/n1282.c new file mode 100644 index 0000000000000000000000000000000000000000..ed952790c883338fdf4479e9d127c91e856c0ba9 --- /dev/null +++ b/clang/test/C/C11/n1282.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify -Wunsequenced -Wno-unused-value %s + +/* WG14 N1282: Yes + * Clarification of Expressions + */ + +int g; + +int f(int i) { + g = i; + return 0; +} + +int main(void) { + int x; + x = (10, g = 1, 20) + (30, g = 2, 40); /* Line A */ // expected-warning {{multiple unsequenced modifications to 'g'}} + x = (10, f(1), 20) + (30, f(2), 40); /* Line B */ + x = (g = 1) + (g = 2); /* Line C */ // expected-warning {{multiple unsequenced modifications to 'g'}} + return 0; +} diff --git a/clang/test/C/C11/n1365.c b/clang/test/C/C11/n1365.c new file mode 100644 index 0000000000000000000000000000000000000000..d60bb546b29a71d34da9d2830c15a5cfbf9bfe91 --- /dev/null +++ b/clang/test/C/C11/n1365.c @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -ast-dump %s | FileCheck %s + +/* WG14 N1365: Clang 16 + * Constant expressions + */ + +// Note: we don't allow you to expand __FLT_EVAL_METHOD__ in the presence of a +// pragma that changes its value. However, we can test that we have the correct +// constant expression behavior by testing that the AST has the correct implicit +// casts, which also specify that the cast was inserted due to an evaluation +// method requirement. +void func(void) { + { + #pragma clang fp eval_method(double) + _Static_assert(123.0F * 2.0F == 246.0F, ""); + // CHECK: StaticAssertDecl + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Bool' + // CHECK-NEXT: BinaryOperator {{.*}} 'int' '==' + // CHECK-NEXT: BinaryOperator {{.*}} 'double' '*' FPEvalMethod=1 + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' FPEvalMethod=1 + // CHECK-NEXT: FloatingLiteral + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' FPEvalMethod=1 + // CHECK-NEXT: FloatingLiteral + + // Ensure that a cast removes the extra precision. + _Static_assert(123.0F * 2.0F == 246.0F, ""); + // CHECK: StaticAssertDecl + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Bool' + // CHECK-NEXT: BinaryOperator {{.*}} 'int' '==' + // CHECK-NEXT: BinaryOperator {{.*}} 'double' '*' FPEvalMethod=1 + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' FPEvalMethod=1 + // CHECK-NEXT: FloatingLiteral + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' FPEvalMethod=1 + // CHECK-NEXT: FloatingLiteral + } + + { + #pragma clang fp eval_method(extended) + _Static_assert(123.0F * 2.0F == 246.0F, ""); + // CHECK: StaticAssertDecl + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Bool' + // CHECK-NEXT: BinaryOperator {{.*}} 'int' '==' + // CHECK-NEXT: BinaryOperator {{.*}} 'long double' '*' FPEvalMethod=2 + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'long double' FPEvalMethod=2 + // CHECK-NEXT: FloatingLiteral + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'long double' FPEvalMethod=2 + // CHECK-NEXT: FloatingLiteral + } + + { + #pragma clang fp eval_method(source) + _Static_assert(123.0F * 2.0F == 246.0F, ""); + // CHECK: StaticAssertDecl + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Bool' + // CHECK-NEXT: BinaryOperator {{.*}} 'int' '==' + // CHECK-NEXT: BinaryOperator {{.*}} 'float' '*' FPEvalMethod=0 + // CHECK-NEXT: FloatingLiteral + // CHECK-NEXT: FloatingLiteral + } +} diff --git a/clang/test/C/C99/block-scopes.c b/clang/test/C/C99/block-scopes.c new file mode 100644 index 0000000000000000000000000000000000000000..589047df3e52bcbf135fde88c045231a032d6196 --- /dev/null +++ b/clang/test/C/C99/block-scopes.c @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c89 -verify %s +// RUN: %clang_cc1 -std=c99 -verify %s +// RUN: %clang_cc1 -std=c11 -verify %s +// RUN: %clang_cc1 -std=c17 -verify %s +// RUN: %clang_cc1 -std=c23 -verify %s + +// expected-no-diagnostics + +/* WG14 ???: yes + * new block scopes for selection and iteration statements + * + * This is referenced in the C99 front matter as new changes to C99, but it is + * not clear which document number introduced the changes. It's possible this + * is WG14 N759, based on discussion in the C99 rationale document that claims + * these changes were made in response to surprising issues with the lifetime + * of compound literals in compound statements vs non-compound statements. + */ + +enum {a, b}; +void different(void) { + if (sizeof(enum {b, a}) != sizeof(int)) + _Static_assert(a == 1, ""); + /* In C89, the 'b' found here would have been from the enum declaration in + * the controlling expression of the selection statement, not from the global + * declaration. In C99 and later, that enumeration is scoped to the 'if' + * statement and the global declaration is what's found. + */ + #if __STDC_VERSION__ >= 199901L + _Static_assert(b == 1, ""); + #else + _Static_assert(b == 0, ""); + #endif +} + diff --git a/clang/test/C/C99/n696.c b/clang/test/C/C99/n696.c new file mode 100644 index 0000000000000000000000000000000000000000..4499c6e42226b547568402f528d8b951513ff0fe --- /dev/null +++ b/clang/test/C/C99/n696.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple x86_64 -verify %s + +/* WG14 N696: yes + * Standard pragmas - improved wording + * + * NB: this also covers N631 which changed these features into pragmas rather + * than macros. + */ + +// Verify that we do not expand macros in STDC pragmas. If we expanded them, +// this code would issue diagnostics. +#define ON 12 +#pragma STDC FENV_ACCESS ON +#pragma STDC CX_LIMITED_RANGE ON +#pragma STDC FP_CONTRACT ON + +// If we expanded macros, this code would not issue diagnostics. +#define BLERP OFF +#pragma STDC FENV_ACCESS BLERP // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}} +#pragma STDC CX_LIMITED_RANGE BLERP // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}} +#pragma STDC FP_CONTRACT BLERP // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}} + diff --git a/clang/test/C/drs/dr0xx.c b/clang/test/C/drs/dr0xx.c index c93cfb63d604cfaf77af8b58bc7cbf494e115188..36de32a93da95d51123d0f60746061a7440b5460 100644 --- a/clang/test/C/drs/dr0xx.c +++ b/clang/test/C/drs/dr0xx.c @@ -73,6 +73,10 @@ * WG14 DR085: yes * Returning from main * + * WG14 DR087: yes + * Order of evaluation + * Note: this DR is covered by C/C11/n1282.c + * * WG14 DR086: yes * Object-like macros in system headers * diff --git a/clang/test/C/drs/dr290.c b/clang/test/C/drs/dr290.c new file mode 100644 index 0000000000000000000000000000000000000000..3a6fd1d0dab6f69fa04e6552f6fca21ecfe2d9c9 --- /dev/null +++ b/clang/test/C/drs/dr290.c @@ -0,0 +1,20 @@ +/* RUN: %clang_cc1 -fsyntax-only -ast-dump %s | FileCheck %s + */ + +/* WG14 DR290: no + * FLT_EVAL_METHOD and extra precision and/or range + * + * We retain an implicit conversion based on the float eval method being used + * instead of dropping it due to the explicit cast. See GH86304 and C23 6.5.5p7. + */ + +#pragma clang fp eval_method(double) +_Static_assert((float)(123.0F * 2.0F) == (float)246.0F, ""); + +// CHECK: StaticAssertDecl +// CHECK-NEXT: ImplicitCastExpr {{.*}} '_Bool' +// CHECK-NEXT: BinaryOperator {{.*}} 'int' '==' +// NB: the following implicit cast is incorrect. +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' FPEvalMethod=1 +// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' FPEvalMethod=1 + diff --git a/clang/test/ClangScanDeps/modules-extension.c b/clang/test/ClangScanDeps/modules-extension.c new file mode 100644 index 0000000000000000000000000000000000000000..0f27f608440f4593effb010ebceef768e749544a --- /dev/null +++ b/clang/test/ClangScanDeps/modules-extension.c @@ -0,0 +1,33 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t + +// This test checks that source files with uncommon extensions still undergo +// dependency directives scan. If header.pch would not and b.h would, the scan +// would fail when parsing `void function(B)` and not knowing the symbol B. + +//--- module.modulemap +module __PCH { header "header.pch" } +module B { header "b.h" } + +//--- header.pch +#include "b.h" +void function(B); + +//--- b.h +typedef int B; + +//--- tu.c +int main() { + function(0); + return 0; +} + +//--- cdb.json.in +[{ + "directory": "DIR", + "file": "DIR/tu.c", + "command": "clang -c DIR/tu.c -fmodules -fmodules-cache-path=DIR/cache -fimplicit-module-maps -include DIR/header.pch" +}] + +// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.in > %t/cdb.json +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full > %t/deps.json diff --git a/clang/test/CodeGen/attr-counted-by-debug-info.c b/clang/test/CodeGen/attr-counted-by-debug-info.c new file mode 100644 index 0000000000000000000000000000000000000000..a6c2b1382b796bffa1dad5f0dae61eef41ec3443 --- /dev/null +++ b/clang/test/CodeGen/attr-counted-by-debug-info.c @@ -0,0 +1,18 @@ +// RUN: %clang -emit-llvm -DCOUNTED_BY -S -g %s -o - | FileCheck %s +// RUN: %clang -emit-llvm -S -g %s -o - | FileCheck %s + +#ifdef COUNTED_BY +#define __counted_by(member) __attribute__((__counted_by__(member))) +#else +#define __counted_by(member) +#endif + +struct { + int num_counters; + long value[] __counted_by(num_counters); +} agent_send_response_port_num; + +// CHECK: !DICompositeType(tag: DW_TAG_array_type, baseType: ![[BT:.*]], elements: ![[ELEMENTS:.*]]) +// CHECK: ![[BT]] = !DIBasicType(name: "long", size: {{.*}}, encoding: DW_ATE_signed) +// CHECK: ![[ELEMENTS]] = !{![[COUNT:.*]]} +// CHECK: ![[COUNT]] = !DISubrange(count: -1) \ No newline at end of file diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c index 25129605e76ce4ea5f0ba1877b911f152149adb6..dd4cbbf5a8986084c73f2108bfc1e21029026b44 100644 --- a/clang/test/CodeGen/attr-target-version.c +++ b/clang/test/CodeGen/attr-target-version.c @@ -109,21 +109,47 @@ int unused_with_implicit_default_def(void) { return 1; } int unused_with_implicit_forward_default_def(void) { return 0; } __attribute__((target_version("lse"))) int unused_with_implicit_forward_default_def(void) { return 1; } -// This should generate a normal function. +// This should generate a target version despite the default not being declared. __attribute__((target_version("rdm"))) int unused_without_default(void) { return 0; } +// These shouldn't generate anything. +int unused_version_declarations(void); +__attribute__((target_version("jscvt"))) int unused_version_declarations(void); +__attribute__((target_version("rdma"))) int unused_version_declarations(void); + +// These should generate the default (mangled) version and the resolver. +int default_def_with_version_decls(void) { return 0; } +__attribute__((target_version("jscvt"))) int default_def_with_version_decls(void); +__attribute__((target_version("rdma"))) int default_def_with_version_decls(void); + +// The following is guarded because in NOFMV we get errors for calling undeclared functions. +#ifdef __HAVE_FUNCTION_MULTI_VERSIONING +// This should generate a default declaration, two target versions and the resolver. +__attribute__((target_version("jscvt"))) int used_def_without_default_decl(void) { return 1; } +__attribute__((target_version("rdma"))) int used_def_without_default_decl(void) { return 2; } + +// This should generate a default declaration and the resolver. +__attribute__((target_version("jscvt"))) int used_decl_without_default_decl(void); +__attribute__((target_version("rdma"))) int used_decl_without_default_decl(void); + +int caller(void) { return used_def_without_default_decl() + used_decl_without_default_decl(); } +#endif + //. // CHECK: @__aarch64_cpu_features = external dso_local global { i64 } // CHECK: @fmv.ifunc = weak_odr alias i32 (), ptr @fmv // CHECK: @fmv_one.ifunc = weak_odr alias i32 (), ptr @fmv_one // CHECK: @fmv_two.ifunc = weak_odr alias i32 (), ptr @fmv_two // CHECK: @fmv_e.ifunc = weak_odr alias i32 (), ptr @fmv_e +// CHECK: @fmv_d.ifunc = internal alias i32 (), ptr @fmv_d // CHECK: @fmv_c.ifunc = weak_odr alias void (), ptr @fmv_c // CHECK: @fmv_inline.ifunc = weak_odr alias i32 (), ptr @fmv_inline -// CHECK: @fmv_d.ifunc = internal alias i32 (), ptr @fmv_d // CHECK: @unused_with_default_def.ifunc = weak_odr alias i32 (), ptr @unused_with_default_def // CHECK: @unused_with_implicit_default_def.ifunc = weak_odr alias i32 (), ptr @unused_with_implicit_default_def // CHECK: @unused_with_implicit_forward_default_def.ifunc = weak_odr alias i32 (), ptr @unused_with_implicit_forward_default_def +// CHECK: @default_def_with_version_decls.ifunc = weak_odr alias i32 (), ptr @default_def_with_version_decls +// CHECK: @used_def_without_default_decl.ifunc = weak_odr alias i32 (), ptr @used_def_without_default_decl +// CHECK: @used_decl_without_default_decl.ifunc = weak_odr alias i32 (), ptr @used_decl_without_default_decl // CHECK: @fmv = weak_odr ifunc i32 (), ptr @fmv.resolver // CHECK: @fmv_one = weak_odr ifunc i32 (), ptr @fmv_one.resolver // CHECK: @fmv_two = weak_odr ifunc i32 (), ptr @fmv_two.resolver @@ -131,97 +157,121 @@ __attribute__((target_version("rdm"))) int unused_without_default(void) { return // CHECK: @fmv_e = weak_odr ifunc i32 (), ptr @fmv_e.resolver // CHECK: @fmv_d = internal ifunc i32 (), ptr @fmv_d.resolver // CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver +// CHECK: @used_def_without_default_decl = weak_odr ifunc i32 (), ptr @used_def_without_default_decl.resolver +// CHECK: @used_decl_without_default_decl = weak_odr ifunc i32 (), ptr @used_decl_without_default_decl.resolver // CHECK: @unused_with_default_def = weak_odr ifunc i32 (), ptr @unused_with_default_def.resolver // CHECK: @unused_with_implicit_default_def = weak_odr ifunc i32 (), ptr @unused_with_implicit_default_def.resolver // CHECK: @unused_with_implicit_forward_default_def = weak_odr ifunc i32 (), ptr @unused_with_implicit_forward_default_def.resolver +// CHECK: @default_def_with_version_decls = weak_odr ifunc i32 (), ptr @default_def_with_version_decls.resolver //. // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv._Mflagm2Msme-i16i64 +// CHECK-LABEL: define {{[^@]+}}@fmv._MflagmMfp16fmlMrng // CHECK-SAME: () #[[ATTR0:[0-9]+]] { // CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv._Mflagm2Msme-i16i64 +// CHECK-SAME: () #[[ATTR1:[0-9]+]] { +// CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv._MlseMsha2 -// CHECK-SAME: () #[[ATTR1:[0-9]+]] { +// CHECK-SAME: () #[[ATTR2:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 3 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv._MdotprodMls64_accdata -// CHECK-SAME: () #[[ATTR2:[0-9]+]] { +// CHECK-SAME: () #[[ATTR3:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 4 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv._Mfp16fmlMmemtag -// CHECK-SAME: () #[[ATTR3:[0-9]+]] { +// CHECK-SAME: () #[[ATTR4:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 5 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv._MaesMfp -// CHECK-SAME: () #[[ATTR4:[0-9]+]] { +// CHECK-SAME: () #[[ATTR5:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 6 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv._McrcMls64_v -// CHECK-SAME: () #[[ATTR5:[0-9]+]] { +// CHECK-SAME: () #[[ATTR6:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 7 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv._Mbti -// CHECK-SAME: () #[[ATTR6:[0-9]+]] { +// CHECK-SAME: () #[[ATTR7:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 8 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv._Msme2 -// CHECK-SAME: () #[[ATTR7:[0-9]+]] { +// CHECK-SAME: () #[[ATTR8:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 9 // // // CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_one._Mls64Msimd +// CHECK-SAME: () #[[ATTR5]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_one._Mdpb -// CHECK-SAME: () #[[ATTR8:[0-9]+]] { +// CHECK-SAME: () #[[ATTR10:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp +// CHECK-SAME: () #[[ATTR5]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_two._Msimd -// CHECK-SAME: () #[[ATTR4]] { +// CHECK-SAME: () #[[ATTR5]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_two._Mdgh -// CHECK-SAME: () #[[ATTR9:[0-9]+]] { +// CHECK-SAME: () #[[ATTR11:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 3 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp16Msimd -// CHECK-SAME: () #[[ATTR10:[0-9]+]] { +// CHECK-SAME: () #[[ATTR12:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 4 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@foo -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv() // CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_one() @@ -371,35 +421,49 @@ __attribute__((target_version("rdm"))) int unused_without_default(void) { return // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_e.default -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 20 // // // CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_d._Msb +// CHECK-SAME: () #[[ATTR13:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 0 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_d.default +// CHECK-SAME: () #[[ATTR11]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_default -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 111 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret void // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_c.default -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret void // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@goo -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv_inline() // CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_e() @@ -587,7 +651,7 @@ __attribute__((target_version("rdm"))) int unused_without_default(void) { return // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@recur -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: call void @reca() // CHECK-NEXT: ret void @@ -595,7 +659,7 @@ __attribute__((target_version("rdm"))) int unused_without_default(void) { return // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@main -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4 @@ -606,7 +670,7 @@ __attribute__((target_version("rdm"))) int unused_without_default(void) { return // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@hoo -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[FP1:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[FP2:%.*]] = alloca ptr, align 8 @@ -623,228 +687,268 @@ __attribute__((target_version("rdm"))) int unused_without_default(void) { return // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@unused_with_forward_default_decl._Mmops -// CHECK-SAME: () #[[ATTR12:[0-9]+]] { +// CHECK-SAME: () #[[ATTR14:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_extern_forward_default_decl._Mdotprod -// CHECK-SAME: () #[[ATTR13:[0-9]+]] { +// CHECK-SAME: () #[[ATTR15:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@unused_with_default_def.default -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_default_decl._Maes +// CHECK-SAME: () #[[ATTR5]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 +// CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_default_def.default -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_default_def._Msve +// CHECK-SAME: () #[[ATTR16:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 0 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@unused_with_default_def.default +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def.default -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_default_def._Mfp16 +// CHECK-SAME: () #[[ATTR12]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def._Mlse -// CHECK-SAME: () #[[ATTR14:[0-9]+]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_default_def.default +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv._MflagmMfp16fmlMrng -// CHECK-SAME: () #[[ATTR15:[0-9]+]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def.default +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 +// CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_one._Mls64Msimd -// CHECK-SAME: () #[[ATTR4]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def._Mlse +// CHECK-SAME: () #[[ATTR17:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp -// CHECK-SAME: () #[[ATTR4]] { +// CHECK-LABEL: define {{[^@]+}}@unused_without_default._Mrdm +// CHECK-SAME: () #[[ATTR18:[0-9]+]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 +// CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@unused_with_default_decl._Maes -// CHECK-SAME: () #[[ATTR4]] { +// CHECK-LABEL: define {{[^@]+}}@default_def_with_version_decls.default +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@unused_with_default_def._Msve -// CHECK-SAME: () #[[ATTR16:[0-9]+]] { +// CHECK-LABEL: define {{[^@]+}}@used_def_without_default_decl._Mjscvt +// CHECK-SAME: () #[[ATTR21:[0-9]+]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 0 +// CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_default_def._Mfp16 -// CHECK-SAME: () #[[ATTR10]] { +// CHECK-LABEL: define {{[^@]+}}@used_def_without_default_decl._Mrdm +// CHECK-SAME: () #[[ATTR18]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 0 +// CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@unused_without_default -// CHECK-SAME: () #[[ATTR17:[0-9]+]] { +// CHECK-LABEL: define {{[^@]+}}@caller +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 0 +// CHECK-NEXT: [[CALL:%.*]] = call i32 @used_def_without_default_decl() +// CHECK-NEXT: [[CALL1:%.*]] = call i32 @used_decl_without_default_decl() +// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]] +// CHECK-NEXT: ret i32 [[ADD]] +// +// +// CHECK-LABEL: define {{[^@]+}}@used_def_without_default_decl.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1048576 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1048576 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @used_def_without_default_decl._Mjscvt +// CHECK: resolver_else: +// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 64 +// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 64 +// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] +// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] +// CHECK: resolver_return1: +// CHECK-NEXT: ret ptr @used_def_without_default_decl._Mrdm +// CHECK: resolver_else2: +// CHECK-NEXT: ret ptr @used_def_without_default_decl.default +// +// +// CHECK-LABEL: define {{[^@]+}}@used_decl_without_default_decl.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1048576 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1048576 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @used_decl_without_default_decl._Mjscvt +// CHECK: resolver_else: +// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 64 +// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 64 +// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] +// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] +// CHECK: resolver_return1: +// CHECK-NEXT: ret ptr @used_decl_without_default_decl._Mrdm +// CHECK: resolver_else2: +// CHECK-NEXT: ret ptr @used_decl_without_default_decl.default // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mf64mmMpmullMsha1 -// CHECK-SAME: () #[[ATTR18:[0-9]+]] { +// CHECK-SAME: () #[[ATTR22:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfcmaMfp16MrdmMsme -// CHECK-SAME: () #[[ATTR19:[0-9]+]] { +// CHECK-SAME: () #[[ATTR23:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mf32mmMi8mmMsha3 -// CHECK-SAME: () #[[ATTR20:[0-9]+]] { +// CHECK-SAME: () #[[ATTR24:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 12 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MditMsve-ebf16 -// CHECK-SAME: () #[[ATTR21:[0-9]+]] { +// CHECK-SAME: () #[[ATTR25:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 8 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MdpbMrcpc2 -// CHECK-SAME: () #[[ATTR22:[0-9]+]] { +// CHECK-SAME: () #[[ATTR26:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 6 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mdpb2Mjscvt -// CHECK-SAME: () #[[ATTR23:[0-9]+]] { +// CHECK-SAME: () #[[ATTR27:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 7 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfrinttsMrcpc -// CHECK-SAME: () #[[ATTR24:[0-9]+]] { +// CHECK-SAME: () #[[ATTR28:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 3 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MsveMsve-bf16 -// CHECK-SAME: () #[[ATTR25:[0-9]+]] { +// CHECK-SAME: () #[[ATTR29:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 4 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msve2-aesMsve2-sha3 -// CHECK-SAME: () #[[ATTR26:[0-9]+]] { +// CHECK-SAME: () #[[ATTR30:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 5 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msve2Msve2-bitpermMsve2-pmull128 -// CHECK-SAME: () #[[ATTR27:[0-9]+]] { +// CHECK-SAME: () #[[ATTR31:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 9 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mmemtag2Msve2-sm4 -// CHECK-SAME: () #[[ATTR28:[0-9]+]] { +// CHECK-SAME: () #[[ATTR32:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 10 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mmemtag3MmopsMrcpc3 -// CHECK-SAME: () #[[ATTR29:[0-9]+]] { +// CHECK-SAME: () #[[ATTR33:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 11 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MaesMdotprod -// CHECK-SAME: () #[[ATTR13]] { +// CHECK-SAME: () #[[ATTR15]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 13 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mfp16fmlMsimd -// CHECK-SAME: () #[[ATTR3]] { +// CHECK-SAME: () #[[ATTR4]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 14 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfpMsm4 -// CHECK-SAME: () #[[ATTR30:[0-9]+]] { +// CHECK-SAME: () #[[ATTR34:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 15 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MlseMrdm -// CHECK-SAME: () #[[ATTR31:[0-9]+]] { +// CHECK-SAME: () #[[ATTR35:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 16 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline.default -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 3 // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_d._Msb -// CHECK-SAME: () #[[ATTR32:[0-9]+]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 0 -// -// -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_d.default -// CHECK-SAME: () #[[ATTR9]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 -// -// // CHECK-LABEL: define {{[^@]+}}@unused_with_default_def.resolver() comdat { // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -887,6 +991,28 @@ __attribute__((target_version("rdm"))) int unused_without_default(void) { return // CHECK-NEXT: ret ptr @unused_with_implicit_forward_default_def.default // // +// CHECK-LABEL: define {{[^@]+}}@default_def_with_version_decls.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1048576 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1048576 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @default_def_with_version_decls._Mjscvt +// CHECK: resolver_else: +// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 64 +// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 64 +// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] +// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] +// CHECK: resolver_return1: +// CHECK-NEXT: ret ptr @default_def_with_version_decls._Mrdm +// CHECK: resolver_else2: +// CHECK-NEXT: ret ptr @default_def_with_version_decls.default +// +// // CHECK-NOFMV: Function Attrs: noinline nounwind optnone // CHECK-NOFMV-LABEL: define {{[^@]+}}@foo // CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] { @@ -995,40 +1121,50 @@ __attribute__((target_version("rdm"))) int unused_without_default(void) { return // CHECK-NOFMV-NEXT: entry: // CHECK-NOFMV-NEXT: ret i32 0 // +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@default_def_with_version_decls +// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: ret i32 0 +// //. -// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+altnzcv,+bf16,+flagm,+sme,+sme-i16i64,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,+neon,+sha2,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+ls64,+neon,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp16fml,+fullfp16,+neon,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR5]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR6]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR7]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme2,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR8]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR9]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR11:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+neon,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+flagm,+fp16fml,+fullfp16,+neon,+rand,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+flagm,+fp16fml,+fullfp16,+neon,+rand,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+altnzcv,+bf16,+flagm,+sme,+sme-i16i64,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,+neon,+sha2,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+ls64,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp16fml,+fullfp16,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR5]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR6]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR7]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR8]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme2,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR9:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+sb,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+neon,-fp-armv8,-v9.5a" } // CHECK: attributes #[[ATTR16]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR17]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+rdm,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR18]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+aes,+f64mm,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR19]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+fullfp16,+neon,+rdm,+sme,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR20]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+f32mm,+fullfp16,+i8mm,+neon,+sha2,+sha3,+sve,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR21]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+dit,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR22]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,+rcpc,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR23]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccdp,+ccpp,+jsconv,+neon,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR24]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint,+rcpc,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR25]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR26]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-sha3,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR27]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-bitperm,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR28]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+mte,+neon,+sve,+sve2,+sve2-sm4,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR29]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops,+mte,+rcpc,+rcpc3,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR30]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+sm4,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR31]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,+neon,+rdm,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR32]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+sb,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR17]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR18]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+rdm,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR19:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+jsconv,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR20:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+rdm,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR21]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+jsconv,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR22]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+aes,+f64mm,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR23]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+fullfp16,+neon,+rdm,+sme,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR24]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+f32mm,+fullfp16,+i8mm,+neon,+sha2,+sha3,+sve,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR25]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+dit,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR26]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,+rcpc,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR27]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccdp,+ccpp,+jsconv,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR28]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint,+rcpc,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR29]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR30]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-sha3,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR31]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-bitperm,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR32]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+mte,+neon,+sve,+sve2,+sve2-sm4,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR33]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops,+mte,+rcpc,+rcpc3,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR34]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+sm4,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR35]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,+neon,+rdm,-fp-armv8,-v9.5a" } //. // CHECK-NOFMV: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" } // CHECK-NOFMV: attributes #[[ATTR1:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" } diff --git a/clang/test/CodeGenCXX/attr-target-version.cpp b/clang/test/CodeGenCXX/attr-target-version.cpp index e06121d1a719fba94bb711f21b76a314bd35eff2..8b7273fe3bb517e23642a266c5a526848537e2c5 100644 --- a/clang/test/CodeGenCXX/attr-target-version.cpp +++ b/clang/test/CodeGenCXX/attr-target-version.cpp @@ -35,7 +35,7 @@ struct MyClass { int unused_with_implicit_forward_default_def(void); int __attribute__((target_version("lse"))) unused_with_implicit_forward_default_def(void); - // This should generate a normal function. + // This should generate a target version despite the default not being declared. int __attribute__((target_version("rdm"))) unused_without_default(void); }; @@ -75,6 +75,13 @@ int bar() { // CHECK: @_ZN7MyClass32unused_with_implicit_default_defEv = weak_odr ifunc i32 (ptr), ptr @_ZN7MyClass32unused_with_implicit_default_defEv.resolver // CHECK: @_ZN7MyClass40unused_with_implicit_forward_default_defEv = weak_odr ifunc i32 (ptr), ptr @_ZN7MyClass40unused_with_implicit_forward_default_defEv.resolver //. +// CHECK-LABEL: @_Z3fooi._Mbf16Msme-f64f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4 +// CHECK-NEXT: ret i32 1 +// +// // CHECK-LABEL: @_Z3fooi.default( // CHECK-NEXT: entry: // CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 @@ -82,6 +89,11 @@ int bar() { // CHECK-NEXT: ret i32 2 // // +// CHECK-LABEL: @_Z3foov._Mebf16Msm4( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 3 +// +// // CHECK-LABEL: @_Z3foov.default( // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 4 @@ -189,6 +201,14 @@ int bar() { // CHECK-NEXT: ret i32 1 // // +// CHECK-LABEL: @_ZN7MyClass22unused_without_defaultEv._Mrdm( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 0 +// +// // CHECK-LABEL: @_Z3barv( // CHECK-NEXT: entry: // CHECK-NEXT: [[M:%.*]] = alloca [[STRUCT_MYCLASS:%.*]], align 1 @@ -250,26 +270,6 @@ int bar() { // CHECK-NEXT: ret ptr @_Z3foov.default // // -// CHECK-LABEL: @_Z3fooi._Mbf16Msme-f64f64( -// CHECK-NEXT: entry: -// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 -// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4 -// CHECK-NEXT: ret i32 1 -// -// -// CHECK-LABEL: @_Z3foov._Mebf16Msm4( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 3 -// -// -// CHECK-LABEL: @_ZN7MyClass22unused_without_defaultEv( -// CHECK-NEXT: entry: -// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 -// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK-NEXT: ret i32 0 -// -// // CHECK-LABEL: @_ZN7MyClass23unused_with_default_defEv.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -312,16 +312,16 @@ int bar() { // CHECK-NEXT: ret ptr @_ZN7MyClass40unused_with_implicit_forward_default_defEv.default // //. -// CHECK: attributes #[[ATTR0:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } -// CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc" } -// CHECK: attributes #[[ATTR2:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon" } -// CHECK: attributes #[[ATTR3:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops" } -// CHECK: attributes #[[ATTR4:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" } -// CHECK: attributes #[[ATTR5:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" } -// CHECK: attributes #[[ATTR6:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" } -// CHECK: attributes #[[ATTR7:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse" } -// CHECK: attributes #[[ATTR8:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme-f64f64" } -// CHECK: attributes #[[ATTR9:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fp-armv8,+neon,+sm4" } +// CHECK: attributes #[[ATTR0:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme-f64f64" } +// CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +// CHECK: attributes #[[ATTR2:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fp-armv8,+neon,+sm4" } +// CHECK: attributes #[[ATTR3:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc" } +// CHECK: attributes #[[ATTR4:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon" } +// CHECK: attributes #[[ATTR5:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops" } +// CHECK: attributes #[[ATTR6:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" } +// CHECK: attributes #[[ATTR7:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" } +// CHECK: attributes #[[ATTR8:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" } +// CHECK: attributes #[[ATTR9:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse" } // CHECK: attributes #[[ATTR10:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm" } // CHECK: attributes #[[ATTR11:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" } //. diff --git a/clang/test/CodeGenCXX/mangle-ms-back-references.cpp b/clang/test/CodeGenCXX/mangle-ms-back-references.cpp index b27a9c5acacb777513efca00e1a072e9acf15190..8707bff95340703be8afc2b982848f12238e0a19 100644 --- a/clang/test/CodeGenCXX/mangle-ms-back-references.cpp +++ b/clang/test/CodeGenCXX/mangle-ms-back-references.cpp @@ -1,5 +1,18 @@ // RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s +namespace NS { +// The name "RT1" for the name of the class below has been specifically +// chosen to ensure that back reference lookup does not match against the +// implicitly generated "$RT1" name of the reference temporary symbol. +struct RT1 { + static const RT1& singleton; + int i; +}; +const RT1& RT1::singleton = RT1{1}; +} +// CHECK: "?$RT1@singleton@RT1@NS@@2ABU23@B" +// CHECK: "?singleton@RT1@NS@@2ABU12@B" + void f1(const char* a, const char* b) {} // CHECK: "?f1@@YAXPBD0@Z" diff --git a/clang/test/CodeGenHLSL/builtins/dot.hlsl b/clang/test/CodeGenHLSL/builtins/dot.hlsl index 0f993193c00cce41d45a369118b4bb326f304164..307d71cce3cb6dfc1e180926b27d733cc166c6c0 100644 --- a/clang/test/CodeGenHLSL/builtins/dot.hlsl +++ b/clang/test/CodeGenHLSL/builtins/dot.hlsl @@ -110,21 +110,21 @@ uint64_t test_dot_ulong4(uint64_t4 p0, uint64_t4 p1) { return dot(p0, p1); } // NO_HALF: ret float %dx.dot half test_dot_half(half p0, half p1) { return dot(p0, p1); } -// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot.v2f16(<2 x half> %0, <2 x half> %1) +// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot2.v2f16(<2 x half> %0, <2 x half> %1) // NATIVE_HALF: ret half %dx.dot -// NO_HALF: %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %0, <2 x float> %1) +// NO_HALF: %dx.dot = call float @llvm.dx.dot2.v2f32(<2 x float> %0, <2 x float> %1) // NO_HALF: ret float %dx.dot half test_dot_half2(half2 p0, half2 p1) { return dot(p0, p1); } -// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot.v3f16(<3 x half> %0, <3 x half> %1) +// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot3.v3f16(<3 x half> %0, <3 x half> %1) // NATIVE_HALF: ret half %dx.dot -// NO_HALF: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %0, <3 x float> %1) +// NO_HALF: %dx.dot = call float @llvm.dx.dot3.v3f32(<3 x float> %0, <3 x float> %1) // NO_HALF: ret float %dx.dot half test_dot_half3(half3 p0, half3 p1) { return dot(p0, p1); } -// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot.v4f16(<4 x half> %0, <4 x half> %1) +// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot4.v4f16(<4 x half> %0, <4 x half> %1) // NATIVE_HALF: ret half %dx.dot -// NO_HALF: %dx.dot = call float @llvm.dx.dot.v4f32(<4 x float> %0, <4 x float> %1) +// NO_HALF: %dx.dot = call float @llvm.dx.dot4.v4f32(<4 x float> %0, <4 x float> %1) // NO_HALF: ret float %dx.dot half test_dot_half4(half4 p0, half4 p1) { return dot(p0, p1); } @@ -132,34 +132,34 @@ half test_dot_half4(half4 p0, half4 p1) { return dot(p0, p1); } // CHECK: ret float %dx.dot float test_dot_float(float p0, float p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %0, <2 x float> %1) +// CHECK: %dx.dot = call float @llvm.dx.dot2.v2f32(<2 x float> %0, <2 x float> %1) // CHECK: ret float %dx.dot float test_dot_float2(float2 p0, float2 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %0, <3 x float> %1) +// CHECK: %dx.dot = call float @llvm.dx.dot3.v3f32(<3 x float> %0, <3 x float> %1) // CHECK: ret float %dx.dot float test_dot_float3(float3 p0, float3 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call float @llvm.dx.dot.v4f32(<4 x float> %0, <4 x float> %1) +// CHECK: %dx.dot = call float @llvm.dx.dot4.v4f32(<4 x float> %0, <4 x float> %1) // CHECK: ret float %dx.dot float test_dot_float4(float4 p0, float4 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %splat.splat, <2 x float> %1) +// CHECK: %dx.dot = call float @llvm.dx.dot2.v2f32(<2 x float> %splat.splat, <2 x float> %1) // CHECK: ret float %dx.dot float test_dot_float2_splat(float p0, float2 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %splat.splat, <3 x float> %1) +// CHECK: %dx.dot = call float @llvm.dx.dot3.v3f32(<3 x float> %splat.splat, <3 x float> %1) // CHECK: ret float %dx.dot float test_dot_float3_splat(float p0, float3 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call float @llvm.dx.dot.v4f32(<4 x float> %splat.splat, <4 x float> %1) +// CHECK: %dx.dot = call float @llvm.dx.dot4.v4f32(<4 x float> %splat.splat, <4 x float> %1) // CHECK: ret float %dx.dot float test_dot_float4_splat(float p0, float4 p1) { return dot(p0, p1); } // CHECK: %conv = sitofp i32 %1 to float // CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer -// CHECK: %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %0, <2 x float> %splat.splat) +// CHECK: %dx.dot = call float @llvm.dx.dot2.v2f32(<2 x float> %0, <2 x float> %splat.splat) // CHECK: ret float %dx.dot float test_builtin_dot_float2_int_splat(float2 p0, int p1) { return dot(p0, p1); @@ -168,7 +168,7 @@ float test_builtin_dot_float2_int_splat(float2 p0, int p1) { // CHECK: %conv = sitofp i32 %1 to float // CHECK: %splat.splatinsert = insertelement <3 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer -// CHECK: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %0, <3 x float> %splat.splat) +// CHECK: %dx.dot = call float @llvm.dx.dot3.v3f32(<3 x float> %0, <3 x float> %splat.splat) // CHECK: ret float %dx.dot float test_builtin_dot_float3_int_splat(float3 p0, int p1) { return dot(p0, p1); diff --git a/clang/test/CodeGenHLSL/builtins/pow.hlsl b/clang/test/CodeGenHLSL/builtins/pow.hlsl index e996ca2f3364101405f0357acea5c5dd184811c7..057cd7215aa5af3f70dc0bce4cd8312a2f84a178 100644 --- a/clang/test/CodeGenHLSL/builtins/pow.hlsl +++ b/clang/test/CodeGenHLSL/builtins/pow.hlsl @@ -39,16 +39,3 @@ float3 test_pow_float3(float3 p0, float3 p1) { return pow(p0, p1); } // CHECK: define noundef <4 x float> @"?test_pow_float4 // CHECK: call <4 x float> @llvm.pow.v4f32 float4 test_pow_float4(float4 p0, float4 p1) { return pow(p0, p1); } - -// CHECK: define noundef double @"?test_pow_double@@YANNN@Z"( -// CHECK: call double @llvm.pow.f64( -double test_pow_double(double p0, double p1) { return pow(p0, p1); } -// CHECK: define noundef <2 x double> @"?test_pow_double2@@YAT?$__vector@N$01@__clang@@T12@0@Z"( -// CHECK: call <2 x double> @llvm.pow.v2f64 -double2 test_pow_double2(double2 p0, double2 p1) { return pow(p0, p1); } -// CHECK: define noundef <3 x double> @"?test_pow_double3@@YAT?$__vector@N$02@__clang@@T12@0@Z"( -// CHECK: call <3 x double> @llvm.pow.v3f64 -double3 test_pow_double3(double3 p0, double3 p1) { return pow(p0, p1); } -// CHECK: define noundef <4 x double> @"?test_pow_double4@@YAT?$__vector@N$03@__clang@@T12@0@Z"( -// CHECK: call <4 x double> @llvm.pow.v4f64 -double4 test_pow_double4(double4 p0, double4 p1) { return pow(p0, p1); } diff --git a/clang/test/CodeGenHLSL/builtins/sqrt.hlsl b/clang/test/CodeGenHLSL/builtins/sqrt.hlsl index 2c2a09617cf86ae38ef419677e1f363e6d330294..adbbf69a8e068580ba2f5e84aafca385b43d7ce0 100644 --- a/clang/test/CodeGenHLSL/builtins/sqrt.hlsl +++ b/clang/test/CodeGenHLSL/builtins/sqrt.hlsl @@ -1,29 +1,53 @@ -// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.2-library %s -fnative-half-type \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF -using hlsl::sqrt; +// NATIVE_HALF: define noundef half @ +// NATIVE_HALF: %{{.*}} = call half @llvm.sqrt.f16( +// NATIVE_HALF: ret half %{{.*}} +// NO_HALF: define noundef float @"?test_sqrt_half@@YA$halff@$halff@@Z"( +// NO_HALF: %{{.*}} = call float @llvm.sqrt.f32( +// NO_HALF: ret float %{{.*}} +half test_sqrt_half(half p0) { return sqrt(p0); } +// NATIVE_HALF: define noundef <2 x half> @ +// NATIVE_HALF: %{{.*}} = call <2 x half> @llvm.sqrt.v2f16 +// NATIVE_HALF: ret <2 x half> %{{.*}} +// NO_HALF: define noundef <2 x float> @ +// NO_HALF: %{{.*}} = call <2 x float> @llvm.sqrt.v2f32( +// NO_HALF: ret <2 x float> %{{.*}} +half2 test_sqrt_half2(half2 p0) { return sqrt(p0); } +// NATIVE_HALF: define noundef <3 x half> @ +// NATIVE_HALF: %{{.*}} = call <3 x half> @llvm.sqrt.v3f16 +// NATIVE_HALF: ret <3 x half> %{{.*}} +// NO_HALF: define noundef <3 x float> @ +// NO_HALF: %{{.*}} = call <3 x float> @llvm.sqrt.v3f32( +// NO_HALF: ret <3 x float> %{{.*}} +half3 test_sqrt_half3(half3 p0) { return sqrt(p0); } +// NATIVE_HALF: define noundef <4 x half> @ +// NATIVE_HALF: %{{.*}} = call <4 x half> @llvm.sqrt.v4f16 +// NATIVE_HALF: ret <4 x half> %{{.*}} +// NO_HALF: define noundef <4 x float> @ +// NO_HALF: %{{.*}} = call <4 x float> @llvm.sqrt.v4f32( +// NO_HALF: ret <4 x float> %{{.*}} +half4 test_sqrt_half4(half4 p0) { return sqrt(p0); } -double sqrt_d(double x) -{ - return sqrt(x); -} - -// CHECK: define noundef double @"?sqrt_d@@YANN@Z"( -// CHECK: call double @llvm.sqrt.f64(double %0) - -float sqrt_f(float x) -{ - return sqrt(x); -} - -// CHECK: define noundef float @"?sqrt_f@@YAMM@Z"( -// CHECK: call float @llvm.sqrt.f32(float %0) - -half sqrt_h(half x) -{ - return sqrt(x); -} - -// CHECK: define noundef half @"?sqrt_h@@YA$f16@$f16@@Z"( -// CHECK: call half @llvm.sqrt.f16(half %0) +// CHECK: define noundef float @ +// CHECK: %{{.*}} = call float @llvm.sqrt.f32( +// CHECK: ret float %{{.*}} +float test_sqrt_float(float p0) { return sqrt(p0); } +// CHECK: define noundef <2 x float> @ +// CHECK: %{{.*}} = call <2 x float> @llvm.sqrt.v2f32 +// CHECK: ret <2 x float> %{{.*}} +float2 test_sqrt_float2(float2 p0) { return sqrt(p0); } +// CHECK: define noundef <3 x float> @ +// CHECK: %{{.*}} = call <3 x float> @llvm.sqrt.v3f32 +// CHECK: ret <3 x float> %{{.*}} +float3 test_sqrt_float3(float3 p0) { return sqrt(p0); } +// CHECK: define noundef <4 x float> @ +// CHECK: %{{.*}} = call <4 x float> @llvm.sqrt.v4f32 +// CHECK: ret <4 x float> %{{.*}} +float4 test_sqrt_float4(float4 p0) { return sqrt(p0); } diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx11-err.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx11-err.cl index f7afb7cb97edad0bdd2bda7238d4f95c8b2fcadb..4363769b864571bded723c97ea7ea95d56b0b8f8 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx11-err.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx11-err.cl @@ -6,21 +6,22 @@ typedef int v2i __attribute__((ext_vector_type(2))); typedef half v8h __attribute__((ext_vector_type(8))); typedef short v8s __attribute__((ext_vector_type(8))); +typedef __bf16 v8bf16 __attribute__((ext_vector_type(8))); typedef half v4h __attribute__((ext_vector_type(4))); typedef short v4s __attribute__((ext_vector_type(4))); +typedef __bf16 v4bf16 __attribute__((ext_vector_type(4))); - - -void amdgcn_global_load_tr(global v2i* v2i_inptr, global v8s* v8s_inptr, global v8h* v8h_inptr, - global int* int_inptr, global v4s* v4s_inptr, global v4h* v4h_inptr) +void amdgcn_global_load_tr(global v2i* v2i_inptr, global v8s* v8s_inptr, global v8h* v8h_inptr, global v8bf16* v8bf16_inptr, + global int* int_inptr, global v4s* v4s_inptr, global v4h* v4h_inptr, global v4bf16* v4bf16_inptr) { - v2i out_1 = __builtin_amdgcn_global_load_tr_v2i32(v2i_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v2i32' needs target feature gfx12-insts,wavefrontsize32}} - v8s out_2 = __builtin_amdgcn_global_load_tr_v8i16(v8s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v8i16' needs target feature gfx12-insts,wavefrontsize32}} - v8h out_3 = __builtin_amdgcn_global_load_tr_v8f16(v8h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v8f16' needs target feature gfx12-insts,wavefrontsize32}} - - int out_4 = __builtin_amdgcn_global_load_tr_i32(int_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_i32' needs target feature gfx12-insts,wavefrontsize64}} - v4s out_5 = __builtin_amdgcn_global_load_tr_v4i16(v4s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v4i16' needs target feature gfx12-insts,wavefrontsize64}} - v4h out_6 = __builtin_amdgcn_global_load_tr_v4f16(v4h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v4f16' needs target feature gfx12-insts,wavefrontsize64}} + v2i out_1 = __builtin_amdgcn_global_load_tr_b64_v2i32(v2i_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b64_v2i32' needs target feature gfx12-insts,wavefrontsize32}} + v8s out_2 = __builtin_amdgcn_global_load_tr_b128_v8i16(v8s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v8i16' needs target feature gfx12-insts,wavefrontsize32}} + v8h out_3 = __builtin_amdgcn_global_load_tr_b128_v8f16(v8h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v8f16' needs target feature gfx12-insts,wavefrontsize32}} + v8bf16 o4 = __builtin_amdgcn_global_load_tr_b128_v8bf16(v8bf16_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v8bf16' needs target feature gfx12-insts,wavefrontsize32}} + + int out_5 = __builtin_amdgcn_global_load_tr_b64_i32(int_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b64_i32' needs target feature gfx12-insts,wavefrontsize64}} + v4s out_6 = __builtin_amdgcn_global_load_tr_b128_v4i16(v4s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v4i16' needs target feature gfx12-insts,wavefrontsize64}} + v4h out_7 = __builtin_amdgcn_global_load_tr_b128_v4f16(v4h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v4f16' needs target feature gfx12-insts,wavefrontsize64}} + v4bf16 o8 = __builtin_amdgcn_global_load_tr_b128_v4bf16(v4bf16_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v4bf16' needs target feature gfx12-insts,wavefrontsize64}} } - diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w32-err.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w32-err.cl index 04ac0a66db7ce74d0e52f41ac079102aacc12577..208f92fc5d44f3ffcd4d25dc063c8b9c3bc2c55f 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w32-err.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w32-err.cl @@ -5,11 +5,12 @@ typedef half v4h __attribute__((ext_vector_type(4))); typedef short v4s __attribute__((ext_vector_type(4))); +typedef __bf16 v4bf16 __attribute__((ext_vector_type(4))); -void amdgcn_global_load_tr(global int* int_inptr, global v4s* v4s_inptr, global v4h* v4h_inptr) +void amdgcn_global_load_tr(global int* int_inptr, global v4s* v4s_inptr, global v4h* v4h_inptr, global v4bf16* v4bf16_inptr) { - int out_4 = __builtin_amdgcn_global_load_tr_i32(int_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_i32' needs target feature gfx12-insts,wavefrontsize64}} - v4s out_5 = __builtin_amdgcn_global_load_tr_v4i16(v4s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v4i16' needs target feature gfx12-insts,wavefrontsize64}} - v4h out_6 = __builtin_amdgcn_global_load_tr_v4f16(v4h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v4f16' needs target feature gfx12-insts,wavefrontsize64}} + int out_1 = __builtin_amdgcn_global_load_tr_b64_i32(int_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b64_i32' needs target feature gfx12-insts,wavefrontsize64}} + v4s out_2 = __builtin_amdgcn_global_load_tr_b128_v4i16(v4s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v4i16' needs target feature gfx12-insts,wavefrontsize64}} + v4h out_3 = __builtin_amdgcn_global_load_tr_b128_v4f16(v4h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v4f16' needs target feature gfx12-insts,wavefrontsize64}} + v4bf16 o4 = __builtin_amdgcn_global_load_tr_b128_v4bf16(v4bf16_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v4bf16' needs target feature gfx12-insts,wavefrontsize64}} } - diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w64-err.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w64-err.cl index 113b54b853a9f48e3628bd4cdfa627536cf7c9ba..199146a9715da6c03057a349472dc31c08803fa5 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w64-err.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w64-err.cl @@ -6,11 +6,12 @@ typedef int v2i __attribute__((ext_vector_type(2))); typedef half v8h __attribute__((ext_vector_type(8))); typedef short v8s __attribute__((ext_vector_type(8))); +typedef __bf16 v8bf16 __attribute__((ext_vector_type(8))); -void amdgcn_global_load_tr(global v2i* v2i_inptr, global v8s* v8s_inptr, global v8h* v8h_inptr) +void amdgcn_global_load_tr(global v2i* v2i_inptr, global v8s* v8s_inptr, global v8h* v8h_inptr, global v8bf16* v8bf16_inptr) { - v2i out_1 = __builtin_amdgcn_global_load_tr_v2i32(v2i_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v2i32' needs target feature gfx12-insts,wavefrontsize32}} - v8s out_2 = __builtin_amdgcn_global_load_tr_v8i16(v8s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v8i16' needs target feature gfx12-insts,wavefrontsize32}} - v8h out_3 = __builtin_amdgcn_global_load_tr_v8f16(v8h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v8f16' needs target feature gfx12-insts,wavefrontsize32}} + v2i out_1 = __builtin_amdgcn_global_load_tr_b64_v2i32(v2i_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b64_v2i32' needs target feature gfx12-insts,wavefrontsize32}} + v8s out_2 = __builtin_amdgcn_global_load_tr_b128_v8i16(v8s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v8i16' needs target feature gfx12-insts,wavefrontsize32}} + v8h out_3 = __builtin_amdgcn_global_load_tr_b128_v8f16(v8h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v8f16' needs target feature gfx12-insts,wavefrontsize32}} + v8bf16 o4 = __builtin_amdgcn_global_load_tr_b128_v8bf16(v8bf16_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v8bf16' needs target feature gfx12-insts,wavefrontsize32}} } - diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w32.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w32.cl index b5fcad68a470204fd6504aa589662f1ae30709db..0035b16b902b68d4fc09bdc600cfd1711b684466 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w32.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w32.cl @@ -5,44 +5,44 @@ typedef int v2i __attribute__((ext_vector_type(2))); typedef half v8h __attribute__((ext_vector_type(8))); typedef short v8s __attribute__((ext_vector_type(8))); +typedef __bf16 v8bf16 __attribute__((ext_vector_type(8))); -// Wave32 - -// -// amdgcn_global_load_tr -// - -// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_v2i32( +// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_b64_v2i32( // CHECK-GFX1200-NEXT: entry: // CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <2 x i32> @llvm.amdgcn.global.load.tr.v2i32(ptr addrspace(1) [[INPTR:%.*]]) // CHECK-GFX1200-NEXT: ret <2 x i32> [[TMP0]] // -v2i test_amdgcn_global_load_tr_v2i32(global v2i* inptr) +v2i test_amdgcn_global_load_tr_b64_v2i32(global v2i* inptr) { - return __builtin_amdgcn_global_load_tr_v2i32(inptr); + return __builtin_amdgcn_global_load_tr_b64_v2i32(inptr); } -// -// amdgcn_global_load_tr -// - -// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_v8i16( +// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_b128_v8i16( // CHECK-GFX1200-NEXT: entry: // CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <8 x i16> @llvm.amdgcn.global.load.tr.v8i16(ptr addrspace(1) [[INPTR:%.*]]) // CHECK-GFX1200-NEXT: ret <8 x i16> [[TMP0]] // -v8s test_amdgcn_global_load_tr_v8i16(global v8s* inptr) +v8s test_amdgcn_global_load_tr_b128_v8i16(global v8s* inptr) { - return __builtin_amdgcn_global_load_tr_v8i16(inptr); + return __builtin_amdgcn_global_load_tr_b128_v8i16(inptr); } -// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_v8f16( +// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_b128_v8f16( // CHECK-GFX1200-NEXT: entry: // CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <8 x half> @llvm.amdgcn.global.load.tr.v8f16(ptr addrspace(1) [[INPTR:%.*]]) // CHECK-GFX1200-NEXT: ret <8 x half> [[TMP0]] // -v8h test_amdgcn_global_load_tr_v8f16(global v8h* inptr) +v8h test_amdgcn_global_load_tr_b128_v8f16(global v8h* inptr) { - return __builtin_amdgcn_global_load_tr_v8f16(inptr); + return __builtin_amdgcn_global_load_tr_b128_v8f16(inptr); } +// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_b128_v8bf16( +// CHECK-GFX1200-NEXT: entry: +// CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <8 x bfloat> @llvm.amdgcn.global.load.tr.v8bf16(ptr addrspace(1) [[INPTR:%.*]]) +// CHECK-GFX1200-NEXT: ret <8 x bfloat> [[TMP0]] +// +v8bf16 test_amdgcn_global_load_tr_b128_v8bf16(global v8bf16* inptr) +{ + return __builtin_amdgcn_global_load_tr_b128_v8bf16(inptr); +} diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w64.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w64.cl index 9c48ac071b4d3fa7e80ee5ab7f12f4462f279013..6c025bb5a55a360f71afe530897eaa5ec92402ca 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w64.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w64.cl @@ -4,44 +4,44 @@ typedef half v4h __attribute__((ext_vector_type(4))); typedef short v4s __attribute__((ext_vector_type(4))); +typedef __bf16 v4bf16 __attribute__((ext_vector_type(4))); -// Wave64 - -// -// amdgcn_global_load_tr -// - -// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_i32( +// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_b64_i32( // CHECK-GFX1200-NEXT: entry: // CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.amdgcn.global.load.tr.i32(ptr addrspace(1) [[INPTR:%.*]]) // CHECK-GFX1200-NEXT: ret i32 [[TMP0]] // -int test_amdgcn_global_load_tr_i32(global int* inptr) +int test_amdgcn_global_load_tr_b64_i32(global int* inptr) { - return __builtin_amdgcn_global_load_tr_i32(inptr); + return __builtin_amdgcn_global_load_tr_b64_i32(inptr); } -// -// amdgcn_global_load_tr -// - -// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_v4i16( +// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_b128_v4i16( // CHECK-GFX1200-NEXT: entry: // CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <4 x i16> @llvm.amdgcn.global.load.tr.v4i16(ptr addrspace(1) [[INPTR:%.*]]) // CHECK-GFX1200-NEXT: ret <4 x i16> [[TMP0]] // -v4s test_amdgcn_global_load_tr_v4i16(global v4s* inptr) +v4s test_amdgcn_global_load_tr_b128_v4i16(global v4s* inptr) { - return __builtin_amdgcn_global_load_tr_v4i16(inptr); + return __builtin_amdgcn_global_load_tr_b128_v4i16(inptr); } -// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_v4f16( +// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_b128_v4f16( // CHECK-GFX1200-NEXT: entry: // CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <4 x half> @llvm.amdgcn.global.load.tr.v4f16(ptr addrspace(1) [[INPTR:%.*]]) // CHECK-GFX1200-NEXT: ret <4 x half> [[TMP0]] // -v4h test_amdgcn_global_load_tr_v4f16(global v4h* inptr) +v4h test_amdgcn_global_load_tr_b128_v4f16(global v4h* inptr) { - return __builtin_amdgcn_global_load_tr_v4f16(inptr); + return __builtin_amdgcn_global_load_tr_b128_v4f16(inptr); } +// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_b128_v4bf16( +// CHECK-GFX1200-NEXT: entry: +// CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <4 x bfloat> @llvm.amdgcn.global.load.tr.v4bf16(ptr addrspace(1) [[INPTR:%.*]]) +// CHECK-GFX1200-NEXT: ret <4 x bfloat> [[TMP0]] +// +v4bf16 test_amdgcn_global_load_tr_b128_v4bf16(global v4bf16* inptr) +{ + return __builtin_amdgcn_global_load_tr_b128_v4bf16(inptr); +} diff --git a/clang/test/Driver/riscv-profiles.c b/clang/test/Driver/riscv-profiles.c new file mode 100644 index 0000000000000000000000000000000000000000..0227487015ba7c0549570e3413ce2f75b24ed767 --- /dev/null +++ b/clang/test/Driver/riscv-profiles.c @@ -0,0 +1,324 @@ +// RUN: %clang --target=riscv32 -### -c %s 2>&1 -march=rvi20u32 \ +// RUN: | FileCheck -check-prefix=RVI20U32 %s +// RVI20U32: "-target-feature" "-a" +// RVI20U32: "-target-feature" "-c" +// RVI20U32: "-target-feature" "-d" +// RVI20U32: "-target-feature" "-f" +// RVI20U32: "-target-feature" "-m" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rvi20u64 \ +// RUN: | FileCheck -check-prefix=RVI20U64 %s +// RVI20U64: "-target-feature" "-a" +// RVI20U64: "-target-feature" "-c" +// RVI20U64: "-target-feature" "-d" +// RVI20U64: "-target-feature" "-f" +// RVI20U64: "-target-feature" "-m" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rva20u64 \ +// RUN: | FileCheck -check-prefix=RVA20U64 %s +// RVA20U64: "-target-feature" "+m" +// RVA20U64: "-target-feature" "+a" +// RVA20U64: "-target-feature" "+f" +// RVA20U64: "-target-feature" "+d" +// RVA20U64: "-target-feature" "+c" +// RVA20U64: "-target-feature" "+ziccamoa" +// RVA20U64: "-target-feature" "+ziccif" +// RVA20U64: "-target-feature" "+zicclsm" +// RVA20U64: "-target-feature" "+ziccrse" +// RVA20U64: "-target-feature" "+zicntr" +// RVA20U64: "-target-feature" "+zicsr" +// RVA20U64: "-target-feature" "+za128rs" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rva20s64 \ +// RUN: | FileCheck -check-prefix=RVA20S64 %s +// RVA20S64: "-target-feature" "+m" +// RVA20S64: "-target-feature" "+a" +// RVA20S64: "-target-feature" "+f" +// RVA20S64: "-target-feature" "+d" +// RVA20S64: "-target-feature" "+c" +// RVA20S64: "-target-feature" "+ziccamoa" +// RVA20S64: "-target-feature" "+ziccif" +// RVA20S64: "-target-feature" "+zicclsm" +// RVA20S64: "-target-feature" "+ziccrse" +// RVA20S64: "-target-feature" "+zicntr" +// RVA20S64: "-target-feature" "+zicsr" +// RVA20S64: "-target-feature" "+zifencei" +// RVA20S64: "-target-feature" "+za128rs" +// RVA20S64: "-target-feature" "+ssccptr" +// RVA20S64: "-target-feature" "+sstvala" +// RVA20S64: "-target-feature" "+sstvecd" +// RVA20S64: "-target-feature" "+svade" +// RVA20S64: "-target-feature" "+svbare" + +// RUN: %clang --target=riscv64 --target=riscv64 -### -c %s 2>&1 -march=rva22u64 \ +// RUN: | FileCheck -check-prefix=RVA22U64 %s +// RVA22U64: "-target-feature" "+m" +// RVA22U64: "-target-feature" "+a" +// RVA22U64: "-target-feature" "+f" +// RVA22U64: "-target-feature" "+d" +// RVA22U64: "-target-feature" "+c" +// RVA22U64: "-target-feature" "+zic64b" +// RVA22U64: "-target-feature" "+zicbom" +// RVA22U64: "-target-feature" "+zicbop" +// RVA22U64: "-target-feature" "+zicboz" +// RVA22U64: "-target-feature" "+ziccamoa" +// RVA22U64: "-target-feature" "+ziccif" +// RVA22U64: "-target-feature" "+zicclsm" +// RVA22U64: "-target-feature" "+ziccrse" +// RVA22U64: "-target-feature" "+zicntr" +// RVA22U64: "-target-feature" "+zicsr" +// RVA22U64: "-target-feature" "+zihintpause" +// RVA22U64: "-target-feature" "+zihpm" +// RVA22U64: "-target-feature" "+za64rs" +// RVA22U64: "-target-feature" "+zfhmin" +// RVA22U64: "-target-feature" "+zba" +// RVA22U64: "-target-feature" "+zbb" +// RVA22U64: "-target-feature" "+zbs" +// RVA22U64: "-target-feature" "+zkt" + +// RUN: %clang --target=riscv64 --target=riscv64 -### -c %s 2>&1 -march=rva22s64 \ +// RUN: | FileCheck -check-prefix=RVA22S64 %s +// RVA22S64: "-target-feature" "+m" +// RVA22S64: "-target-feature" "+a" +// RVA22S64: "-target-feature" "+f" +// RVA22S64: "-target-feature" "+d" +// RVA22S64: "-target-feature" "+c" +// RVA22S64: "-target-feature" "+zic64b" +// RVA22S64: "-target-feature" "+zicbom" +// RVA22S64: "-target-feature" "+zicbop" +// RVA22S64: "-target-feature" "+zicboz" +// RVA22S64: "-target-feature" "+ziccamoa" +// RVA22S64: "-target-feature" "+ziccif" +// RVA22S64: "-target-feature" "+zicclsm" +// RVA22S64: "-target-feature" "+ziccrse" +// RVA22S64: "-target-feature" "+zicntr" +// RVA22S64: "-target-feature" "+zicsr" +// RVA22S64: "-target-feature" "+zifencei" +// RVA22S64: "-target-feature" "+zihintpause" +// RVA22S64: "-target-feature" "+zihpm" +// RVA22S64: "-target-feature" "+za64rs" +// RVA22S64: "-target-feature" "+zfhmin" +// RVA22S64: "-target-feature" "+zba" +// RVA22S64: "-target-feature" "+zbb" +// RVA22S64: "-target-feature" "+zbs" +// RVA22S64: "-target-feature" "+zkt" +// RVA22S64: "-target-feature" "+ssccptr" +// RVA22S64: "-target-feature" "+sscounterenw" +// RVA22S64: "-target-feature" "+sstvala" +// RVA22S64: "-target-feature" "+sstvecd" +// RVA22S64: "-target-feature" "+svade" +// RVA22S64: "-target-feature" "+svbare" +// RVA22S64: "-target-feature" "+svinval" +// RVA22S64: "-target-feature" "+svpbmt" + +// RUN: %clang --target=riscv64 --target=riscv64 -### -c %s 2>&1 -march=rva23u64 -menable-experimental-extensions \ +// RUN: | FileCheck -check-prefix=RVA23U64 %s +// RVA23U64: "-target-feature" "+m" +// RVA23U64: "-target-feature" "+a" +// RVA23U64: "-target-feature" "+f" +// RVA23U64: "-target-feature" "+d" +// RVA23U64: "-target-feature" "+c" +// RVA23U64: "-target-feature" "+v" +// RVA23U64: "-target-feature" "+zic64b" +// RVA23U64: "-target-feature" "+zicbom" +// RVA23U64: "-target-feature" "+zicbop" +// RVA23U64: "-target-feature" "+zicboz" +// RVA23U64: "-target-feature" "+ziccamoa" +// RVA23U64: "-target-feature" "+ziccif" +// RVA23U64: "-target-feature" "+zicclsm" +// RVA23U64: "-target-feature" "+ziccrse" +// RVA23U64: "-target-feature" "+zicntr" +// RVA23U64: "-target-feature" "+zicond" +// RVA23U64: "-target-feature" "+zicsr" +// RVA23U64: "-target-feature" "+zihintntl" +// RVA23U64: "-target-feature" "+zihintpause" +// RVA23U64: "-target-feature" "+zihpm" +// RVA23U64: "-target-feature" "+experimental-zimop" +// RVA23U64: "-target-feature" "+za64rs" +// RVA23U64: "-target-feature" "+zawrs" +// RVA23U64: "-target-feature" "+zfa" +// RVA23U64: "-target-feature" "+zfhmin" +// RVA23U64: "-target-feature" "+zcb" +// RVA23U64: "-target-feature" "+experimental-zcmop" +// RVA23U64: "-target-feature" "+zba" +// RVA23U64: "-target-feature" "+zbb" +// RVA23U64: "-target-feature" "+zbs" +// RVA23U64: "-target-feature" "+zkt" +// RVA23U64: "-target-feature" "+zvbb" +// RVA23U64: "-target-feature" "+zvfhmin" +// RVA23U64: "-target-feature" "+zvkt" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rva23s64 -menable-experimental-extensions \ +// RUN: | FileCheck -check-prefix=RVA23S64 %s +// RVA23S64: "-target-feature" "+m" +// RVA23S64: "-target-feature" "+a" +// RVA23S64: "-target-feature" "+f" +// RVA23S64: "-target-feature" "+d" +// RVA23S64: "-target-feature" "+c" +// RVA23S64: "-target-feature" "+v" +// RVA23S64: "-target-feature" "+h" +// RVA23S64: "-target-feature" "+zic64b" +// RVA23S64: "-target-feature" "+zicbom" +// RVA23S64: "-target-feature" "+zicbop" +// RVA23S64: "-target-feature" "+zicboz" +// RVA23S64: "-target-feature" "+ziccamoa" +// RVA23S64: "-target-feature" "+ziccif" +// RVA23S64: "-target-feature" "+zicclsm" +// RVA23S64: "-target-feature" "+ziccrse" +// RVA23S64: "-target-feature" "+zicntr" +// RVA23S64: "-target-feature" "+zicond" +// RVA23S64: "-target-feature" "+zicsr" +// RVA23S64: "-target-feature" "+zifencei" +// RVA23S64: "-target-feature" "+zihintntl" +// RVA23S64: "-target-feature" "+zihintpause" +// RVA23S64: "-target-feature" "+zihpm" +// RVA23S64: "-target-feature" "+experimental-zimop" +// RVA23S64: "-target-feature" "+za64rs" +// RVA23S64: "-target-feature" "+zawrs" +// RVA23S64: "-target-feature" "+zfa" +// RVA23S64: "-target-feature" "+zfhmin" +// RVA23S64: "-target-feature" "+zcb" +// RVA23S64: "-target-feature" "+experimental-zcmop" +// RVA23S64: "-target-feature" "+zba" +// RVA23S64: "-target-feature" "+zbb" +// RVA23S64: "-target-feature" "+zbs" +// RVA23S64: "-target-feature" "+zkt" +// RVA23S64: "-target-feature" "+zvbb" +// RVA23S64: "-target-feature" "+zvfhmin" +// RVA23S64: "-target-feature" "+zvkt" +// RVA23S64: "-target-feature" "+shcounterenw" +// RVA23S64: "-target-feature" "+shgatpa" +// RVA23S64: "-target-feature" "+shtvala" +// RVA23S64: "-target-feature" "+shvsatpa" +// RVA23S64: "-target-feature" "+shvstvala" +// RVA23S64: "-target-feature" "+shvstvecd" +// RVA23S64: "-target-feature" "+ssccptr" +// RVA23S64: "-target-feature" "+sscofpmf" +// RVA23S64: "-target-feature" "+sscounterenw" +// RVA23S64: "-target-feature" "+experimental-ssnpm" +// RVA23S64: "-target-feature" "+ssstateen" +// RVA23S64: "-target-feature" "+sstc" +// RVA23S64: "-target-feature" "+sstvala" +// RVA23S64: "-target-feature" "+sstvecd" +// RVA23S64: "-target-feature" "+ssu64xl" +// RVA23S64: "-target-feature" "+svade" +// RVA23S64: "-target-feature" "+svbare" +// RVA23S64: "-target-feature" "+svinval" +// RVA23S64: "-target-feature" "+svnapot" +// RVA23S64: "-target-feature" "+svpbmt" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rvb23u64 -menable-experimental-extensions \ +// RUN: | FileCheck -check-prefix=RVB23U64 %s +// RVB23U64: "-target-feature" "+m" +// RVB23U64: "-target-feature" "+a" +// RVB23U64: "-target-feature" "+f" +// RVB23U64: "-target-feature" "+d" +// RVB23U64: "-target-feature" "+c" +// RVB23U64: "-target-feature" "+zic64b" +// RVB23U64: "-target-feature" "+zicbom" +// RVB23U64: "-target-feature" "+zicbop" +// RVB23U64: "-target-feature" "+zicboz" +// RVB23U64: "-target-feature" "+ziccamoa" +// RVB23U64: "-target-feature" "+ziccif" +// RVB23U64: "-target-feature" "+zicclsm" +// RVB23U64: "-target-feature" "+ziccrse" +// RVB23U64: "-target-feature" "+zicntr" +// RVB23U64: "-target-feature" "+zicond" +// RVB23U64: "-target-feature" "+zicsr" +// RVB23U64: "-target-feature" "+zihintntl" +// RVB23U64: "-target-feature" "+zihintpause" +// RVB23U64: "-target-feature" "+zihpm" +// RVB23U64: "-target-feature" "+experimental-zimop" +// RVB23U64: "-target-feature" "+za64rs" +// RVB23U64: "-target-feature" "+zawrs" +// RVB23U64: "-target-feature" "+zfa" +// RVB23U64: "-target-feature" "+zcb" +// RVB23U64: "-target-feature" "+experimental-zcmop" +// RVB23U64: "-target-feature" "+zba" +// RVB23U64: "-target-feature" "+zbb" +// RVB23U64: "-target-feature" "+zbs" +// RVB23U64: "-target-feature" "+zkt" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rvb23s64 -menable-experimental-extensions \ +// RUN: | FileCheck -check-prefix=RVB23S64 %s +// RVB23S64: "-target-feature" "+m" +// RVB23S64: "-target-feature" "+a" +// RVB23S64: "-target-feature" "+f" +// RVB23S64: "-target-feature" "+d" +// RVB23S64: "-target-feature" "+c" +// RVB23S64: "-target-feature" "+zic64b" +// RVB23S64: "-target-feature" "+zicbom" +// RVB23S64: "-target-feature" "+zicbop" +// RVB23S64: "-target-feature" "+zicboz" +// RVB23S64: "-target-feature" "+ziccamoa" +// RVB23S64: "-target-feature" "+ziccif" +// RVB23S64: "-target-feature" "+zicclsm" +// RVB23S64: "-target-feature" "+ziccrse" +// RVB23S64: "-target-feature" "+zicntr" +// RVB23S64: "-target-feature" "+zicond" +// RVB23S64: "-target-feature" "+zicsr" +// RVB23S64: "-target-feature" "+zifencei" +// RVB23S64: "-target-feature" "+zihintntl" +// RVB23S64: "-target-feature" "+zihintpause" +// RVB23S64: "-target-feature" "+zihpm" +// RVB23S64: "-target-feature" "+experimental-zimop" +// RVB23S64: "-target-feature" "+za64rs" +// RVB23S64: "-target-feature" "+zawrs" +// RVB23S64: "-target-feature" "+zfa" +// RVB23S64: "-target-feature" "+zcb" +// RVB23S64: "-target-feature" "+experimental-zcmop" +// RVB23S64: "-target-feature" "+zba" +// RVB23S64: "-target-feature" "+zbb" +// RVB23S64: "-target-feature" "+zbs" +// RVB23S64: "-target-feature" "+zkt" +// RVB23S64: "-target-feature" "+ssccptr" +// RVB23S64: "-target-feature" "+sscofpmf" +// RVB23S64: "-target-feature" "+sscounterenw" +// RVB23S64: "-target-feature" "+sstc" +// RVB23S64: "-target-feature" "+sstvala" +// RVB23S64: "-target-feature" "+sstvecd" +// RVB23S64: "-target-feature" "+ssu64xl" +// RVB23S64: "-target-feature" "+svade" +// RVB23S64: "-target-feature" "+svbare" +// RVB23S64: "-target-feature" "+svinval" +// RVB23S64: "-target-feature" "+svnapot" +// RVB23S64: "-target-feature" "+svpbmt" + +// RUN: %clang --target=riscv32 -### -c %s 2>&1 -march=rvm23u32 -menable-experimental-extensions \ +// RUN: | FileCheck -check-prefix=RVM23U32 %s +// RVM23U32: "-target-feature" "+m" +// RVM23U32: "-target-feature" "+zicbop" +// RVM23U32: "-target-feature" "+zicond" +// RVM23U32: "-target-feature" "+zicsr" +// RVM23U32: "-target-feature" "+zihintntl" +// RVM23U32: "-target-feature" "+zihintpause" +// RVM23U32: "-target-feature" "+experimental-zimop" +// RVM23U32: "-target-feature" "+zce" +// RVM23U32: "-target-feature" "+experimental-zcmop" +// RVM23U32: "-target-feature" "+zba" +// RVM23U32: "-target-feature" "+zbb" +// RVM23U32: "-target-feature" "+zbs" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rva22u64_zfa \ +// RUN: | FileCheck -check-prefix=PROFILE-WITH-ADDITIONAL %s +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+m" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+a" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+f" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+d" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+c" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zicbom" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zicbop" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zicboz" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zihintpause" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zfa" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zfhmin" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zba" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zbb" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zbs" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zkt" + +// RUN: not %clang --target=riscv64 -### -c %s 2>&1 -march=rva19u64_zfa | FileCheck -check-prefix=INVALID-PROFILE %s +// INVALID-PROFILE: error: invalid arch name 'rva19u64_zfa', unsupported profile + +// RUN: not %clang --target=riscv64 -### -c %s 2>&1 -march=rva22u64zfa | FileCheck -check-prefix=INVALID-ADDITIONAL %s +// INVALID-ADDITIONAL: error: invalid arch name 'rva22u64zfa', additional extensions must be after separator '_' diff --git a/clang/test/InstallAPI/Inputs/Simple/Extra/SimpleExtraAPI1.h b/clang/test/InstallAPI/Inputs/Simple/Extra/SimpleExtraAPI1.h new file mode 100644 index 0000000000000000000000000000000000000000..83a5b9507de307ea599b505e17586f71bf0e41a2 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Extra/SimpleExtraAPI1.h @@ -0,0 +1 @@ +extern int extraGlobalAPI1; diff --git a/clang/test/InstallAPI/Inputs/Simple/Extra/SimpleExtraAPI2.h b/clang/test/InstallAPI/Inputs/Simple/Extra/SimpleExtraAPI2.h new file mode 100644 index 0000000000000000000000000000000000000000..34fe3364bba84eaaa79becbdcfa1d0a64faba59c --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Extra/SimpleExtraAPI2.h @@ -0,0 +1 @@ +extern int extraGlobalAPI2; diff --git a/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/Basic.h b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/Basic.h new file mode 100644 index 0000000000000000000000000000000000000000..08412bb2de2838b3aef30693261f2b3ef34cbd70 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/Basic.h @@ -0,0 +1,103 @@ +#import + +// Basic class with no super class +@interface Basic1 +@end + +@interface Basic2 : NSObject +@end + +@interface Basic3 : NSObject +@property BOOL property1; +@property(readonly) BOOL property2; +@property(getter=isProperty3) BOOL property3; +@property BOOL dynamicProp; +@end + +@interface Basic4 : NSObject { +@public + BOOL ivar1; +@protected + BOOL ivar2; +@package + BOOL ivar3; +@private + BOOL ivar4; +} +@end + +__attribute__((visibility("hidden"))) @interface Basic4_1 : NSObject { +@public + BOOL ivar1; +@protected + BOOL ivar2; +@package + BOOL ivar3; +@private + BOOL ivar4; +} +@end + +@interface Basic4_2 : NSObject { +@private + BOOL ivar4; +@package + BOOL ivar3; +@protected + BOOL ivar2; +@public + BOOL ivar1; +} +@end + +@interface Basic5 : NSObject ++ (void)aClassMethod; +- (void)anInstanceMethod; +@end + +@interface Basic6 : NSObject +@end + +@interface Basic6 () { +@public + BOOL ivar1; +} +@property BOOL property1; +- (void)anInstanceMethodFromAnExtension; +@end + +@interface Basic6 (Foo) +@property BOOL property2; +- (void)anInstanceMethodFromACategory; +@end + +__attribute__((visibility("hidden"))) +@interface Basic7 : NSObject +@end + +@interface Basic7 () +- (void) anInstanceMethodFromAnHiddenExtension; +@end + +@interface Basic8 : NSObject ++ (void)useSameName; +@end + +// Classes and protocols can have the same name. For now they would only clash +// in the selector map if the protocl starts with '_'. +@protocol _A +- (void)aMethod; +@end + +@interface A : NSObject +- (void)aMethod NS_AVAILABLE(10_11, 9_0); +- (void)bMethod NS_UNAVAILABLE; +@end + +@interface Basic9 : NSObject +@property(readonly) BOOL aProperty NS_AVAILABLE(10_10, 8_0); +@end + +@interface Basic9 (deprecated) +@property(readwrite) BOOL aProperty NS_DEPRECATED_MAC(10_8, 10_10); +@end diff --git a/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/External.h b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/External.h new file mode 100644 index 0000000000000000000000000000000000000000..5dc3c92f34c24de8cb076b4483071a61c600c48d --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/External.h @@ -0,0 +1,19 @@ +#import + +// Sub-class an external defined ObjC Class. +@interface ExternalManagedObject : NSManagedObject +- (void)foo; +@end + +// Add category to external defined ObjC Class. +@interface NSManagedObject (Simple) +- (int)supportsSimple; +@end + +// CoreData Accessors are dynamically generated and have no implementation. +@interface ExternalManagedObject (CoreDataGeneratedAccessors) +- (void)addChildObject:(ExternalManagedObject *)value; +- (void)removeChildObject:(ExternalManagedObject *)value; +- (void)addChild:(NSSet *)values; +- (void)removeChild:(NSSet *)values; +@end diff --git a/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/Simple.h b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/Simple.h new file mode 100644 index 0000000000000000000000000000000000000000..12c77098a8d9a759cffd86fe004b9ffbd25cb45e --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/Simple.h @@ -0,0 +1,45 @@ +#import + +// Useless forward declaration. This is used for testing. +@class FooBar; +@protocol FooProtocol; + +@protocol ForwardProcotol; + +// Test public global. +extern int publicGlobalVariable; + +// Test weak public global. +extern int weakPublicGlobalVariable __attribute__((weak)); + +// Test public ObjC class +@interface Simple : NSObject +@end + +__attribute__((objc_exception)) +@interface Base : NSObject +@end + +@interface SubClass : Base +@end + +@protocol BaseProtocol +- (void) baseMethod; +@end + +NS_AVAILABLE(10_11, 9_0) +@protocol FooProtocol +- (void) protocolMethod; +@end + +@protocol BarProtocol +- (void) barMethod; +@end + +@interface FooClass +@end + +// Create an empty category conforms to a forward declared protocol. +// +@interface FooClass (Test) +@end diff --git a/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/SimpleAPI.h b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/SimpleAPI.h new file mode 100644 index 0000000000000000000000000000000000000000..d953fac966daf3d72e49ab595ed48a824b1fc267 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/SimpleAPI.h @@ -0,0 +1 @@ +extern int otherFrameworkAPI; diff --git a/clang/test/InstallAPI/Inputs/Simple/Simple.framework/PrivateHeaders/SimplePrivate.h b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/PrivateHeaders/SimplePrivate.h new file mode 100644 index 0000000000000000000000000000000000000000..5a28cda3928e3d8b5f1a0f199af04f748ac75d43 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/PrivateHeaders/SimplePrivate.h @@ -0,0 +1,5 @@ +// Test private global variable. +extern int privateGlobalVariable; + +// Test weak private global. +extern int weakPrivateGlobalVariable __attribute__((weak)); diff --git a/clang/test/InstallAPI/Inputs/Simple/Simple.framework/PrivateHeaders/SimplePrivateSPI.h b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/PrivateHeaders/SimplePrivateSPI.h new file mode 100644 index 0000000000000000000000000000000000000000..c9aca30fa82fa851b16420a572dce36c32718fb3 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/PrivateHeaders/SimplePrivateSPI.h @@ -0,0 +1,2 @@ +// Test private global variable. +extern int otherFrameworkSPI; diff --git a/clang/test/InstallAPI/Inputs/Simple/Simple.yaml b/clang/test/InstallAPI/Inputs/Simple/Simple.yaml new file mode 100644 index 0000000000000000000000000000000000000000..998e51f1a67dcc9915f661e68975f3998d6b0412 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Simple.yaml @@ -0,0 +1,3196 @@ +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x6 + ncmds: 15 + sizeofcmds: 1952 + flags: 0x118085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 472 + segname: __TEXT + vmaddr: 0 + vmsize: 12288 + fileoff: 0 + filesize: 12288 + maxprot: 5 + initprot: 5 + nsects: 5 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x1BC0 + size: 180 + offset: 0x1BC0 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 554889E50FBE47085DC3554889E58857085DC3554889E50FBE47095DC3554889E50FBE470A5DC3554889E588570A5DC3554889E55DC3554889E55DC3554889E55DC3554889E50FBE47095DC3554889E58857095DC3554889E5B8010000005DC3554889E55DC3554889E55DC3554889E55DC3554889E55DC3554889E5B0015DC3554889E55DC3554889E55DC3554889E55DC3554889E50FBE47085DC3554889E55DC3554889E55DC3554889E55DC3554889E55DC3 + - sectname: __cstring + segname: __TEXT + addr: 0x1C74 + size: 296 + offset: 0x1C74 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 53696D706C65004261736500537562436C6173730053696D706C65496E7465726E616C4150490053696D706C65496E7465726E616C53504900426173696331004261736963320042617369633300426173696334004261736963345F31004261736963345F32004261736963350042617369633600466F6F004261736963370045787465726E616C4D616E616765644F626A6563740048696464656E436C61737300426173696338004100426173696339006465707265636174656400466F6F436C61737300466F6F50726F746F636F6C004261736550726F746F636F6C0042617250726F746F636F6C0050726976617465005072697661746550726F746F636F6C0063313640303A380076323040303A3863313600630076313640303A380042313640303A3800 + - sectname: __objc_methname + segname: __TEXT + addr: 0x1D9C + size: 450 + offset: 0x1D9C + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 70726F7065727479310073657450726F7065727479313A0070726F70657274793200697350726F7065727479330073657450726F7065727479333A0070726F7065727479330054632C5670726F7065727479310054632C522C5670726F7065727479320054632C47697350726F7065727479332C5670726F7065727479330064796E616D696350726F700054632C440069766172310069766172320069766172330069766172340061436C6173734D6574686F6400616E496E7374616E63654D6574686F6400616E496E7374616E63654D6574686F6446726F6D416E457874656E73696F6E0073657450726F7065727479323A00616E496E7374616E63654D6574686F6446726F6D4143617465676F727900546300616E496E7374616E63654D6574686F6446726F6D416E48696464656E457874656E73696F6E00666F6F00737570706F72747353696D706C650075736553616D654E616D6500614D6574686F64006150726F7065727479005F6150726F70657274790054632C522C565F6150726F706572747900626173654D6574686F640070726F746F636F6C4D6574686F64006261724D6574686F64007072697661746550726F636F746F6C4D6574686F6400 + - sectname: __unwind_info + segname: __TEXT + addr: 0x1F60 + size: 4152 + offset: 0x1F60 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000001C000000010000002000000000000000200000000200000000000001C01B00003800000038000000741C00000000000038000000030000000C0001001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + - sectname: __eh_frame + segname: __TEXT + addr: 0x2F98 + size: 24 + offset: 0x2F98 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x6000000B + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 1400000000000000017A520001781001100C070890010000 + - cmd: LC_SEGMENT_64 + cmdsize: 792 + segname: __DATA + vmaddr: 12288 + vmsize: 8192 + fileoff: 12288 + filesize: 8192 + maxprot: 3 + initprot: 3 + nsects: 9 + flags: 0 + Sections: + - sectname: __objc_const + segname: __DATA + addr: 0x3000 + size: 4952 + offset: 0x3000 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000002800000028000000000000000000000000000000741C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000008000000000000000000000000000000741C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000028000000280000000000000000000000000000007B1C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000008000000080000000000000000000000000000007B1C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000007B1C000000000000D043000000000000010000002800000028000000000000000000000000000000801C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000008000000000000000000000000000000801C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000801C0000000000002044000000000000010000002800000028000000000000000000000000000000891C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000008000000000000000000000000000000891C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000891C00000000000070440000000000000100000028000000280000000000000000000000000000009B1C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000008000000080000000000000000000000000000009B1C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000009B1C000000000000C044000000000000030000002800000028000000000000000000000000000000AD1C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000AD1C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000002800000028000000000000000000000000000000B41C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000008000000000000000000000000000000B41C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000002800000028000000000000000000000000000000BB1C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000000050000009C1D000000000000771D000000000000C01B000000000000A61D0000000000007F1D000000000000CA1B000000000000B41D000000000000771D000000000000D31B000000000000BE1D000000000000771D000000000000DD1B000000000000CA1D0000000000007F1D000000000000E71B000000000000200000000300000098490000000000009C1D0000000000008A1D0000000000000000000001000000A049000000000000B41D0000000000008A1D0000000000000000000001000000A849000000000000D81D0000000000008A1D000000000000000000000100000010000000040000009C1D000000000000E21D000000000000B41D000000000000F01D000000000000D81D000000000000001E0000000000001B1E000000000000271E00000000000000000000080000000B000000000000000000000000000000BB1C00000000000098340000000000000000000000000000183500000000000000000000000000008035000000000000010000002800000028000000000000000000000000000000C21C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000004000000B0490000000000002C1E0000000000008A1D0000000000000000000001000000B849000000000000321E0000000000008A1D0000000000000000000001000000C049000000000000381E0000000000008A1D0000000000000000000001000000C8490000000000003E1E0000000000008A1D000000000000000000000100000000000000080000000C000000000000000000000000000000C21C00000000000000000000000000000000000000000000583600000000000000000000000000000000000000000000110000002800000028000000000000000000000000000000C91C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000004000000D0490000000000002C1E0000000000008A1D0000000000000000000001000000D849000000000000321E0000000000008A1D0000000000000000000001000000E049000000000000381E0000000000008A1D0000000000000000000001000000E8490000000000003E1E0000000000008A1D000000000000000000000100000010000000080000000C000000000000000000000000000000C91C00000000000000000000000000000000000000000000703700000000000000000000000000000000000000000000010000002800000028000000000000000000000000000000D21C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000004000000F0490000000000003E1E0000000000008A1D0000000000000000000001000000F849000000000000381E0000000000008A1D0000000000000000000001000000004A000000000000321E0000000000008A1D0000000000000000000001000000084A0000000000002C1E0000000000008A1D000000000000000000000100000000000000080000000C000000000000000000000000000000D21C000000000000000000000000000000000000000000008838000000000000000000000000000000000000000000001800000001000000441E0000000000008C1D000000000000F01B000000000000010000002800000028000000000000000000000000000000DB1C000000000000583900000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000511E0000000000008C1D000000000000F61B000000000000000000000800000008000000000000000000000000000000DB1C000000000000C0390000000000000000000000000000000000000000000000000000000000000000000000000000010000002800000028000000000000000000000000000000E21C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000003000000621E0000000000008C1D000000000000FC1B0000000000009C1D000000000000771D000000000000021C000000000000A61D0000000000007F1D0000000000000C1C0000000000002000000002000000104A0000000000002C1E0000000000008A1D0000000000000000000001000000184A0000000000009C1D0000000000008A1D000000000000000000000100000010000000010000009C1D000000000000E21D00000000000000000000080000000A000000000000000000000000000000E21C000000000000703A0000000000000000000000000000C03A0000000000000000000000000000083B0000000000001800000003000000B41D000000000000771D000000000000151C000000000000821E0000000000007F1D000000000000201C000000000000901E0000000000008C1D000000000000261C0000000000001000000001000000B41D000000000000AE1E000000000000E91C0000000000004047000000000000683B00000000000000000000000000000000000000000000B83B00000000000000000000000000004000000000000000110000002800000028000000000000000000000000000000ED1C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000B11E0000000000008C1D0000000000002C1C000000000000100000000800000008000000000000000000000000000000ED1C000000000000583C0000000000000000000000000000000000000000000000000000000000000000000000000000010000002800000028000000000000000000000000000000F41C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000D71E0000000000008C1D000000000000321C000000000000000000000800000008000000000000000000000000000000F41C000000000000083D00000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000DB1E000000000000941D000000000000381C000000000000741C0000000000000000000000000000703D000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000001100000028000000280000000000000000000000000000000A1D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000008000000080000000000000000000000000000000A1D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000EA1E0000000000008C1D000000000000401C000000000000010000002800000028000000000000000000000000000000161D000000000000603E00000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000EA1E0000000000008C1D000000000000461C000000000000000000000800000008000000000000000000000000000000161D000000000000C83E00000000000000000000000000000000000000000000000000000000000000000000000000000100000028000000280000000000000000000000000000001D1D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000F61E0000000000008C1D0000000000004C1C0000000000000000000008000000080000000000000000000000000000001D1D000000000000783F00000000000000000000000000000000000000000000000000000000000000000000000000000100000028000000280000000000000000000000000000001F1D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000FE1E000000000000771D000000000000521C0000000000002000000001000000204A000000000000081F0000000000008A1D00000000000000000000010000001000000001000000FE1E000000000000131F0000000000000000000008000000090000000000000000000000000000001F1D000000000000284000000000000000000000000000004840000000000000000000000000000070400000000000001000000001000000FE1E000000000000AE1E000000000000261D0000000000002049000000000000000000000000000000000000000000000000000000000000D040000000000000000000000000000040000000000000001800000001000000241F0000000000008C1D00000000000000000000000000008C1D0000000000000100000000000000284A000000000000000000000000000018000000010000002F1F0000000000008C1D00000000000000000000000000008C1D00000000000018000000010000003E1F0000000000008C1D00000000000000000000000000008C1D0000000000000200000000000000884A000000000000E84A0000000000000000000000000000030000002800000028000000000000000000000000000000311D0000000000000000000000000000B8410000000000000000000000000000000000000000000000000000000000001800000003000000241F0000000000008C1D0000000000005C1C0000000000002F1F0000000000008C1D000000000000621C0000000000003E1F0000000000008C1D000000000000681C000000000000020000000000000000000000000000000000000000000000311D0000000000002042000000000000B8410000000000000000000000000000000000000000000000000000000000001800000001000000481F0000000000008C1D0000000000006E1C0000000000001800000001000000481F0000000000008C1D00000000000000000000000000008C1D0000000000000100000000000000484B00000000000000000000000000005F1D0000000000004849000000000000B84200000000000000000000000000000043000000000000000000000000000000000000000000004000000000000000 + - sectname: __objc_data + segname: __DATA + addr: 0x4358 + size: 1600 + offset: 0x4358 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 000000000000000000000000000000000000000000000000000000000000000000300000000000005843000000000000000000000000000000000000000000000000000000000000483000000000000000000000000000000000000000000000000000000000000000000000000000009030000000000000A843000000000000000000000000000000000000000000000000000000000000D8300000000000000000000000000000A843000000000000000000000000000000000000000000003831000000000000F843000000000000D0430000000000000000000000000000000000000000000080310000000000000000000000000000000000000000000000000000000000000000000000000000E03100000000000048440000000000000000000000000000000000000000000000000000000000002832000000000000000000000000000000000000000000000000000000000000000000000000000088320000000000009844000000000000000000000000000000000000000000000000000000000000D032000000000000104500000000000000000000000000000000000000000000000000000000000078330000000000001045000000000000E8440000000000000000000000000000000000000000000030330000000000000000000000000000000000000000000000000000000000000000000000000000C03300000000000038450000000000000000000000000000000000000000000000000000000000000834000000000000000000000000000000000000000000000000000000000000000000000000000050340000000000008845000000000000000000000000000000000000000000000000000000000000C83500000000000000000000000000000000000000000000000000000000000000000000000000001036000000000000D845000000000000000000000000000000000000000000000000000000000000E036000000000000000000000000000000000000000000000000000000000000000000000000000028370000000000002846000000000000000000000000000000000000000000000000000000000000F837000000000000000000000000000000000000000000000000000000000000000000000000000040380000000000007846000000000000000000000000000000000000000000000000000000000000103900000000000000000000000000000000000000000000000000000000000000000000000000007839000000000000C846000000000000000000000000000000000000000000000000000000000000E0390000000000000000000000000000000000000000000000000000000000000000000000000000283A0000000000001847000000000000000000000000000000000000000000000000000000000000203B0000000000000000000000000000000000000000000000000000000000000000000000000000103C0000000000006847000000000000000000000000000000000000000000000000000000000000783C0000000000000000000000000000000000000000000000000000000000000000000000000000C03C000000000000B847000000000000000000000000000000000000000000000000000000000000283D0000000000000000000000000000000000000000000000000000000000000000000000000000D03D0000000000000848000000000000000000000000000000000000000000000000000000000000183E0000000000000000000000000000000000000000000000000000000000000000000000000000803E0000000000005848000000000000000000000000000000000000000000000000000000000000E83E0000000000000000000000000000000000000000000000000000000000000000000000000000303F000000000000A848000000000000000000000000000000000000000000000000000000000000983F0000000000000000000000000000000000000000000000000000000000000000000000000000E03F000000000000F8480000000000000000000000000000000000000000000000000000000000008840000000000000704900000000000000000000000000000000000000000000000000000000000070420000000000007049000000000000484900000000000000000000000000000000000000000000D841000000000000 + - sectname: __objc_ivar + segname: __DATA + addr: 0x4998 + size: 144 + offset: 0x4998 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 080000000000000009000000000000000A00000000000000080000000000000009000000000000000A000000000000000B00000000000000080000000000000009000000000000000A000000000000000B00000000000000080000000000000009000000000000000A000000000000000B00000000000000080000000000000009000000000000000800000000000000 + - sectname: __data + segname: __DATA + addr: 0x4A28 + size: 392 + offset: 0x4A28 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 0000000000000000461D000000000000000000000000000028410000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000048410000000000000000000000000000000000000000000000000000000000003A1D00000000000050410000000000006841000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000008841000000000000000000000000000000000000000000000000000000000000531D0000000000000000000000000000904100000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000B041000000000000000000000000000000000000000000000000000000000000671D0000000000000000000000000000D84200000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000F842000000000000000000000000000000000000000000000000000000000000 + - sectname: __objc_protolist + segname: __DATA + addr: 0x4BB0 + size: 32 + offset: 0x4BB0 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x1000000B + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 284A000000000000884A000000000000E84A000000000000484B000000000000 + - sectname: __objc_classlist + segname: __DATA + addr: 0x4BD0 + size: 160 + offset: 0x4BD0 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x10000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 8043000000000000D04300000000000020440000000000007044000000000000C044000000000000E8440000000000006045000000000000B04500000000000000460000000000005046000000000000A046000000000000F04600000000000040470000000000009047000000000000E04700000000000030480000000000008048000000000000D04800000000000020490000000000004849000000000000 + - sectname: __objc_catlist + segname: __DATA + addr: 0x4C70 + size: 32 + offset: 0x4C70 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x10000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: D03B000000000000903D000000000000E8400000000000001843000000000000 + - sectname: __objc_imageinfo + segname: __DATA + addr: 0x4C90 + size: 8 + offset: 0x4C90 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000040000000' + - sectname: __common + segname: __DATA + addr: 0x4C98 + size: 16 + offset: 0x0 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x1 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 20480 + vmsize: 10272 + fileoff: 20480 + filesize: 10272 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 20480 + rebase_size: 320 + bind_off: 20800 + bind_size: 480 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 21280 + export_size: 896 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 22208 + nsyms: 187 + stroff: 25200 + strsize: 5552 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 131 + iextdefsym: 131 + nextdefsym: 49 + iundefsym: 180 + nundefsym: 7 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 88 + dylib: + name: 24 + timestamp: 0 + current_version: 66051 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/Simple.framework/Versions/A/Simple' + ZeroPadBytes: 3 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C441D-5555-3144-A104-DD1AF4EF8FE7 + - cmd: LC_VERSION_MIN_MACOSX + cmdsize: 16 + version: 658432 + sdk: 983040 + - cmd: LC_LOAD_DYLIB + cmdsize: 96 + dylib: + name: 24 + timestamp: 0 + current_version: 197722368 + compatibility_version: 19660800 + Content: '/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation' + ZeroPadBytes: 3 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 14942208 + compatibility_version: 65536 + Content: '/usr/lib/libobjc.A.dylib' + ZeroPadBytes: 8 + - cmd: LC_LOAD_DYLIB + cmdsize: 96 + dylib: + name: 24 + timestamp: 0 + current_version: 91750400 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/CoreData.framework/Versions/A/CoreData' + ZeroPadBytes: 7 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88539136 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 22176 + datasize: 32 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 22208 + datasize: 0 +LinkEditData: + RebaseOpcodes: + - Opcode: REBASE_OPCODE_SET_TYPE_IMM + Imm: 1 + - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 1 + ExtraData: [ 0x18 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x3, 0x40 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x40 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x40 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x40 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x4, 0x40 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 15 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 8 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x10 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x10 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x10 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 5 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 7 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 9 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 9 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 5 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x28 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 7 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 5 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 4 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x40 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 5 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 7 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 7 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 4 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x18 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x8 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x8 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 9 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x38 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x98 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x18 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 5 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x18 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x18 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x18 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES + Imm: 0 + ExtraData: [ 0x1C ] + - Opcode: REBASE_OPCODE_DONE + Imm: 0 + BindOpcodes: + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: _objc_ehtype_vtable + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM + Imm: 2 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 1 + ULEBExtraData: [ 0x120 ] + Symbol: '' + - Opcode: BIND_OPCODE_SET_ADDEND_SLEB + Imm: 0 + SLEBExtraData: [ 16 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xA0 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xA0 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xA0 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: '_OBJC_CLASS_$_NSManagedObject' + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM + Imm: 3 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xA78 ] + Symbol: '' + - Opcode: BIND_OPCODE_SET_ADDEND_SLEB + Imm: 0 + SLEBExtraData: [ 0 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xA48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: '_OBJC_METACLASS_$_NSObject' + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM + Imm: 2 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xFFFFFFFFFFFFFB68 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x90 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: __objc_empty_cache + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xFFFFFFFFFFFFFA60 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: '_OBJC_CLASS_$_NSObject' + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xFFFFFFFFFFFFFA00 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x98 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x98 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x98 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: '_OBJC_METACLASS_$_NSManagedObject' + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM + Imm: 3 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xFFFFFFFFFFFFFE90 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DONE + Imm: 0 + Symbol: '' + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 5 + Name: _ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 41 + Name: p + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 86 + Name: rivateGlobalVariable + Flags: 0x0 + Address: 0x4CA0 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 92 + Name: ublicGlobalVariable + Flags: 0x0 + Address: 0x4CA4 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 98 + Name: extraGlobalAPI + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 106 + Name: '1' + Flags: 0x0 + Address: 0x4C98 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 112 + Name: '2' + Flags: 0x0 + Address: 0x4C9C + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 118 + Name: weakP + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 165 + Name: rivateGlobalVariable + Flags: 0x4 + Address: 0x4BAC + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 171 + Name: ublicGlobalVariable + Flags: 0x4 + Address: 0x4BA8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 177 + Name: OBJC_ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 232 + Name: 'IVAR_$_Basic' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 248 + Name: 6.ivar1 + Flags: 0x0 + Address: 0x4A10 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 254 + Name: '4' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 274 + Name: .ivar + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 284 + Name: '2' + Flags: 0x0 + Address: 0x49B8 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 290 + Name: '1' + Flags: 0x0 + Address: 0x49B0 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 296 + Name: _2.ivar + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 306 + Name: '1' + Flags: 0x0 + Address: 0x4A08 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 312 + Name: '2' + Flags: 0x0 + Address: 0x4A00 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 318 + Name: 'METACLASS_$_' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 369 + Name: FooClass + Flags: 0x0 + Address: 0x4970 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 375 + Name: ExternalManagedObject + Flags: 0x0 + Address: 0x47B8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 381 + Name: S + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 401 + Name: imple + Flags: 0x0 + Address: 0x4358 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 418 + Name: Internal + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 432 + Name: SPI + Flags: 0x0 + Address: 0x4498 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 438 + Name: API + Flags: 0x0 + Address: 0x4448 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 444 + Name: ubClass + Flags: 0x0 + Address: 0x43F8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 450 + Name: Bas + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 461 + Name: e + Flags: 0x0 + Address: 0x43A8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 467 + Name: ic + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 501 + Name: '2' + Flags: 0x0 + Address: 0x4538 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 507 + Name: '3' + Flags: 0x0 + Address: 0x4588 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 513 + Name: '5' + Flags: 0x0 + Address: 0x46C8 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 519 + Name: '4' + Flags: 0x0 + Address: 0x45D8 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 530 + Name: _2 + Flags: 0x0 + Address: 0x4678 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 536 + Name: '9' + Flags: 0x0 + Address: 0x48F8 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 542 + Name: '8' + Flags: 0x0 + Address: 0x4858 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 548 + Name: '6' + Flags: 0x0 + Address: 0x4718 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 554 + Name: '1' + Flags: 0x0 + Address: 0x4510 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 560 + Name: A + Flags: 0x0 + Address: 0x48A8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 566 + Name: 'EHTYPE_$_' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 579 + Name: Base + Flags: 0x0 + Address: 0x3120 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 584 + Name: S + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 612 + Name: ubClass + Flags: 0x0 + Address: 0x31C8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 617 + Name: impleInternal + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 631 + Name: SPI + Flags: 0x0 + Address: 0x3318 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 636 + Name: API + Flags: 0x0 + Address: 0x3270 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 641 + Name: 'CLASS_$_' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 692 + Name: A + Flags: 0x0 + Address: 0x48D0 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 698 + Name: ExternalManagedObject + Flags: 0x0 + Address: 0x47E0 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 704 + Name: FooClass + Flags: 0x0 + Address: 0x4948 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 710 + Name: S + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 730 + Name: ubClass + Flags: 0x0 + Address: 0x4420 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 736 + Name: imple + Flags: 0x0 + Address: 0x4380 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 753 + Name: Internal + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 767 + Name: API + Flags: 0x0 + Address: 0x4470 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 773 + Name: SPI + Flags: 0x0 + Address: 0x44C0 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 779 + Name: Bas + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 790 + Name: e + Flags: 0x0 + Address: 0x43D0 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 796 + Name: ic + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 830 + Name: '1' + Flags: 0x0 + Address: 0x44E8 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 836 + Name: '3' + Flags: 0x0 + Address: 0x45B0 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 842 + Name: '4' + Flags: 0x0 + Address: 0x4600 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 853 + Name: _2 + Flags: 0x0 + Address: 0x46A0 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 859 + Name: '2' + Flags: 0x0 + Address: 0x4560 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 865 + Name: '8' + Flags: 0x0 + Address: 0x4880 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 871 + Name: '9' + Flags: 0x0 + Address: 0x4920 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 877 + Name: '6' + Flags: 0x0 + Address: 0x4740 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 883 + Name: '5' + Flags: 0x0 + Address: 0x46F0 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 2 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7104 + - n_strx: 22 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7114 + - n_strx: 46 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7123 + - n_strx: 66 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7133 + - n_strx: 88 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7143 + - n_strx: 112 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7152 + - n_strx: 135 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7158 + - n_strx: 162 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7164 + - n_strx: 204 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7170 + - n_strx: 224 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7180 + - n_strx: 248 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7189 + - n_strx: 273 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7200 + - n_strx: 302 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7206 + - n_strx: 347 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7212 + - n_strx: 395 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7218 + - n_strx: 424 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7224 + - n_strx: 466 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7232 + - n_strx: 488 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7238 + - n_strx: 510 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7244 + - n_strx: 523 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7250 + - n_strx: 543 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7260 + - n_strx: 566 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7266 + - n_strx: 593 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7272 + - n_strx: 615 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7278 + - n_strx: 658 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12288 + - n_strx: 687 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12360 + - n_strx: 712 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12432 + - n_strx: 739 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12504 + - n_strx: 762 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12600 + - n_strx: 793 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12672 + - n_strx: 820 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12768 + - n_strx: 860 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12840 + - n_strx: 896 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12936 + - n_strx: 936 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13008 + - n_strx: 972 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13176 + - n_strx: 997 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13104 + - n_strx: 1026 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13248 + - n_strx: 1055 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13320 + - n_strx: 1080 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13392 + - n_strx: 1109 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13464 + - n_strx: 1142 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13592 + - n_strx: 1177 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13696 + - n_strx: 1203 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13768 + - n_strx: 1228 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13840 + - n_strx: 1257 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13912 + - n_strx: 1292 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14048 + - n_strx: 1317 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14120 + - n_strx: 1348 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14192 + - n_strx: 1385 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14328 + - n_strx: 1412 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14400 + - n_strx: 1443 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14472 + - n_strx: 1480 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14608 + - n_strx: 1507 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14680 + - n_strx: 1537 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14712 + - n_strx: 1566 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14784 + - n_strx: 1599 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14816 + - n_strx: 1624 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14888 + - n_strx: 1653 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14960 + - n_strx: 1686 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15040 + - n_strx: 1721 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15112 + - n_strx: 1747 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15136 + - n_strx: 1772 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15208 + - n_strx: 1820 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15288 + - n_strx: 1852 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15312 + - n_strx: 1883 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15376 + - n_strx: 1912 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15448 + - n_strx: 1945 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15480 + - n_strx: 1970 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15552 + - n_strx: 2014 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15624 + - n_strx: 2062 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15656 + - n_strx: 2102 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15728 + - n_strx: 2162 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15760 + - n_strx: 2205 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15824 + - n_strx: 2239 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15896 + - n_strx: 2269 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15968 + - n_strx: 2299 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16000 + - n_strx: 2328 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16072 + - n_strx: 2361 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16104 + - n_strx: 2386 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16176 + - n_strx: 2410 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16248 + - n_strx: 2438 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16280 + - n_strx: 2458 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16352 + - n_strx: 2487 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16424 + - n_strx: 2520 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16456 + - n_strx: 2555 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16496 + - n_strx: 2581 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16520 + - n_strx: 2606 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16592 + - n_strx: 2645 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16616 + - n_strx: 2683 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 17008 + - n_strx: 2710 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16856 + - n_strx: 2741 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16680 + - n_strx: 2789 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16712 + - n_strx: 2833 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16720 + - n_strx: 2868 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16744 + - n_strx: 2915 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16776 + - n_strx: 2958 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16784 + - n_strx: 3005 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16816 + - n_strx: 3048 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16824 + - n_strx: 3082 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16928 + - n_strx: 3117 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 17080 + - n_strx: 3171 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 17112 + - n_strx: 3222 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 17144 + - n_strx: 3269 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 17152 + - n_strx: 3316 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 17176 + - n_strx: 4000 + n_type: 0x1E + n_sect: 7 + n_desc: 0 + n_value: 17960 + - n_strx: 4027 + n_type: 0x1E + n_sect: 7 + n_desc: 0 + n_value: 18000 + - n_strx: 4192 + n_type: 0x1E + n_sect: 7 + n_desc: 0 + n_value: 18280 + - n_strx: 4217 + n_type: 0x1E + n_sect: 7 + n_desc: 0 + n_value: 18320 + - n_strx: 4314 + n_type: 0x1E + n_sect: 7 + n_desc: 0 + n_value: 18440 + - n_strx: 4344 + n_type: 0x1E + n_sect: 7 + n_desc: 0 + n_value: 18480 + - n_strx: 4548 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18840 + - n_strx: 4578 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18848 + - n_strx: 4608 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18856 + - n_strx: 4690 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18880 + - n_strx: 4716 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18888 + - n_strx: 4742 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18896 + - n_strx: 4770 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18904 + - n_strx: 4798 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18912 + - n_strx: 4826 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18920 + - n_strx: 4854 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18928 + - n_strx: 4882 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18936 + - n_strx: 4992 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18968 + - n_strx: 5022 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18976 + - n_strx: 5053 + n_type: 0x1E + n_sect: 9 + n_desc: 0 + n_value: 18984 + - n_strx: 5084 + n_type: 0x1E + n_sect: 9 + n_desc: 0 + n_value: 19080 + - n_strx: 5114 + n_type: 0x1E + n_sect: 9 + n_desc: 0 + n_value: 19176 + - n_strx: 5144 + n_type: 0x1E + n_sect: 9 + n_desc: 0 + n_value: 19272 + - n_strx: 5231 + n_type: 0x1E + n_sect: 10 + n_desc: 0 + n_value: 19376 + - n_strx: 5268 + n_type: 0x1E + n_sect: 10 + n_desc: 0 + n_value: 19384 + - n_strx: 5304 + n_type: 0x1E + n_sect: 10 + n_desc: 0 + n_value: 19392 + - n_strx: 5340 + n_type: 0x1E + n_sect: 10 + n_desc: 0 + n_value: 19400 + - n_strx: 3353 + n_type: 0xF + n_sect: 14 + n_desc: 0 + n_value: 19608 + - n_strx: 3370 + n_type: 0xF + n_sect: 14 + n_desc: 0 + n_value: 19612 + - n_strx: 3387 + n_type: 0xF + n_sect: 14 + n_desc: 0 + n_value: 19616 + - n_strx: 3410 + n_type: 0xF + n_sect: 14 + n_desc: 0 + n_value: 19620 + - n_strx: 3432 + n_type: 0xF + n_sect: 6 + n_desc: 0 + n_value: 12576 + - n_strx: 3452 + n_type: 0xF + n_sect: 6 + n_desc: 0 + n_value: 12744 + - n_strx: 3476 + n_type: 0xF + n_sect: 6 + n_desc: 0 + n_value: 12912 + - n_strx: 3509 + n_type: 0xF + n_sect: 6 + n_desc: 0 + n_value: 13080 + - n_strx: 3542 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17240 + - n_strx: 3567 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17280 + - n_strx: 3588 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17320 + - n_strx: 3611 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17360 + - n_strx: 3630 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17400 + - n_strx: 3657 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17440 + - n_strx: 3680 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17480 + - n_strx: 3716 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17520 + - n_strx: 3748 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17560 + - n_strx: 3784 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17600 + - n_strx: 3816 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17640 + - n_strx: 3837 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17680 + - n_strx: 3862 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17720 + - n_strx: 3887 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17760 + - n_strx: 3908 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17800 + - n_strx: 3933 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17840 + - n_strx: 3954 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17880 + - n_strx: 3979 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17920 + - n_strx: 4050 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18040 + - n_strx: 4077 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18080 + - n_strx: 4100 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18120 + - n_strx: 4125 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18160 + - n_strx: 4146 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18200 + - n_strx: 4171 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18240 + - n_strx: 4238 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18360 + - n_strx: 4278 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18400 + - n_strx: 4370 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18520 + - n_strx: 4395 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18560 + - n_strx: 4416 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18600 + - n_strx: 4436 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18640 + - n_strx: 4452 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18680 + - n_strx: 4477 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18720 + - n_strx: 4498 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18760 + - n_strx: 4521 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18800 + - n_strx: 4638 + n_type: 0xF + n_sect: 8 + n_desc: 0 + n_value: 18864 + - n_strx: 4664 + n_type: 0xF + n_sect: 8 + n_desc: 0 + n_value: 18872 + - n_strx: 4910 + n_type: 0xF + n_sect: 8 + n_desc: 0 + n_value: 18944 + - n_strx: 4938 + n_type: 0xF + n_sect: 8 + n_desc: 0 + n_value: 18952 + - n_strx: 4966 + n_type: 0xF + n_sect: 8 + n_desc: 0 + n_value: 18960 + - n_strx: 5178 + n_type: 0xF + n_sect: 9 + n_desc: 128 + n_value: 19368 + - n_strx: 5204 + n_type: 0xF + n_sect: 9 + n_desc: 128 + n_value: 19372 + - n_strx: 5380 + n_type: 0x1 + n_sect: 0 + n_desc: 768 + n_value: 0 + - n_strx: 5410 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + - n_strx: 5433 + n_type: 0x1 + n_sect: 0 + n_desc: 768 + n_value: 0 + - n_strx: 5467 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + - n_strx: 5494 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + - n_strx: 5513 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + - n_strx: 5533 + n_type: 0x1 + n_sect: 0 + n_desc: 1024 + n_value: 0 + StringTable: + - ' ' + - '-[Basic3 property1]' + - '-[Basic3 setProperty1:]' + - '-[Basic3 property2]' + - '-[Basic3 isProperty3]' + - '-[Basic3 setProperty3:]' + - '+[Basic5 aClassMethod]' + - '-[Basic5 anInstanceMethod]' + - '-[Basic6 anInstanceMethodFromAnExtension]' + - '-[Basic6 property1]' + - '-[Basic6 setProperty1:]' + - '-[Basic6(Foo) property2]' + - '-[Basic6(Foo) setProperty2:]' + - '-[Basic6(Foo) anInstanceMethodFromACategory]' + - '-[Basic7 anInstanceMethodFromAnHiddenExtension]' + - '-[ExternalManagedObject foo]' + - '-[NSManagedObject(Simple) supportsSimple]' + - '+[Basic8 useSameName]' + - '-[Basic8 useSameName]' + - '-[A aMethod]' + - '-[Basic9 aProperty]' + - '-[FooClass baseMethod]' + - '-[FooClass protocolMethod]' + - '-[FooClass barMethod]' + - '-[FooClass(Private) privateProcotolMethod]' + - '__OBJC_METACLASS_RO_$_Simple' + - '__OBJC_CLASS_RO_$_Simple' + - '__OBJC_METACLASS_RO_$_Base' + - '__OBJC_CLASS_RO_$_Base' + - '__OBJC_METACLASS_RO_$_SubClass' + - '__OBJC_CLASS_RO_$_SubClass' + - '__OBJC_METACLASS_RO_$_SimpleInternalAPI' + - '__OBJC_CLASS_RO_$_SimpleInternalAPI' + - '__OBJC_METACLASS_RO_$_SimpleInternalSPI' + - '__OBJC_CLASS_RO_$_SimpleInternalSPI' + - '__OBJC_CLASS_RO_$_Basic1' + - '__OBJC_METACLASS_RO_$_Basic1' + - '__OBJC_METACLASS_RO_$_Basic2' + - '__OBJC_CLASS_RO_$_Basic2' + - '__OBJC_METACLASS_RO_$_Basic3' + - '__OBJC_$_INSTANCE_METHODS_Basic3' + - '__OBJC_$_INSTANCE_VARIABLES_Basic3' + - '__OBJC_$_PROP_LIST_Basic3' + - '__OBJC_CLASS_RO_$_Basic3' + - '__OBJC_METACLASS_RO_$_Basic4' + - '__OBJC_$_INSTANCE_VARIABLES_Basic4' + - '__OBJC_CLASS_RO_$_Basic4' + - '__OBJC_METACLASS_RO_$_Basic4_1' + - '__OBJC_$_INSTANCE_VARIABLES_Basic4_1' + - '__OBJC_CLASS_RO_$_Basic4_1' + - '__OBJC_METACLASS_RO_$_Basic4_2' + - '__OBJC_$_INSTANCE_VARIABLES_Basic4_2' + - '__OBJC_CLASS_RO_$_Basic4_2' + - '__OBJC_$_CLASS_METHODS_Basic5' + - '__OBJC_METACLASS_RO_$_Basic5' + - '__OBJC_$_INSTANCE_METHODS_Basic5' + - '__OBJC_CLASS_RO_$_Basic5' + - '__OBJC_METACLASS_RO_$_Basic6' + - '__OBJC_$_INSTANCE_METHODS_Basic6' + - '__OBJC_$_INSTANCE_VARIABLES_Basic6' + - '__OBJC_$_PROP_LIST_Basic6' + - '__OBJC_CLASS_RO_$_Basic6' + - '__OBJC_$_CATEGORY_INSTANCE_METHODS_Basic6_$_Foo' + - '__OBJC_$_PROP_LIST_Basic6_$_Foo' + - '__OBJC_$_CATEGORY_Basic6_$_Foo' + - '__OBJC_METACLASS_RO_$_Basic7' + - '__OBJC_$_INSTANCE_METHODS_Basic7' + - '__OBJC_CLASS_RO_$_Basic7' + - '__OBJC_METACLASS_RO_$_ExternalManagedObject' + - '__OBJC_$_INSTANCE_METHODS_ExternalManagedObject' + - '__OBJC_CLASS_RO_$_ExternalManagedObject' + - '__OBJC_$_CATEGORY_INSTANCE_METHODS_NSManagedObject_$_Simple' + - '__OBJC_$_CATEGORY_NSManagedObject_$_Simple' + - '__OBJC_METACLASS_RO_$_HiddenClass' + - '__OBJC_CLASS_RO_$_HiddenClass' + - '__OBJC_$_CLASS_METHODS_Basic8' + - '__OBJC_METACLASS_RO_$_Basic8' + - '__OBJC_$_INSTANCE_METHODS_Basic8' + - '__OBJC_CLASS_RO_$_Basic8' + - '__OBJC_METACLASS_RO_$_A' + - '__OBJC_$_INSTANCE_METHODS_A' + - '__OBJC_CLASS_RO_$_A' + - '__OBJC_METACLASS_RO_$_Basic9' + - '__OBJC_$_INSTANCE_METHODS_Basic9' + - '__OBJC_$_INSTANCE_VARIABLES_Basic9' + - '__OBJC_$_PROP_LIST_Basic9' + - '__OBJC_CLASS_RO_$_Basic9' + - '__OBJC_$_PROP_LIST_Basic9_$_deprecated' + - '__OBJC_$_CATEGORY_Basic9_$_deprecated' + - '__OBJC_CLASS_RO_$_FooClass' + - '__OBJC_METACLASS_RO_$_FooClass' + - '__OBJC_$_PROTOCOL_INSTANCE_METHODS_BaseProtocol' + - '__OBJC_$_PROTOCOL_METHOD_TYPES_BaseProtocol' + - '__OBJC_$_PROTOCOL_REFS_FooProtocol' + - '__OBJC_$_PROTOCOL_INSTANCE_METHODS_FooProtocol' + - '__OBJC_$_PROTOCOL_METHOD_TYPES_FooProtocol' + - '__OBJC_$_PROTOCOL_INSTANCE_METHODS_BarProtocol' + - '__OBJC_$_PROTOCOL_METHOD_TYPES_BarProtocol' + - '__OBJC_CLASS_PROTOCOLS_$_FooClass' + - '__OBJC_$_INSTANCE_METHODS_FooClass' + - '__OBJC_$_CATEGORY_INSTANCE_METHODS_FooClass_$_Private' + - '__OBJC_$_PROTOCOL_INSTANCE_METHODS_PrivateProtocol' + - '__OBJC_$_PROTOCOL_METHOD_TYPES_PrivateProtocol' + - '__OBJC_CATEGORY_PROTOCOLS_$_FooClass_$_Private' + - '__OBJC_$_CATEGORY_FooClass_$_Private' + - _extraGlobalAPI1 + - _extraGlobalAPI2 + - _privateGlobalVariable + - _publicGlobalVariable + - '_OBJC_EHTYPE_$_Base' + - '_OBJC_EHTYPE_$_SubClass' + - '_OBJC_EHTYPE_$_SimpleInternalAPI' + - '_OBJC_EHTYPE_$_SimpleInternalSPI' + - '_OBJC_METACLASS_$_Simple' + - '_OBJC_CLASS_$_Simple' + - '_OBJC_METACLASS_$_Base' + - '_OBJC_CLASS_$_Base' + - '_OBJC_METACLASS_$_SubClass' + - '_OBJC_CLASS_$_SubClass' + - '_OBJC_METACLASS_$_SimpleInternalAPI' + - '_OBJC_CLASS_$_SimpleInternalAPI' + - '_OBJC_METACLASS_$_SimpleInternalSPI' + - '_OBJC_CLASS_$_SimpleInternalSPI' + - '_OBJC_CLASS_$_Basic1' + - '_OBJC_METACLASS_$_Basic1' + - '_OBJC_METACLASS_$_Basic2' + - '_OBJC_CLASS_$_Basic2' + - '_OBJC_METACLASS_$_Basic3' + - '_OBJC_CLASS_$_Basic3' + - '_OBJC_METACLASS_$_Basic4' + - '_OBJC_CLASS_$_Basic4' + - '_OBJC_METACLASS_$_Basic4_1' + - '_OBJC_CLASS_$_Basic4_1' + - '_OBJC_METACLASS_$_Basic4_2' + - '_OBJC_CLASS_$_Basic4_2' + - '_OBJC_METACLASS_$_Basic5' + - '_OBJC_CLASS_$_Basic5' + - '_OBJC_METACLASS_$_Basic6' + - '_OBJC_CLASS_$_Basic6' + - '_OBJC_METACLASS_$_Basic7' + - '_OBJC_CLASS_$_Basic7' + - '_OBJC_METACLASS_$_ExternalManagedObject' + - '_OBJC_CLASS_$_ExternalManagedObject' + - '_OBJC_METACLASS_$_HiddenClass' + - '_OBJC_CLASS_$_HiddenClass' + - '_OBJC_METACLASS_$_Basic8' + - '_OBJC_CLASS_$_Basic8' + - '_OBJC_METACLASS_$_A' + - '_OBJC_CLASS_$_A' + - '_OBJC_METACLASS_$_Basic9' + - '_OBJC_CLASS_$_Basic9' + - '_OBJC_CLASS_$_FooClass' + - '_OBJC_METACLASS_$_FooClass' + - '_OBJC_IVAR_$_Basic3.property1' + - '_OBJC_IVAR_$_Basic3.property2' + - '_OBJC_IVAR_$_Basic3.property3' + - '_OBJC_IVAR_$_Basic4.ivar1' + - '_OBJC_IVAR_$_Basic4.ivar2' + - '_OBJC_IVAR_$_Basic4.ivar3' + - '_OBJC_IVAR_$_Basic4.ivar4' + - '_OBJC_IVAR_$_Basic4_1.ivar1' + - '_OBJC_IVAR_$_Basic4_1.ivar2' + - '_OBJC_IVAR_$_Basic4_1.ivar3' + - '_OBJC_IVAR_$_Basic4_1.ivar4' + - '_OBJC_IVAR_$_Basic4_2.ivar4' + - '_OBJC_IVAR_$_Basic4_2.ivar3' + - '_OBJC_IVAR_$_Basic4_2.ivar2' + - '_OBJC_IVAR_$_Basic4_2.ivar1' + - '_OBJC_IVAR_$_Basic6.ivar1' + - '_OBJC_IVAR_$_Basic6.property1' + - '_OBJC_IVAR_$_Basic9._aProperty' + - '__OBJC_PROTOCOL_$_BaseProtocol' + - '__OBJC_PROTOCOL_$_FooProtocol' + - '__OBJC_PROTOCOL_$_BarProtocol' + - '__OBJC_PROTOCOL_$_PrivateProtocol' + - _weakPublicGlobalVariable + - _weakPrivateGlobalVariable + - '__OBJC_LABEL_PROTOCOL_$_BaseProtocol' + - '__OBJC_LABEL_PROTOCOL_$_FooProtocol' + - '__OBJC_LABEL_PROTOCOL_$_BarProtocol' + - '__OBJC_LABEL_PROTOCOL_$_PrivateProtocol' + - '_OBJC_CLASS_$_NSManagedObject' + - '_OBJC_CLASS_$_NSObject' + - '_OBJC_METACLASS_$_NSManagedObject' + - '_OBJC_METACLASS_$_NSObject' + - __objc_empty_cache + - _objc_ehtype_vtable + - dyld_stub_binder + - '' + - '' + FunctionStarts: [ 0x1BC0, 0x1BCA, 0x1BD3, 0x1BDD, 0x1BE7, 0x1BF0, 0x1BF6, + 0x1BFC, 0x1C02, 0x1C0C, 0x1C15, 0x1C20, 0x1C26, 0x1C2C, + 0x1C32, 0x1C38, 0x1C40, 0x1C46, 0x1C4C, 0x1C52, 0x1C5C, + 0x1C62, 0x1C68, 0x1C6E ] +... diff --git a/clang/test/InstallAPI/Inputs/Simple/SimpleInternalAPI.h b/clang/test/InstallAPI/Inputs/Simple/SimpleInternalAPI.h new file mode 100644 index 0000000000000000000000000000000000000000..5dd416a0619cfb1c5185a6c5be00af90a4d588e0 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/SimpleInternalAPI.h @@ -0,0 +1,3 @@ +#ifndef HAVE_SEEN_PROJECT_HEADER_FIRST +#error "Project header was not included in the correct order!" +#endif diff --git a/clang/test/InstallAPI/Inputs/Simple/SimpleInternalAPI2.h b/clang/test/InstallAPI/Inputs/Simple/SimpleInternalAPI2.h new file mode 100644 index 0000000000000000000000000000000000000000..9bbae52d721538588333ae0d4c15fd276b5e9bf1 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/SimpleInternalAPI2.h @@ -0,0 +1,7 @@ +#import + +__attribute__((objc_exception)) +@interface SimpleInternalAPI : NSObject +@end + +#define HAVE_SEEN_PROJECT_HEADER_FIRST 1 diff --git a/clang/test/InstallAPI/Inputs/Simple/SimpleInternalSPI.h b/clang/test/InstallAPI/Inputs/Simple/SimpleInternalSPI.h new file mode 100644 index 0000000000000000000000000000000000000000..a816c01abeb0d2c03303700417f89c07edfa1242 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/SimpleInternalSPI.h @@ -0,0 +1,5 @@ +#import + +__attribute__((objc_exception)) +@interface SimpleInternalSPI : NSObject +@end diff --git a/clang/test/InstallAPI/diagnostics-cpp.test b/clang/test/InstallAPI/diagnostics-cpp.test index 65888653750722a7d8dd8cf9fbbbceb95fa4c771..51cca129ea0af2fb0f8009e7c1eefea850a5dc1b 100644 --- a/clang/test/InstallAPI/diagnostics-cpp.test +++ b/clang/test/InstallAPI/diagnostics-cpp.test @@ -21,6 +21,8 @@ CHECK-NEXT: CPP.h:5:7: error: declaration has external linkage, but symbol has i CHECK-NEXT: CPP.h:6:7: error: dynamic library symbol '(weak-def) Bar::init()' is weak defined, but its declaration is not CHECK-NEXT: int init(); CHECK-NEXT: ^ +CHECK-NEXT: warning: violations found for arm64 +CHECK-NEXT: error: no declaration found for exported symbol 'int foo(unsigned int)' in dynamic library //--- inputs.json.in { diff --git a/clang/test/InstallAPI/extra-exclude-headers.test b/clang/test/InstallAPI/extra-exclude-headers.test new file mode 100644 index 0000000000000000000000000000000000000000..663ca1a5d5000d8bb8a486bba3951499da3b9bcc --- /dev/null +++ b/clang/test/InstallAPI/extra-exclude-headers.test @@ -0,0 +1,207 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: mkdir -p %t/System/Library/Frameworks +; RUN: cp -r %S/Inputs/Simple/Simple.framework %t/System/Library/Frameworks/ +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json +; RUN: yaml2obj %S/Inputs/Simple/Simple.yaml -o %t/Simple + +// Add exclude options. +; RUN: clang-installapi -target x86_64-apple-macosx10.12 \ +; RUN: -install_name /System/Library/Frameworks/Simple.framework/Versions/A/Simple \ +; RUN: -current_version 1.2.3 -compatibility_version 1 \ +; RUN: -F%t/System/Library/Frameworks \ +; RUN: %t/inputs.json -o %t/Simple.tbd \ +; RUN: --verify-against=%t/Simple --verify-mode=ErrorsAndWarnings \ +; RUN: --exclude-public-header=**/SimpleAPI.h \ +; RUN: --exclude-private-header=**/SimplePrivateSPI.h 2>&1 | FileCheck -check-prefix=WARNINGS %s +; RUN: llvm-readtapi -compare %t/Simple.tbd %t/expected-excluded.tbd + +// Add extra options. +; RUN: clang-installapi -target x86_64-apple-macosx10.12 \ +; RUN: -install_name /System/Library/Frameworks/Simple.framework/Versions/A/Simple \ +; RUN: -current_version 1.2.3 -compatibility_version 1 \ +; RUN: -F%t/System/Library/Frameworks \ +; RUN: %t/inputs.json -o %t/Simple.tbd \ +; RUN: --verify-against=%t/Simple --verify-mode=Pedantic \ +; RUN: --extra-project-header=%S/Inputs/Simple/SimpleInternalAPI2.h \ +; RUN: --extra-project-header=%S/Inputs/Simple/SimpleInternalAPI.h \ +; RUN: --extra-public-header=%S/Inputs/Simple/Extra \ +; RUN: --extra-private-header=%S/Inputs/Simple/SimpleInternalSPI.h \ +; RUN: --exclude-public-header=**/SimpleAPI.h \ +; RUN: --exclude-private-header=**/SimplePrivateSPI.h 2>&1 | FileCheck -check-prefix=PEDANTIC -allow-empty %s +; RUN: llvm-readtapi -compare %t/Simple.tbd %t/expected-extra.tbd + +// Check fatal missing file input. +; RUN: not clang-installapi -target x86_64-apple-macosx10.12 \ +; RUN: -install_name /System/Library/Frameworks/Simple.framework/Versions/A/Simple \ +; RUN: -current_version 1.2.3 -compatibility_version 1 \ +; RUN: -F%t/System/Library/Frameworks \ +; RUN: %t/inputs.json -o %t/Simple.tbd \ +; RUN: --extra-public-header=%S/Inputs/Simple/NoSuchFile.h 2>&1 | FileCheck -allow-empty -check-prefix=NOPUBLIC %s + +; WARNINGS: warning: no declaration was found for exported symbol '_extraGlobalAPI1' in dynamic library +; WARNINGS: warning: no declaration was found for exported symbol '_extraGlobalAPI2' in dynamic library +; WARNINGS: warning: no declaration was found for exported symbol '(ObjC Class) SimpleInternalSPI' in dynamic library +; WARNINGS: warning: no declaration was found for exported symbol '(ObjC Class) SimpleInternalAPI' in dynamic library + +; PEDANTIC-NOT: error +; PEDANTIC: warning: cannot find protocol definition for 'ForwardProcotol' + +; NOPUBLIC: error: no such public header file: + +;--- expected-excluded.tbd +{ + "main_library": { + "current_versions": [ + { + "version": "1.2.3" + } + ], + "exported_symbols": [ + { + "data": { + "global": [ + "_publicGlobalVariable", + "_privateGlobalVariable" + ], + "objc_class": [ + "ExternalManagedObject", "Basic6", + "Basic1", "Base", "Basic3", + "FooClass", "Simple", + "Basic4_2", "Basic5", + "Basic9","Basic8", + "Basic2", "Basic4", "A", "SubClass" + ], + "objc_eh_type": [ + "SubClass", "Base" + ], + "objc_ivar": [ + "Basic4.ivar2", "Basic4_2.ivar1", "Basic6.ivar1", + "Basic4.ivar1", "Basic4_2.ivar2" + ], + "weak": [ + "_weakPrivateGlobalVariable", "_weakPublicGlobalVariable" + ] + } + } + ], + "flags": [ + { + "attributes": ["not_app_extension_safe"] + } + ], + "install_names": [ + { + "name": "/System/Library/Frameworks/Simple.framework/Versions/A/Simple" + } + ], + "target_info": [ + {"min_deployment": "10.12", "target": "x86_64-macos"} + ] + }, + "tapi_tbd_version": 5 +} + +;--- expected-extra.tbd +{ + "main_library": { + "current_versions": [ + { "version": "1.2.3" } + ], + "exported_symbols": [ + { + "data": { + "global": [ + "_publicGlobalVariable", "_extraGlobalAPI2", + "_extraGlobalAPI1", "_privateGlobalVariable" + ], + "objc_class": [ + "SubClass", "SimpleInternalSPI", + "Basic6", "Basic1", "Base", + "Basic3", "Simple", "Basic4_2", + "Basic5", "FooClass", "Basic9", + "Basic8", "Basic2", "Basic4", + "A", "SimpleInternalAPI", + "ExternalManagedObject" + ], + "objc_eh_type": [ + "SubClass", "SimpleInternalAPI", + "Base", "SimpleInternalSPI" + ], + "objc_ivar": [ + "Basic4.ivar2", "Basic4_2.ivar1", + "Basic6.ivar1", "Basic4.ivar1", + "Basic4_2.ivar2" + ], + "weak": [ + "_weakPrivateGlobalVariable", "_weakPublicGlobalVariable" + ] + } + } + ], + "flags": [ + { + "attributes": [ "not_app_extension_safe"] + } + ], + "install_names": [ + { "name": "/System/Library/Frameworks/Simple.framework/Versions/A/Simple" } + ], + "target_info": [ + { "min_deployment": "10.12", "target": "x86_64-macos" } + ] + }, + "tapi_tbd_version": 5 +} + +;--- inputs.json.in +{ + "headers": [ + { + "path" : "DSTROOT/System/Library/Frameworks/Simple.framework/Headers/Basic.h", + "type" : "public" + }, + { + "path" : "DSTROOT/System/Library/Frameworks/Simple.framework/Headers/External.h", + "type" : "public" + }, + { + "path" : "DSTROOT/System/Library/Frameworks/Simple.framework/Headers/Simple.h", + "type" : "public" + }, + { + "path" : "DSTROOT/System/Library/Frameworks/Simple.framework/Headers/SimpleAPI.h", + "type" : "public" + }, + { + "path" : "DSTROOT/System/Library/Frameworks/Simple.framework/PrivateHeaders/SimplePrivate.h", + "type" : "private" + }, + { + "path" : "DSTROOT/System/Library/Frameworks/Simple.framework/PrivateHeaders/SimplePrivateSPI.h", + "type" : "private" + } + ], + "version": "3" +} + +;--- System/Library/Frameworks/Foundation.framework/Headers/Foundation.h +@interface NSObject +@end + +typedef unsigned char BOOL; +#ifndef NS_AVAILABLE +#define NS_AVAILABLE(x,y) __attribute__((availability(macosx,introduced=x))) +#endif +#ifndef NS_UNAVAILABLE +#define NS_UNAVAILABLE __attribute__((unavailable)) +#endif +#ifndef NS_DEPRECATED_MAC +#define NS_DEPRECATED_MAC(x,y) __attribute__((availability(macosx,introduced=x,deprecated=y,message="" ))); +#endif + +@interface NSManagedObject +@end + +@interface NSSet +@end diff --git a/clang/test/InstallAPI/linker-symbols.test b/clang/test/InstallAPI/linker-symbols.test new file mode 100644 index 0000000000000000000000000000000000000000..1e4ddf9c45d5dffe5566ee1057da3f49534c9627 --- /dev/null +++ b/clang/test/InstallAPI/linker-symbols.test @@ -0,0 +1,440 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json + +; RUN: yaml2obj %t/MagicSymbols.yaml -o %t/MagicSymbols + +; RUN: not clang-installapi -target x86_64-apple-macosx13 \ +; RUN: -install_name \ +; RUN: /System/Library/Frameworks/SpecialLinkerSymbols.framework/Versions/A/SpecialLinkerSymbols \ +; RUN: -current_version 1 -compatibility_version 1 \ +; RUN: %t/inputs.json -o %t/output.tbd \ +; RUN: --verify-mode=ErrorsOnly \ +; RUN: --verify-against=%t/MagicSymbols 2>&1 | FileCheck %s + +CHECK: warning: violations found for x86_64 +CHECK: error: no declaration found for exported symbol '$ld$add$os10.4$_symbol2' in dynamic library +CHECK: error: no declaration found for exported symbol '$ld$add$os10.5$_symbol2' in dynamic library +CHECK: error: no declaration found for exported symbol '$ld$hide$os10.6$_symbol1' in dynamic library +CHECK: error: no declaration found for exported symbol '$ld$hide$os10.7$_symbol1' in dynamic library +CHECK: error: no declaration found for exported symbol '$ld$weak$os10.5$_symbol3' in dynamic library +CHECK: error: no declaration found for exported symbol '$ld$weak$os10.4$_symbol3' in dynamic library +CHECK: error: no declaration found for exported symbol '$ld$install_name$os10.4$/System/Library/Frameworks/A.framework/Versions/A/A' in dynamic library +CHECK: error: no declaration found for exported symbol '$ld$install_name$os10.5$/System/Library/Frameworks/B.framework/Versions/A/B' in dynamic library + +;--- MagicSymbols.h +#ifndef SPECIAL_LINKER_SYMBOLS_H +#define SPECIAL_LINKER_SYMBOLS_H + +extern const int SpecialLinkerSymbolsVersion; + +extern int symbol1; +extern int symbol3; + +#endif // SPECIAL_LINKER_SYMBOLS_H + +;--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/MagicSymbols.h", + "type" : "project" + } + ], + "version": "3" +} + +;--- MagicSymbols.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x6 + ncmds: 12 + sizeofcmds: 952 + flags: 0x100085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __TEXT + vmaddr: 0 + vmsize: 4096 + fileoff: 0 + filesize: 4096 + maxprot: 5 + initprot: 5 + nsects: 2 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0xBD8 + size: 0 + offset: 0xBD8 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x80000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '' + - sectname: __const + segname: __TEXT + addr: 0xBD8 + size: 4 + offset: 0xBD8 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '07000000' + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __DATA + vmaddr: 4096 + vmsize: 4096 + fileoff: 4096 + filesize: 4096 + maxprot: 3 + initprot: 3 + nsects: 2 + flags: 0 + Sections: + - sectname: __data + segname: __DATA + addr: 0x1000 + size: 8 + offset: 0x1000 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 4D00000009030000 + - sectname: __common + segname: __DATA + addr: 0x1008 + size: 8 + offset: 0x0 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x1 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 8192 + vmsize: 944 + fileoff: 8192 + filesize: 944 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 0 + rebase_size: 0 + bind_off: 0 + bind_size: 0 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 8192 + export_size: 376 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 8576 + nsyms: 12 + stroff: 8768 + strsize: 368 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 0 + iextdefsym: 0 + nextdefsym: 11 + iundefsym: 11 + nundefsym: 1 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 120 + dylib: + name: 24 + timestamp: 0 + current_version: 65536 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/SpecialLinkerSymbols.framework/Versions/A/SpecialLinkerSymbols' + ZeroPadBytes: 7 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C4478-5555-3144-A106-356C3C9DACA3 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 851968 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88539136 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 8568 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 8576 + datasize: 0 +LinkEditData: + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 11 + Name: _ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 50 + Name: SpecialLinkerSymbolsVersion + Flags: 0x0 + Address: 0xBD8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 55 + Name: symbol + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 63 + Name: '3' + Flags: 0x0 + Address: 0x1004 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 68 + Name: '1' + Flags: 0x0 + Address: 0x1000 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 73 + Name: '$ld$' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 134 + Name: 'add$os10.' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 162 + Name: '4$_symbol2' + Flags: 0x0 + Address: 0x1008 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 167 + Name: '5$_symbol2' + Flags: 0x0 + Address: 0x1009 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 172 + Name: 'hide$os10.' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 200 + Name: '6$_symbol1' + Flags: 0x0 + Address: 0x100A + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 205 + Name: '7$_symbol1' + Flags: 0x0 + Address: 0x100B + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 210 + Name: 'weak$os10.' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 238 + Name: '5$_symbol3' + Flags: 0x0 + Address: 0x100F + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 243 + Name: '4$_symbol3' + Flags: 0x0 + Address: 0x100E + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 248 + Name: 'install_name$os10.' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 362 + Name: '4$/System/Library/Frameworks/A.framework/Versions/A/A' + Flags: 0x0 + Address: 0x100C + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 367 + Name: '5$/System/Library/Frameworks/B.framework/Versions/A/B' + Flags: 0x0 + Address: 0x100D + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 2 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4104 + - n_strx: 26 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4105 + - n_strx: 50 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4106 + - n_strx: 75 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4107 + - n_strx: 100 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4108 + - n_strx: 176 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4109 + - n_strx: 252 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4110 + - n_strx: 277 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4111 + - n_strx: 302 + n_type: 0xF + n_sect: 2 + n_desc: 0 + n_value: 3032 + - n_strx: 331 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 4096 + - n_strx: 340 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 4100 + - n_strx: 349 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + StringTable: + - ' ' + - '$ld$add$os10.4$_symbol2' + - '$ld$add$os10.5$_symbol2' + - '$ld$hide$os10.6$_symbol1' + - '$ld$hide$os10.7$_symbol1' + - '$ld$install_name$os10.4$/System/Library/Frameworks/A.framework/Versions/A/A' + - '$ld$install_name$os10.5$/System/Library/Frameworks/B.framework/Versions/A/B' + - '$ld$weak$os10.4$_symbol3' + - '$ld$weak$os10.5$_symbol3' + - _SpecialLinkerSymbolsVersion + - _symbol1 + - _symbol3 + - dyld_stub_binder + - '' + - '' +... diff --git a/clang/test/InstallAPI/mismatching-objc-class-symbols.test b/clang/test/InstallAPI/mismatching-objc-class-symbols.test new file mode 100644 index 0000000000000000000000000000000000000000..3b4acf1035ace382956431fcd944a2cf49ba1e08 --- /dev/null +++ b/clang/test/InstallAPI/mismatching-objc-class-symbols.test @@ -0,0 +1,269 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json +; RUN: yaml2obj %t/swift-objc-class.yaml -o %t/libswift-objc.dylib + +// Try out dylib that only has 1 symbol for a ObjCClass, with no declarations in header. +; RUN: clang-installapi -target arm64-apple-macos14 -dynamiclib \ +; RUN: -install_name tmp.dylib --verify-against=%t/libswift-objc.dylib \ +; RUN: -I%t/usr/include %t/inputs.json -o %t/missing.tbd \ +; RUN: --verify-mode=ErrorsAndWarnings 2>&1 | FileCheck --check-prefix MISSING_DECL %s +; RUN: llvm-readtapi --compare %t/missing.tbd %t/missing-expected.tbd + +// Try out a dylib that only has 1 symbol for a ObjCClass, +// but a complete ObjCClass decl in header. +; RUN: clang-installapi -target arm64-apple-macos14 -dynamiclib \ +; RUN: -install_name tmp.dylib --verify-against=%t/libswift-objc.dylib \ +; RUN: -I%t/usr/include %t/inputs.json -o %t/mismatching.tbd \ +; RUN: --verify-mode=Pedantic -DFULL_DECL 2>&1 | FileCheck --check-prefix MISMATCH_DECL %s +; RUN: llvm-readtapi -compare %t/mismatching.tbd %t/mismatching-expected.tbd + +// Try out a dylib that only has 1 symbol for a ObjCClass, but is represented in header. +; RUN: clang-installapi -target arm64-apple-macos14 \ +; RUN: -install_name tmp.dylib --verify-against=%t/libswift-objc.dylib \ +; RUN: -I%t/usr/include %t/inputs.json -o %t/matching.tbd \ +; RUN: --verify-mode=Pedantic \ +; RUN: -DHAS_META_DECL 2>&1 | FileCheck --allow-empty %s + +; MISSING_DECL: violations found for arm64 +; MISSING_DECL-NEXT: warning: no declaration was found for exported symbol 'Metaclass of Suggestion' in dynamic library + +; MISMATCH_DECL: violations found for arm64-apple-macos14 +; MISMATCH_DECL: warning: declaration has external linkage, but dynamic library doesn't have symbol 'Class of Suggestion' + +; CHECK-NOT: error +; CHECK-NOT: warning + + +;--- usr/include/mismatch.h +#if HAS_META_DECL +int metaclass __asm("_OBJC_METACLASS_$_Suggestion"); +#endif + +#if FULL_DECL +@interface Suggestion +@end +#endif + +;--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/usr/include/mismatch.h", + "type" : "public" + } + ], + "version": "3" +} + +;--- missing-expected.tbd +--- !tapi-tbd +tbd-version: 4 +targets: [ arm64-macos ] +flags: [ not_app_extension_safe ] +install-name: tmp.dylib +current-version: 0 +compatibility-version: 0 +... + +;--- mismatching-expected.tbd +--- !tapi-tbd +tbd-version: 4 +targets: [ arm64-macos ] +flags: [ not_app_extension_safe ] +install-name: tmp.dylib +current-version: 0 +compatibility-version: 0 +exports: + - targets: [ arm64-macos ] + objc-classes: [ Suggestion ] +... + +;--- swift-objc-class.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x100000C + cpusubtype: 0x0 + filetype: 0x6 + ncmds: 13 + sizeofcmds: 752 + flags: 0x100085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __TEXT + vmaddr: 0 + vmsize: 16384 + fileoff: 0 + filesize: 16384 + maxprot: 5 + initprot: 5 + nsects: 2 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x330 + size: 0 + offset: 0x330 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x80000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '' + - sectname: __const + segname: __TEXT + addr: 0x330 + size: 1 + offset: 0x330 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '61' + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 16384 + vmsize: 416 + fileoff: 16384 + filesize: 416 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 0 + rebase_size: 0 + bind_off: 0 + bind_size: 0 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 16384 + export_size: 40 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 16432 + nsyms: 2 + stroff: 16464 + strsize: 48 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 0 + iextdefsym: 0 + nextdefsym: 1 + iundefsym: 1 + nundefsym: 1 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 40 + dylib: + name: 24 + timestamp: 0 + current_version: 0 + compatibility_version: 0 + Content: tmp.dylib + ZeroPadBytes: 7 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C4443-5555-3144-A142-97179769CBE0 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 917504 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 96 + dylib: + name: 24 + timestamp: 0 + current_version: 197656576 + compatibility_version: 19660800 + Content: '/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation' + ZeroPadBytes: 3 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88473600 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 16424 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 16432 + datasize: 0 + - cmd: LC_CODE_SIGNATURE + cmdsize: 16 + dataoff: 16512 + datasize: 288 +LinkEditData: + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 32 + Name: '_OBJC_METACLASS_$_Suggestion' + Flags: 0x0 + Address: 0x330 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 2 + n_type: 0xF + n_sect: 2 + n_desc: 0 + n_value: 816 + - n_strx: 31 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + StringTable: + - ' ' + - '_OBJC_METACLASS_$_Suggestion' + - dyld_stub_binder + FunctionStarts: [ 0x330 ] +... +// Generated from: +// xcrun -sdk macosx clang tmp.c -dynamiclib -install_name tmp.dylib +// tmp.c: +// __attribute__((visibility("default"))) +// const char Meta __asm("_OBJC_METACLASS_$_Suggestion") = 'a'; diff --git a/clang/test/InstallAPI/symbol-flags.test b/clang/test/InstallAPI/symbol-flags.test new file mode 100644 index 0000000000000000000000000000000000000000..3f68afd17e3b2009135ca04ee0edb758cdba0f0e --- /dev/null +++ b/clang/test/InstallAPI/symbol-flags.test @@ -0,0 +1,290 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json + +; RUN: yaml2obj %t/flags.yaml -o %t/SymbolFlags + +; RUN: not clang-installapi -x c++ --target=arm64-apple-macos13 \ +; RUN: -install_name /System/Library/Frameworks/SymbolFlags.framework/Versions/A/SymbolFlags \ +; RUN: -current_version 1 -compatibility_version 1 \ +; RUN: %t/inputs.json -o output.tbd \ +; RUN: --verify-against=%t/SymbolFlags \ +; RUN: --verify-mode=ErrorsOnly 2>&1 | FileCheck %s + +; CHECK: project.h:2:21: error: declaration '(tlv) val' is thread local, but symbol is not in dynamic library +; CHECK-NEXT: extern __thread int val; +; CHECK: project.h:3:13: error: dynamic library symbol '(weak-def) __Z12my_weak_funcv' is weak defined, but its declaration is not +; CHECK-NEXT: extern void my_weak_func(); + +;--- project.h +extern void my_func(); +extern __thread int val; +extern void my_weak_func(); + +;--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/project.h", + "type" : "project" + } + ], + "version": "3" +} + +;--- flags.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x100000C + cpusubtype: 0x0 + filetype: 0x6 + ncmds: 14 + sizeofcmds: 912 + flags: 0x118085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __TEXT + vmaddr: 0 + vmsize: 16384 + fileoff: 0 + filesize: 16384 + maxprot: 5 + initprot: 5 + nsects: 2 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0xFB0 + size: 8 + offset: 0xFB0 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: C0035FD6C0035FD6 + - sectname: __unwind_info + segname: __TEXT + addr: 0xFB8 + size: 4152 + offset: 0xFB8 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000001C000000010000002000000000000000200000000200000000000002B00F00003800000038000000B80F00000000000038000000030000000C0001001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DATA + vmaddr: 16384 + vmsize: 16384 + fileoff: 16384 + filesize: 0 + maxprot: 3 + initprot: 3 + nsects: 1 + flags: 0 + Sections: + - sectname: __common + segname: __DATA + addr: 0x4000 + size: 4 + offset: 0x0 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x1 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 32768 + vmsize: 480 + fileoff: 16384 + filesize: 480 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 0 + rebase_size: 0 + bind_off: 0 + bind_size: 0 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 16384 + export_size: 64 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 16456 + nsyms: 4 + stroff: 16520 + strsize: 56 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 0 + iextdefsym: 0 + nextdefsym: 3 + iundefsym: 3 + nundefsym: 1 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 96 + dylib: + name: 24 + timestamp: 0 + current_version: 65536 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/SymbolFlags.framework/Versions/A/SymbolFlags' + ZeroPadBytes: 1 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C4436-5555-3144-A1AF-5D3063ACFC99 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 851968 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 48 + dylib: + name: 24 + timestamp: 0 + current_version: 117985024 + compatibility_version: 65536 + Content: '/usr/lib/libc++.1.dylib' + ZeroPadBytes: 1 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88473600 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 16448 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 16456 + datasize: 0 + - cmd: LC_CODE_SIGNATURE + cmdsize: 16 + dataoff: 16576 + datasize: 288 +LinkEditData: + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 5 + Name: _ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 16 + Name: val + Flags: 0x0 + Address: 0x4000 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 22 + Name: _Z + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 52 + Name: 7my_funcv + Flags: 0x0 + Address: 0xFB0 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 57 + Name: 12my_weak_funcv + Flags: 0x4 + Address: 0xFB4 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 2 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4016 + - n_strx: 15 + n_type: 0xF + n_sect: 1 + n_desc: 128 + n_value: 4020 + - n_strx: 34 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 16384 + - n_strx: 39 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + StringTable: + - ' ' + - __Z7my_funcv + - __Z12my_weak_funcv + - _val + - dyld_stub_binder + FunctionStarts: [ 0xFB0, 0xFB4 ] +... + +/// Generated from: +// clang++ -mtargetos=macosx13 -arch arm64 flags.cpp +// flags.cpp: +// __attribute__((visibility("default"))) void my_func() {} +// __attribute__((weak)) void my_weak_func() {} +// int val = 0; diff --git a/clang/test/Sema/aarch64-sme-func-attrs.c b/clang/test/Sema/aarch64-sme-func-attrs.c index 47dbeca206a94e67b02004f3dda2c6677aafb77a..bfc8768c3f36e1c0c07cf1b1362275870aca2323 100644 --- a/clang/test/Sema/aarch64-sme-func-attrs.c +++ b/clang/test/Sema/aarch64-sme-func-attrs.c @@ -483,14 +483,16 @@ void just_fine(void) {} __arm_locally_streaming __attribute__((target_version("sme2"))) -void just_fine_locally_streaming(void) {} +void incompatible_locally_streaming(void) {} +// expected-error@-1 {{attribute 'target_version' multiversioning cannot be combined with attribute '__arm_locally_streaming'}} +// expected-cpp-error@-2 {{attribute 'target_version' multiversioning cannot be combined with attribute '__arm_locally_streaming'}} __attribute__((target_version("default"))) -void just_fine_locally_streaming(void) {} +void incompatible_locally_streaming(void) {} void fmv_caller() { cannot_work_version(); cannot_work_clones(); just_fine(); - just_fine_locally_streaming(); + incompatible_locally_streaming(); } diff --git a/clang/test/Sema/attr-target-version.c b/clang/test/Sema/attr-target-version.c index e2940c434c2ff5f2528a1eb1947efecb73022b33..cd5be459456eb70e6a15ea2ecf32caab4c21ba32 100644 --- a/clang/test/Sema/attr-target-version.c +++ b/clang/test/Sema/attr-target-version.c @@ -68,13 +68,15 @@ int __attribute__((target_version(""))) unsup1(void) { return 1; } void __attribute__((target_version("crc32"))) unsup2(void) {} void __attribute__((target_version("default+fp16"))) koo(void) {} +//expected-error@-1 {{function multiversioning doesn't support feature 'default'}} void __attribute__((target_version("default+default+default"))) loo(void) {} +//expected-error@-1 {{function multiversioning doesn't support feature 'default'}} void __attribute__((target_version("rdm+rng+crc"))) redef(void) {} //expected-error@+2 {{redefinition of 'redef'}} //expected-note@-2 {{previous definition is here}} void __attribute__((target_version("rdm+rng+crc"))) redef(void) {} -int __attribute__((target_version("sm4"))) def(void); +int def(void); void __attribute__((target_version("dit"))) nodef(void); void __attribute__((target_version("ls64"))) nodef(void); void __attribute__((target_version("aes"))) ovl(void); @@ -83,7 +85,6 @@ int bar() { // expected-error@+2 {{reference to overloaded function could not be resolved; did you mean to call it?}} // expected-note@-3 {{possible target for call}} ovl++; - // expected-error@+1 {{no matching function for call to 'nodef'}} nodef(); return def(); } @@ -92,8 +93,6 @@ int __attribute__((target_version("sha1"))) def(void) { return 1; } int __attribute__((target_version("sve"))) prot(); // expected-error@-1 {{multiversioned function must have a prototype}} -// expected-note@+1 {{function multiversioning caused by this declaration}} -int __attribute__((target_version("fcma"))) prot(); int __attribute__((target_version("pmull"))) rtype(int); // expected-error@+1 {{multiversioned function declaration has a different return type}} @@ -104,6 +103,7 @@ int __attribute__((target_version("sha2"))) combine(void) { return 1; } int __attribute__((aarch64_vector_pcs, target_version("sha3"))) combine(void) { return 2; } int __attribute__((target_version("fp+aes+pmull+rcpc"))) unspec_args() { return -1; } +// expected-error@-1 {{multiversioned function must have a prototype}} // expected-error@+1 {{multiversioned function must have a prototype}} int __attribute__((target_version("default"))) unspec_args() { return 0; } int cargs() { return unspec_args(); } diff --git a/clang/test/SemaCXX/attr-target-version.cpp b/clang/test/SemaCXX/attr-target-version.cpp index 0bd710c4e282ad3d4d850143f7fdce454c2a8f3f..b3385f043590f84ca7574992bc92abb27ba5e06b 100644 --- a/clang/test/SemaCXX/attr-target-version.cpp +++ b/clang/test/SemaCXX/attr-target-version.cpp @@ -9,7 +9,6 @@ void __attribute__((target_version("rcpc3"))) no_def(void); void __attribute__((target_version("mops"))) no_def(void); void __attribute__((target_version("rdma"))) no_def(void); -// expected-error@+1 {{no matching function for call to 'no_def'}} void foo(void) { no_def(); } constexpr int __attribute__((target_version("sve2"))) diff_const(void) { return 1; } @@ -41,6 +40,7 @@ inline int __attribute__((target_version("sme"))) diff_inline(void) { return 1; int __attribute__((target_version("fp16"))) diff_inline(void) { return 2; } inline int __attribute__((target_version("sme"))) diff_inline1(void) { return 1; } +//expected-error@+1 {{multiversioned function declaration has a different inline specification}} int __attribute__((target_version("default"))) diff_inline1(void) { return 2; } int __attribute__((target_version("fcma"))) diff_type1(void) { return 1; } @@ -59,8 +59,7 @@ int __attribute__((target_version("sve2-sha3"))) diff_type3(void) noexcept(true) template int __attribute__((target_version("default"))) temp(T) { return 1; } template int __attribute__((target_version("simd"))) temp1(T) { return 1; } -// expected-error@+1 {{attribute 'target_version' multiversioned functions do not yet support function templates}} -template int __attribute__((target_version("sha3"))) temp1(T) { return 2; } +// expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support function templates}} extern "C" { int __attribute__((target_version("aes"))) extc(void) { return 1; } @@ -70,17 +69,23 @@ int __attribute__((target_version("lse"))) extc(void) { return 1; } auto __attribute__((target_version("default"))) ret1(void) { return 1; } auto __attribute__((target_version("dpb"))) ret2(void) { return 1; } +// expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support deduced return types}} auto __attribute__((target_version("dpb2"))) ret3(void) -> int { return 1; } class Cls { __attribute__((target_version("rng"))) Cls(); + // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support constructors}} __attribute__((target_version("sve-i8mm"))) ~Cls(); + // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support destructors}} Cls &__attribute__((target_version("f32mm"))) operator=(const Cls &) = default; + // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support defaulted functions}} Cls &__attribute__((target_version("ssbs"))) operator=(Cls &&) = delete; + // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support deleted functions}} virtual void __attribute__((target_version("default"))) vfunc(); virtual void __attribute__((target_version("sm4"))) vfunc1(); + // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support virtual functions}} }; __attribute__((target_version("sha3"))) void Decl(); diff --git a/clang/test/SemaCXX/namespace-alias.cpp b/clang/test/SemaCXX/namespace-alias.cpp index 281ee9962e8b52e3457ee0f6565f17efab624d06..591957a657c03a9bdb8777501df4791359893b0a 100644 --- a/clang/test/SemaCXX/namespace-alias.cpp +++ b/clang/test/SemaCXX/namespace-alias.cpp @@ -47,6 +47,8 @@ namespace I { namespace A1 { int i; } namespace A2 = A1; + + namespace A3::extra::specifiers = A2; // expected-error {{alias must be a single identifier}} } int f() { diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp index 54e82d78d4d228d24c569da99d82c30c1963b4fe..13061cfa36eeb0a7ea8b2ed992965500cdcb4309 100644 --- a/clang/tools/clang-installapi/ClangInstallAPI.cpp +++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp @@ -123,7 +123,7 @@ static bool run(ArrayRef Args, const char *ProgName) { } } - if (Ctx.Verifier->getState() == DylibVerifier::Result::Invalid) + if (Ctx.Verifier->verifyRemainingSymbols() == DylibVerifier::Result::Invalid) return EXIT_FAILURE; // After symbols have been collected, prepare to write output. diff --git a/clang/tools/clang-installapi/InstallAPIOpts.td b/clang/tools/clang-installapi/InstallAPIOpts.td index 87f4c3327e8409bd2771ca79802efa36b59039e0..ab9e1fe7f2f949af6abd190dfea7ea7627f4f25f 100644 --- a/clang/tools/clang-installapi/InstallAPIOpts.td +++ b/clang/tools/clang-installapi/InstallAPIOpts.td @@ -29,3 +29,35 @@ def verify_mode_EQ : Joined<["--"], "verify-mode=">, HelpText<"Specify the severity and extend of the validation. Valid modes are ErrorsOnly, ErrorsAndWarnings, and Pedantic.">; def demangle : Flag<["--", "-"], "demangle">, HelpText<"Demangle symbols when printing warnings and errors">; + +// Additional input options. +def extra_project_header : Separate<["-"], "extra-project-header">, + MetaVarName<"">, + HelpText<"Add additional project header location for parsing">; +def extra_project_header_EQ : Joined<["--"], "extra-project-header=">, + Alias; +def exclude_project_header : Separate<["-"], "exclude-project-header">, + MetaVarName<"">, + HelpText<"Exclude project header from parsing">; +def exclude_project_header_EQ : Joined<["--"], "exclude-project-header=">, + Alias; +def extra_public_header : Separate<["-"], "extra-public-header">, + MetaVarName<"">, + HelpText<"Add additional public header location for parsing">; +def extra_public_header_EQ : Joined<["--"], "extra-public-header=">, + Alias; +def extra_private_header : Separate<["-"], "extra-private-header">, + MetaVarName<"">, + HelpText<"Add additional private header location for parsing">; +def extra_private_header_EQ : Joined<["--"], "extra-private-header=">, + Alias; +def exclude_public_header : Separate<["-"], "exclude-public-header">, + MetaVarName<"">, + HelpText<"Exclude public header from parsing">; +def exclude_public_header_EQ : Joined<["--"], "exclude-public-header=">, + Alias; +def exclude_private_header : Separate<["-"], "exclude-private-header">, + MetaVarName<"">, + HelpText<"Exclude private header from parsing">; +def exclude_private_header_EQ : Joined<["--"], "exclude-private-header=">, + Alias; diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp index b8696bb7896d8662fec1782fcdb5ba42b1f87407..4f79c62724a62d58763e56463bde61343f477d67 100644 --- a/clang/tools/clang-installapi/Options.cpp +++ b/clang/tools/clang-installapi/Options.cpp @@ -10,6 +10,7 @@ #include "clang/Driver/Driver.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/InstallAPI/FileList.h" +#include "clang/InstallAPI/HeaderFile.h" #include "clang/InstallAPI/InstallAPIDiagnostic.h" #include "llvm/Support/Program.h" #include "llvm/TargetParser/Host.h" @@ -181,6 +182,26 @@ bool Options::processFrontendOptions(InputArgList &Args) { return true; } +bool Options::addFilePaths(InputArgList &Args, PathSeq &Headers, + OptSpecifier ID) { + for (const StringRef Path : Args.getAllArgValues(ID)) { + if ((bool)FM->getDirectory(Path, /*CacheFailure=*/false)) { + auto InputHeadersOrErr = enumerateFiles(*FM, Path); + if (!InputHeadersOrErr) { + Diags->Report(diag::err_cannot_open_file) + << Path << toString(InputHeadersOrErr.takeError()); + return false; + } + // Sort headers to ensure deterministic behavior. + sort(*InputHeadersOrErr); + for (std::string &H : *InputHeadersOrErr) + Headers.emplace_back(std::move(H)); + } else + Headers.emplace_back(Path); + } + return true; +} + std::vector Options::processAndFilterOutInstallAPIOptions(ArrayRef Args) { std::unique_ptr Table; @@ -220,6 +241,35 @@ Options::processAndFilterOutInstallAPIOptions(ArrayRef Args) { if (const Arg *A = ParsedArgs.getLastArg(OPT_verify_against)) DriverOpts.DylibToVerify = A->getValue(); + // Handle exclude & extra header directories or files. + auto handleAdditionalInputArgs = [&](PathSeq &Headers, + clang::installapi::ID OptID) { + if (ParsedArgs.hasArgNoClaim(OptID)) + Headers.clear(); + return addFilePaths(ParsedArgs, Headers, OptID); + }; + + if (!handleAdditionalInputArgs(DriverOpts.ExtraPublicHeaders, + OPT_extra_public_header)) + return {}; + + if (!handleAdditionalInputArgs(DriverOpts.ExtraPrivateHeaders, + OPT_extra_private_header)) + return {}; + if (!handleAdditionalInputArgs(DriverOpts.ExtraProjectHeaders, + OPT_extra_project_header)) + return {}; + + if (!handleAdditionalInputArgs(DriverOpts.ExcludePublicHeaders, + OPT_exclude_public_header)) + return {}; + if (!handleAdditionalInputArgs(DriverOpts.ExcludePrivateHeaders, + OPT_exclude_private_header)) + return {}; + if (!handleAdditionalInputArgs(DriverOpts.ExcludeProjectHeaders, + OPT_exclude_project_header)) + return {}; + /// Any unclaimed arguments should be forwarded to the clang driver. std::vector ClangDriverArgs(ParsedArgs.size()); for (const Arg *A : ParsedArgs) { @@ -302,6 +352,77 @@ InstallAPIContext Options::createContext() { return Ctx; } } + // After initial input has been processed, add any extra headers. + auto HandleExtraHeaders = [&](PathSeq &Headers, HeaderType Type) -> bool { + assert(Type != HeaderType::Unknown && "Missing header type."); + for (const StringRef Path : Headers) { + if (!FM->getOptionalFileRef(Path)) { + Diags->Report(diag::err_no_such_header_file) + << Path << (unsigned)Type - 1; + return false; + } + SmallString FullPath(Path); + FM->makeAbsolutePath(FullPath); + + auto IncludeName = createIncludeHeaderName(FullPath); + Ctx.InputHeaders.emplace_back( + FullPath, Type, IncludeName.has_value() ? *IncludeName : ""); + Ctx.InputHeaders.back().setExtra(); + } + return true; + }; + + if (!HandleExtraHeaders(DriverOpts.ExtraPublicHeaders, HeaderType::Public) || + !HandleExtraHeaders(DriverOpts.ExtraPrivateHeaders, + HeaderType::Private) || + !HandleExtraHeaders(DriverOpts.ExtraProjectHeaders, HeaderType::Project)) + return Ctx; + + // After all headers have been added, consider excluded headers. + std::vector> ExcludedHeaderGlobs; + std::set ExcludedHeaderFiles; + auto ParseGlobs = [&](const PathSeq &Paths, HeaderType Type) { + for (const StringRef Path : Paths) { + auto Glob = HeaderGlob::create(Path, Type); + if (Glob) + ExcludedHeaderGlobs.emplace_back(std::move(Glob.get())); + else { + consumeError(Glob.takeError()); + if (auto File = FM->getFileRef(Path)) + ExcludedHeaderFiles.emplace(*File); + else { + Diags->Report(diag::err_no_such_header_file) + << Path << (unsigned)Type; + return false; + } + } + } + return true; + }; + + if (!ParseGlobs(DriverOpts.ExcludePublicHeaders, HeaderType::Public) || + !ParseGlobs(DriverOpts.ExcludePrivateHeaders, HeaderType::Private) || + !ParseGlobs(DriverOpts.ExcludeProjectHeaders, HeaderType::Project)) + return Ctx; + + for (HeaderFile &Header : Ctx.InputHeaders) { + for (auto &Glob : ExcludedHeaderGlobs) + if (Glob->match(Header)) + Header.setExcluded(); + } + if (!ExcludedHeaderFiles.empty()) { + for (HeaderFile &Header : Ctx.InputHeaders) { + auto FileRef = FM->getFileRef(Header.getPath()); + if (!FileRef) + continue; + if (ExcludedHeaderFiles.count(*FileRef)) + Header.setExcluded(); + } + } + // Report if glob was ignored. + for (const auto &Glob : ExcludedHeaderGlobs) + if (!Glob->didMatch()) + Diags->Report(diag::warn_glob_did_not_match) << Glob->str(); // Parse binary dylib and initialize verifier. if (DriverOpts.DylibToVerify.empty()) { diff --git a/clang/tools/clang-installapi/Options.h b/clang/tools/clang-installapi/Options.h index 2beeafc86bb086ef888990dee6373d17ae13b409..c18309f693701eacbab9180f3387ee44a36ed4aa 100644 --- a/clang/tools/clang-installapi/Options.h +++ b/clang/tools/clang-installapi/Options.h @@ -31,6 +31,24 @@ struct DriverOptions { /// \brief Path to input file lists (JSON). llvm::MachO::PathSeq FileLists; + /// \brief Paths of extra public headers. + PathSeq ExtraPublicHeaders; + + /// \brief Paths of extra private headers. + PathSeq ExtraPrivateHeaders; + + /// \brief Paths of extra project headers. + PathSeq ExtraProjectHeaders; + + /// \brief List of excluded public headers. + PathSeq ExcludePublicHeaders; + + /// \brief List of excluded private headers. + PathSeq ExcludePrivateHeaders; + + /// \brief List of excluded project headers. + PathSeq ExcludeProjectHeaders; + /// \brief Mappings of target triples & tapi targets to build for. std::map Targets; @@ -103,6 +121,9 @@ public: std::vector &getClangFrontendArgs() { return FrontendArgs; } private: + bool addFilePaths(llvm::opt::InputArgList &Args, PathSeq &Headers, + llvm::opt::OptSpecifier ID); + DiagnosticsEngine *Diags; FileManager *FM; std::vector FrontendArgs; diff --git a/clang/unittests/Analysis/FlowSensitive/DeterminismTest.cpp b/clang/unittests/Analysis/FlowSensitive/DeterminismTest.cpp index e794bd4943f23226bf76756dd36a24a116a3204a..a2cbfb1ff5826baa194826f7f52a45e16b9e660b 100644 --- a/clang/unittests/Analysis/FlowSensitive/DeterminismTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/DeterminismTest.cpp @@ -30,7 +30,9 @@ namespace clang::dataflow { // flow-condition at function exit. std::string analyzeAndPrintExitCondition(llvm::StringRef Code) { DataflowAnalysisContext DACtx(std::make_unique()); - clang::TestAST AST(Code); + TestInputs Inputs(Code); + Inputs.Language = TestLanguage::Lang_CXX17; + clang::TestAST AST(Inputs); const auto *Target = cast(test::findValueDecl(AST.context(), "target")); Environment InitEnv(DACtx, *Target); diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 1d3b268976a767e8781a2c52144f11b4456873f7..ca055a462a28660e61025738b8e8a727f717827e 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -17,6 +17,7 @@ #include "clang/Analysis/FlowSensitive/StorageLocation.h" #include "clang/Analysis/FlowSensitive/Value.h" #include "clang/Basic/LangStandard.h" +#include "clang/Testing/TestAST.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Testing/Support/Error.h" @@ -135,12 +136,32 @@ const Formula &getFormula(const ValueDecl &D, const Environment &Env) { } TEST(TransferTest, CNotSupported) { - std::string Code = R"( - void target() {} - )"; - ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis( - Code, [](const auto &, auto &) {}, {BuiltinOptions{}}, - LangStandard::lang_c89), + TestInputs Inputs("void target() {}"); + Inputs.Language = TestLanguage::Lang_C89; + clang::TestAST AST(Inputs); + const auto *Target = + cast(test::findValueDecl(AST.context(), "target")); + ASSERT_THAT_ERROR(AdornedCFG::build(*Target).takeError(), + llvm::FailedWithMessage("Can only analyze C++")); +} + +TEST(TransferTest, ObjectiveCNotSupported) { + TestInputs Inputs("void target() {}"); + Inputs.Language = TestLanguage::Lang_OBJC; + clang::TestAST AST(Inputs); + const auto *Target = + cast(test::findValueDecl(AST.context(), "target")); + ASSERT_THAT_ERROR(AdornedCFG::build(*Target).takeError(), + llvm::FailedWithMessage("Can only analyze C++")); +} + +TEST(TransferTest, ObjectiveCXXNotSupported) { + TestInputs Inputs("void target() {}"); + Inputs.Language = TestLanguage::Lang_OBJCXX; + clang::TestAST AST(Inputs); + const auto *Target = + cast(test::findValueDecl(AST.context(), "target")); + ASSERT_THAT_ERROR(AdornedCFG::build(*Target).takeError(), llvm::FailedWithMessage("Can only analyze C++")); } diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index bea989c8c306db7e4ae4680fef55761c652bae9d..03005384a6f667e10d0c2164abfe90d5994b1c5d 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -3621,8 +3621,8 @@ TEST_F(FormatTest, FormatsClasses) { " : public aaaaaaaaaaaaaaaaaaa {};"); verifyFormat("template \n" - "struct Aaaaaaaaaaaaaaaaa\n" - " : Aaaaaaaaaaaaaaaaa {};"); + "struct Aaaaaaaaaaaaaaaaa\n" + " : Aaaaaaaaaaaaaaaaa {};"); verifyFormat("class ::A::B {};"); } @@ -11034,10 +11034,10 @@ TEST_F(FormatTest, UnderstandsBinaryOperators) { } TEST_F(FormatTest, UnderstandsPointersToMembers) { - verifyFormat("int A::*x;"); - verifyFormat("int (S::*func)(void *);"); - verifyFormat("void f() { int (S::*func)(void *); }"); - verifyFormat("typedef bool *(Class::*Member)() const;"); + verifyFormat("int A:: *x;"); + verifyFormat("int (S:: *func)(void *);"); + verifyFormat("void f() { int (S:: *func)(void *); }"); + verifyFormat("typedef bool *(Class:: *Member)() const;"); verifyFormat("void f() {\n" " (a->*f)();\n" " a->*x;\n" @@ -11052,9 +11052,19 @@ TEST_F(FormatTest, UnderstandsPointersToMembers) { verifyFormat( "(aaaaaaaaaa->*bbbbbbb)(\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaa));"); + FormatStyle Style = getLLVMStyle(); + EXPECT_EQ(Style.PointerAlignment, FormatStyle::PAS_Right); + verifyFormat("typedef bool *(Class:: *Member)() const;", Style); + verifyFormat("void f(int A:: *p) { int A:: *v = &A::B; }", Style); + Style.PointerAlignment = FormatStyle::PAS_Left; - verifyFormat("typedef bool* (Class::*Member)() const;", Style); + verifyFormat("typedef bool* (Class::* Member)() const;", Style); + verifyFormat("void f(int A::* p) { int A::* v = &A::B; }", Style); + + Style.PointerAlignment = FormatStyle::PAS_Middle; + verifyFormat("typedef bool * (Class:: * Member)() const;", Style); + verifyFormat("void f(int A:: * p) { int A:: * v = &A::B; }", Style); } TEST_F(FormatTest, UnderstandsUnaryOperators) { @@ -12386,7 +12396,7 @@ TEST_F(FormatTest, FormatsFunctionTypes) { verifyFormat("int (*func)(void *);"); verifyFormat("void f() { int (*func)(void *); }"); verifyFormat("template \n" - "using MyCallback = void (CallbackClass::*)(SomeObject *Data);"); + "using Callback = void (CallbackClass:: *)(SomeObject *Data);"); verifyGoogleFormat("A;"); verifyGoogleFormat("void* (*a)(int);"); @@ -19149,13 +19159,13 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { "int bbbbbbb = 0;", Alignment); // http://llvm.org/PR68079 - verifyFormat("using Fn = int (A::*)();\n" - "using RFn = int (A::*)() &;\n" - "using RRFn = int (A::*)() &&;", + verifyFormat("using Fn = int (A:: *)();\n" + "using RFn = int (A:: *)() &;\n" + "using RRFn = int (A:: *)() &&;", Alignment); - verifyFormat("using Fn = int (A::*)();\n" - "using RFn = int *(A::*)() &;\n" - "using RRFn = double (A::*)() &&;", + verifyFormat("using Fn = int (A:: *)();\n" + "using RFn = int *(A:: *)() &;\n" + "using RRFn = double (A:: *)() &&;", Alignment); // PAS_Right @@ -21090,7 +21100,14 @@ TEST_F(FormatTest, CatchAlignArrayOfStructuresRightAlignment) { " [0] = {1, 1},\n" " [1] { 1, 1, },\n" " [2] { 1, 1, },\n" - "};"); + "};", + Style); + verifyNoCrash("test arr[] = {\n" + "#define FOO(i) {i, i},\n" + "SOME_GENERATOR(FOO)\n" + "{2, 2}\n" + "};", + Style); verifyFormat("return GradForUnaryCwise(g, {\n" " {{\"sign\"}, \"Sign\", " @@ -21343,7 +21360,14 @@ TEST_F(FormatTest, CatchAlignArrayOfStructuresLeftAlignment) { " [0] = {1, 1},\n" " [1] { 1, 1, },\n" " [2] { 1, 1, },\n" - "};"); + "};", + Style); + verifyNoCrash("test arr[] = {\n" + "#define FOO(i) {i, i},\n" + "SOME_GENERATOR(FOO)\n" + "{2, 2}\n" + "};", + Style); verifyFormat("return GradForUnaryCwise(g, {\n" " {{\"sign\"}, \"Sign\", {\"x\", " diff --git a/clang/unittests/Format/FormatTestTableGen.cpp b/clang/unittests/Format/FormatTestTableGen.cpp index c96866f0840f00dff5c478fccf4b8c3a59d00261..8ca6bf97e5a6b1dbfefc03ebbba75fd0fccd60c3 100644 --- a/clang/unittests/Format/FormatTestTableGen.cpp +++ b/clang/unittests/Format/FormatTestTableGen.cpp @@ -411,6 +411,38 @@ TEST_F(FormatTestTableGen, DAGArgBreakAll) { Style); } +TEST_F(FormatTestTableGen, DAGArgAlignment) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen); + Style.ColumnLimit = 60; + Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakAll; + Style.TableGenBreakingDAGArgOperators = {"ins", "outs"}; + verifyFormat("def Def : Parent {\n" + " let dagarg = (ins\n" + " a:$src1,\n" + " aa:$src2,\n" + " aaa:$src3\n" + " )\n" + "}\n", + Style); + verifyFormat("def Def : Parent {\n" + " let dagarg = (not a:$src1, aa:$src2, aaa:$src2)\n" + "}\n", + Style); + Style.AlignConsecutiveTableGenBreakingDAGArgColons.Enabled = true; + verifyFormat("def Def : Parent {\n" + " let dagarg = (ins\n" + " a :$src1,\n" + " aa :$src2,\n" + " aaa:$src3\n" + " )\n" + "}\n", + Style); + verifyFormat("def Def : Parent {\n" + " let dagarg = (not a:$src1, aa:$src2, aaa:$src2)\n" + "}\n", + Style); +} + TEST_F(FormatTestTableGen, CondOperatorAlignment) { FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen); Style.ColumnLimit = 60; diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp index 43476aea66337b19afd2517b21db7189d7536455..792d8f3c3a98258b008b939271bef93475e81100 100644 --- a/clang/unittests/Format/QualifierFixerTest.cpp +++ b/clang/unittests/Format/QualifierFixerTest.cpp @@ -305,7 +305,7 @@ TEST_F(QualifierFixerTest, RightQualifier) { verifyFormat("Foo inline static const;", "Foo inline const static;", Style); verifyFormat("Foo inline static const;", Style); - verifyFormat("Foo::Bar const volatile A::*;", + verifyFormat("Foo::Bar const volatile A:: *;", "volatile const Foo::Bar A::*;", Style); @@ -523,14 +523,15 @@ TEST_F(QualifierFixerTest, RightQualifier) { verifyFormat("const INTPTR a;", Style); // Pointers to members - verifyFormat("int S::*a;", Style); - verifyFormat("int const S::*a;", "const int S:: *a;", Style); - verifyFormat("int const S::*const a;", "const int S::* const a;", Style); - verifyFormat("int A::*const A::*p1;", Style); - verifyFormat("float (C::*p)(int);", Style); - verifyFormat("float (C::*const p)(int);", Style); - verifyFormat("float (C::*p)(int) const;", Style); - verifyFormat("float const (C::*p)(int);", "const float (C::*p)(int);", Style); + verifyFormat("int S:: *a;", Style); + verifyFormat("int const S:: *a;", "const int S:: *a;", Style); + verifyFormat("int const S:: *const a;", "const int S::* const a;", Style); + verifyFormat("int A:: *const A:: *p1;", Style); + verifyFormat("float (C:: *p)(int);", Style); + verifyFormat("float (C:: *const p)(int);", Style); + verifyFormat("float (C:: *p)(int) const;", Style); + verifyFormat("float const (C:: *p)(int);", "const float (C::*p)(int);", + Style); } TEST_F(QualifierFixerTest, LeftQualifier) { @@ -830,14 +831,15 @@ TEST_F(QualifierFixerTest, LeftQualifier) { verifyFormat("INTPTR const a;", Style); // Pointers to members - verifyFormat("int S::*a;", Style); - verifyFormat("const int S::*a;", "int const S:: *a;", Style); - verifyFormat("const int S::*const a;", "int const S::* const a;", Style); - verifyFormat("int A::*const A::*p1;", Style); - verifyFormat("float (C::*p)(int);", Style); - verifyFormat("float (C::*const p)(int);", Style); - verifyFormat("float (C::*p)(int) const;", Style); - verifyFormat("const float (C::*p)(int);", "float const (C::*p)(int);", Style); + verifyFormat("int S:: *a;", Style); + verifyFormat("const int S:: *a;", "int const S:: *a;", Style); + verifyFormat("const int S:: *const a;", "int const S::* const a;", Style); + verifyFormat("int A:: *const A:: *p1;", Style); + verifyFormat("float (C:: *p)(int);", Style); + verifyFormat("float (C:: *const p)(int);", Style); + verifyFormat("float (C:: *p)(int) const;", Style); + verifyFormat("const float (C:: *p)(int);", "float const (C::*p)(int);", + Style); } TEST_F(QualifierFixerTest, ConstVolatileQualifiersOrder) { diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 1aa855b3419877ca0eb21c32572f02d61b1dd71b..2539d3d76ef019eeff37aed1d633b98c81431b3f 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -2424,6 +2424,22 @@ TEST_F(TokenAnnotatorTest, UnderstandTableGenTokens) { EXPECT_TOKEN(Tokens[1], tok::identifier, TT_Unknown); // other EXPECT_TOKEN(Tokens[5], tok::comma, TT_TableGenDAGArgListComma); EXPECT_TOKEN(Tokens[9], tok::r_paren, TT_TableGenDAGArgCloser); + + // If TableGenBreakingDAGArgOperators is enabled, it uses + // TT_TableGenDAGArgListColonToAlign to annotate the colon to align. + Style.AlignConsecutiveTableGenBreakingDAGArgColons.Enabled = true; + Tokens = AnnotateValue("(ins type1:$src1, type2:$src2)"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[1], tok::identifier, + TT_TableGenDAGArgOperatorToBreak); // ins + EXPECT_TOKEN(Tokens[3], tok::colon, TT_TableGenDAGArgListColonToAlign); + EXPECT_TOKEN(Tokens[7], tok::colon, TT_TableGenDAGArgListColonToAlign); + + Tokens = AnnotateValue("(other type1:$src1, type2:$src2)"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[1], tok::identifier, TT_Unknown); // other + EXPECT_TOKEN(Tokens[3], tok::colon, TT_TableGenDAGArgListColon); + EXPECT_TOKEN(Tokens[7], tok::colon, TT_TableGenDAGArgListColon); } TEST_F(TokenAnnotatorTest, UnderstandConstructors) { diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt index b56e1e21015db91a85e6aa8a0a51b604eb057327..e5a77e77de75cdbafd99f878e0dbdd51f1e3e391 100644 --- a/clang/unittests/Interpreter/CMakeLists.txt +++ b/clang/unittests/Interpreter/CMakeLists.txt @@ -1,6 +1,7 @@ set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} Core + MC OrcJIT Support TargetParser diff --git a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp index b7708616fd24d34a8fc2daed6a4d3a6332ff5cfd..1ba865a79ed778cf161383e43a47112536a90ccd 100644 --- a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp +++ b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp @@ -18,14 +18,22 @@ #include "clang/Sema/Sema.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" +#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Support/Error.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/Threading.h" #include "llvm/Testing/Support/Error.h" #include "gmock/gmock.h" #include "gtest/gtest.h" + #include +#if defined(_AIX) +#define CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT +#endif + using namespace clang; namespace { @@ -37,10 +45,23 @@ static bool HostSupportsJit() { return false; } +// Some tests require a arm-registered-target +static bool IsARMTargetRegistered() { + llvm::Triple TT; + TT.setArch(llvm::Triple::arm); + TT.setVendor(llvm::Triple::UnknownVendor); + TT.setOS(llvm::Triple::UnknownOS); + + std::string UnusedErr; + return llvm::TargetRegistry::lookupTarget(TT.str(), UnusedErr); +} + struct LLVMInitRAII { LLVMInitRAII() { - llvm::InitializeNativeTarget(); - llvm::InitializeNativeTargetAsmPrinter(); + llvm::InitializeAllTargets(); + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllAsmPrinters(); } ~LLVMInitRAII() { llvm::llvm_shutdown(); } } LLVMInit; @@ -51,12 +72,30 @@ public: llvm::Error &Err) : Interpreter(std::move(CI), Err) {} - llvm::Error testCreateExecutor() { return Interpreter::CreateExecutor(); } + llvm::Error testCreateJITBuilderError() { + JB = nullptr; + return Interpreter::CreateExecutor(); + } + + llvm::Error testCreateExecutor() { + JB = std::make_unique(); + return Interpreter::CreateExecutor(); + } void resetExecutor() { Interpreter::ResetExecutor(); } + +private: + llvm::Expected> + CreateJITBuilder(CompilerInstance &CI) override { + if (JB) + return std::move(JB); + return llvm::make_error("TestError", std::error_code()); + } + + std::unique_ptr JB; }; -#ifdef _AIX +#ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT TEST(InterpreterExtensionsTest, DISABLED_ExecutorCreateReset) { #else TEST(InterpreterExtensionsTest, ExecutorCreateReset) { @@ -69,6 +108,8 @@ TEST(InterpreterExtensionsTest, ExecutorCreateReset) { llvm::Error ErrOut = llvm::Error::success(); TestCreateResetExecutor Interp(cantFail(CB.CreateCpp()), ErrOut); cantFail(std::move(ErrOut)); + EXPECT_THAT_ERROR(Interp.testCreateJITBuilderError(), + llvm::FailedWithMessage("TestError")); cantFail(Interp.testCreateExecutor()); Interp.resetExecutor(); cantFail(Interp.testCreateExecutor()); @@ -126,4 +167,96 @@ TEST(InterpreterExtensionsTest, FindRuntimeInterface) { EXPECT_EQ(1U, Interp.RuntimeIBPtr->TransformerQueries); } +class CustomJBInterpreter : public Interpreter { + using CustomJITBuilderCreatorFunction = + std::function>()>; + CustomJITBuilderCreatorFunction JBCreator = nullptr; + +public: + CustomJBInterpreter(std::unique_ptr CI, llvm::Error &ErrOut) + : Interpreter(std::move(CI), ErrOut) {} + + ~CustomJBInterpreter() override { + // Skip cleanUp() because it would trigger LLJIT default dtors + Interpreter::ResetExecutor(); + } + + void setCustomJITBuilderCreator(CustomJITBuilderCreatorFunction Fn) { + JBCreator = std::move(Fn); + } + + llvm::Expected> + CreateJITBuilder(CompilerInstance &CI) override { + if (JBCreator) + return JBCreator(); + return Interpreter::CreateJITBuilder(CI); + } + + llvm::Error CreateExecutor() { return Interpreter::CreateExecutor(); } +}; + +#ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT +TEST(InterpreterExtensionsTest, DISABLED_DefaultCrossJIT) { +#else +TEST(InterpreterExtensionsTest, DefaultCrossJIT) { +#endif + if (!IsARMTargetRegistered()) + GTEST_SKIP(); + + IncrementalCompilerBuilder CB; + CB.SetTargetTriple("armv6-none-eabi"); + auto CI = cantFail(CB.CreateCpp()); + llvm::Error ErrOut = llvm::Error::success(); + CustomJBInterpreter Interp(std::move(CI), ErrOut); + cantFail(std::move(ErrOut)); + cantFail(Interp.CreateExecutor()); +} + +#ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT +TEST(InterpreterExtensionsTest, DISABLED_CustomCrossJIT) { +#else +TEST(InterpreterExtensionsTest, CustomCrossJIT) { +#endif + if (!IsARMTargetRegistered()) + GTEST_SKIP(); + + std::string TargetTriple = "armv6-none-eabi"; + + IncrementalCompilerBuilder CB; + CB.SetTargetTriple(TargetTriple); + auto CI = cantFail(CB.CreateCpp()); + llvm::Error ErrOut = llvm::Error::success(); + CustomJBInterpreter Interp(std::move(CI), ErrOut); + cantFail(std::move(ErrOut)); + + using namespace llvm::orc; + LLJIT *JIT = nullptr; + std::vector> Objs; + Interp.setCustomJITBuilderCreator([&]() { + auto JTMB = JITTargetMachineBuilder(llvm::Triple(TargetTriple)); + JTMB.setCPU("cortex-m0plus"); + auto JB = std::make_unique(); + JB->setJITTargetMachineBuilder(JTMB); + JB->setPlatformSetUp(setUpInactivePlatform); + JB->setNotifyCreatedCallback([&](LLJIT &J) { + ObjectLayer &ObjLayer = J.getObjLinkingLayer(); + auto *JITLinkObjLayer = llvm::dyn_cast(&ObjLayer); + JITLinkObjLayer->setReturnObjectBuffer( + [&Objs](std::unique_ptr MB) { + Objs.push_back(std::move(MB)); + }); + JIT = &J; + return llvm::Error::success(); + }); + return JB; + }); + + EXPECT_EQ(0U, Objs.size()); + cantFail(Interp.CreateExecutor()); + cantFail(Interp.ParseAndExecute("int a = 1;")); + ExecutorAddr Addr = cantFail(JIT->lookup("a")); + EXPECT_NE(0U, Addr.getValue()); + EXPECT_EQ(1U, Objs.size()); +} + } // end anonymous namespace diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp index e76c0677db5ead160c35376f8c357221d26037cf..69bc2da242884e81c5e37db640b81c77b59cd69c 100644 --- a/clang/unittests/Interpreter/InterpreterTest.cpp +++ b/clang/unittests/Interpreter/InterpreterTest.cpp @@ -340,6 +340,12 @@ TEST(InterpreterTest, Value) { EXPECT_EQ(V1.getKind(), Value::K_Int); EXPECT_FALSE(V1.isManuallyAlloc()); + Value V1b; + llvm::cantFail(Interp->ParseAndExecute("char c = 42;")); + llvm::cantFail(Interp->ParseAndExecute("c", &V1b)); + EXPECT_TRUE(V1b.getKind() == Value::K_Char_S || + V1b.getKind() == Value::K_Char_U); + Value V2; llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;")); llvm::cantFail(Interp->ParseAndExecute("y", &V2)); diff --git a/clang/unittests/StaticAnalyzer/CMakeLists.txt b/clang/unittests/StaticAnalyzer/CMakeLists.txt index 519be36fe0fa382cb0e9e648092946982cf0f522..ff34d5747cc81b31aa891576a523ea5edecfa21e 100644 --- a/clang/unittests/StaticAnalyzer/CMakeLists.txt +++ b/clang/unittests/StaticAnalyzer/CMakeLists.txt @@ -11,6 +11,7 @@ add_clang_unittest(StaticAnalysisTests CallEventTest.cpp ConflictingEvalCallsTest.cpp FalsePositiveRefutationBRVisitorTest.cpp + IsCLibraryFunctionTest.cpp MemRegionDescriptiveNameTest.cpp NoStateChangeFuncVisitorTest.cpp ParamRegionTest.cpp diff --git a/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp b/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d6dfcaac6f3bdc41bd97f7f23af81a6f70bba45f --- /dev/null +++ b/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp @@ -0,0 +1,84 @@ +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Frontend/ASTUnit.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/Tooling/Tooling.h" +#include "gtest/gtest.h" + +#include + +using namespace clang; +using namespace ento; +using namespace ast_matchers; + +class IsCLibraryFunctionTest : public testing::Test { + std::unique_ptr ASTUnitP; + const FunctionDecl *Result = nullptr; + +public: + const FunctionDecl *getFunctionDecl() const { return Result; } + + testing::AssertionResult buildAST(StringRef Code) { + ASTUnitP = tooling::buildASTFromCode(Code); + if (!ASTUnitP) + return testing::AssertionFailure() << "AST construction failed"; + + ASTContext &Context = ASTUnitP->getASTContext(); + if (Context.getDiagnostics().hasErrorOccurred()) + return testing::AssertionFailure() << "Compilation error"; + + auto Matches = ast_matchers::match(functionDecl().bind("fn"), Context); + if (Matches.empty()) + return testing::AssertionFailure() << "No function declaration found"; + + if (Matches.size() > 1) + return testing::AssertionFailure() + << "Multiple function declarations found"; + + Result = Matches[0].getNodeAs("fn"); + return testing::AssertionSuccess(); + } +}; + +TEST_F(IsCLibraryFunctionTest, AcceptsGlobal) { + ASSERT_TRUE(buildAST(R"cpp(void fun();)cpp")); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, AcceptsExternCGlobal) { + ASSERT_TRUE(buildAST(R"cpp(extern "C" { void fun(); })cpp")); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsNoInlineNoExternalLinkage) { + // Functions that are neither inlined nor externally visible cannot be C + // library functions. + ASSERT_TRUE(buildAST(R"cpp(static void fun();)cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsAnonymousNamespace) { + ASSERT_TRUE(buildAST(R"cpp(namespace { void fun(); })cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, AcceptsStdNamespace) { + ASSERT_TRUE(buildAST(R"cpp(namespace std { void fun(); })cpp")); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsOtherNamespaces) { + ASSERT_TRUE(buildAST(R"cpp(namespace stdx { void fun(); })cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsClassStatic) { + ASSERT_TRUE(buildAST(R"cpp(class A { static void fun(); };)cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsClassMember) { + ASSERT_TRUE(buildAST(R"cpp(class A { void fun(); };)cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} diff --git a/clang/www/analyzer/alpha_checks.html b/clang/www/analyzer/alpha_checks.html index 7bbe4a20288f23e0dd73125653971abb9f01825e..f040d1957b0f98bad4d5dbc428ae9ac80e56379d 100644 --- a/clang/www/analyzer/alpha_checks.html +++ b/clang/www/analyzer/alpha_checks.html @@ -307,26 +307,6 @@ void test(int x) { - - - -