diff --git a/.ci/monolithic-linux.sh b/.ci/monolithic-linux.sh index 9e670c447fbaddc82106905b60927fc2c5c883db..35f1aacb4985f046562778a77d1f618ff443863f 100755 --- a/.ci/monolithic-linux.sh +++ b/.ci/monolithic-linux.sh @@ -18,7 +18,7 @@ set -o pipefail MONOREPO_ROOT="${MONOREPO_ROOT:="$(git rev-parse --show-toplevel)"}" BUILD_DIR="${BUILD_DIR:=${MONOREPO_ROOT}/build}" -rm -rf ${BUILD_DIR} +rm -rf "${BUILD_DIR}" ccache --zero-stats @@ -37,8 +37,8 @@ projects="${1}" targets="${2}" echo "--- cmake" -pip install -q -r ${MONOREPO_ROOT}/mlir/python/requirements.txt -cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ +pip install -q -r "${MONOREPO_ROOT}"/mlir/python/requirements.txt +cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \ -D LLVM_ENABLE_PROJECTS="${projects}" \ -G Ninja \ -D CMAKE_BUILD_TYPE=Release \ @@ -54,4 +54,4 @@ cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ echo "--- ninja" # Targets are not escaped as they are passed as separate arguments. -ninja -C "${BUILD_DIR}" -k 0 ${targets} +ninja -C "${BUILD_DIR}" -k 0 "${targets}" diff --git a/.ci/monolithic-windows.sh b/.ci/monolithic-windows.sh index 52ba13036f915983e97ad1149ffc40ee51a4c24e..f84c0966704e731dcdb6de180d458c1fd645609c 100755 --- a/.ci/monolithic-windows.sh +++ b/.ci/monolithic-windows.sh @@ -19,7 +19,7 @@ set -o pipefail MONOREPO_ROOT="${MONOREPO_ROOT:="$(git rev-parse --show-toplevel)"}" BUILD_DIR="${BUILD_DIR:=${MONOREPO_ROOT}/build}" -rm -rf ${BUILD_DIR} +rm -rf "${BUILD_DIR}" if [[ -n "${CLEAR_CACHE:-}" ]]; then echo "clearing sccache" @@ -37,14 +37,14 @@ projects="${1}" targets="${2}" echo "--- cmake" -pip install -q -r ${MONOREPO_ROOT}/mlir/python/requirements.txt +pip install -q -r "${MONOREPO_ROOT}"/mlir/python/requirements.txt # The CMAKE_*_LINKER_FLAGS to disable the manifest come from research # on fixing a build reliability issue on the build server, please # see https://github.com/llvm/llvm-project/pull/82393 and # https://discourse.llvm.org/t/rfc-future-of-windows-pre-commit-ci/76840/40 # for further information. -cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ +cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \ -D LLVM_ENABLE_PROJECTS="${projects}" \ -G Ninja \ -D CMAKE_BUILD_TYPE=Release \ @@ -62,4 +62,4 @@ cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ echo "--- ninja" # Targets are not escaped as they are passed as separate arguments. -ninja -C "${BUILD_DIR}" -k 0 ${targets} +ninja -C "${BUILD_DIR}" -k 0 "${targets}" 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/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index b8e8ab26c3ffa61a1f3a76883034564086d1d237..ff61cf83a6af3c816e7fa4b0a55fa26f3d1471e4 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -36,7 +36,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2 + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 with: results_file: results.sarif results_format: sarif 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/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp index fdadef9dcd384828db57559b8be5dc76b9d9b29d..c9e037c225dd41674c834cb8ed921e1eac591214 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -3547,7 +3547,7 @@ MCSymbol *BinaryFunction::getSymbolForEntryID(uint64_t EntryID) { if (!isMultiEntry()) return nullptr; - uint64_t NumEntries = 0; + uint64_t NumEntries = 1; if (hasCFG()) { for (BinaryBasicBlock *BB : BasicBlocks) { MCSymbol *EntrySymbol = getSecondaryEntryPointSymbol(*BB); @@ -3580,7 +3580,7 @@ uint64_t BinaryFunction::getEntryIDForSymbol(const MCSymbol *Symbol) const { return 0; // Check all secondary entries available as either basic blocks or lables. - uint64_t NumEntries = 0; + uint64_t NumEntries = 1; for (const BinaryBasicBlock *BB : BasicBlocks) { MCSymbol *EntrySymbol = getSecondaryEntryPointSymbol(*BB); if (!EntrySymbol) @@ -3589,7 +3589,7 @@ uint64_t BinaryFunction::getEntryIDForSymbol(const MCSymbol *Symbol) const { return NumEntries; ++NumEntries; } - NumEntries = 0; + NumEntries = 1; for (const std::pair &KV : Labels) { MCSymbol *EntrySymbol = getSecondaryEntryPointSymbol(KV.second); if (!EntrySymbol) 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/Profile/YAMLProfileWriter.cpp b/bolt/lib/Profile/YAMLProfileWriter.cpp index 6edef92f5e038079854262d77964a8c87ca35af6..0f082086c1fc24810d97e2a078c6648eda753585 100644 --- a/bolt/lib/Profile/YAMLProfileWriter.cpp +++ b/bolt/lib/Profile/YAMLProfileWriter.cpp @@ -97,15 +97,21 @@ YAMLProfileWriter::convert(const BinaryFunction &BF, bool UseDFS) { if (!ICSP) continue; for (const IndirectCallProfile &CSP : ICSP.get()) { + StringRef TargetName = ""; const BinaryFunction *Callee = setCSIDestination(BC, CSI, CSP.Symbol); + if (Callee) + TargetName = Callee->getOneName(); CSI.Count = CSP.Count; CSI.Mispreds = CSP.Mispreds; - if (CSI.Count && Callee) - CSTargets.emplace_back(Callee->getOneName(), CSI); + CSTargets.emplace_back(TargetName, CSI); } } else { // direct call or a tail call + StringRef TargetName = ""; const MCSymbol *CalleeSymbol = BC.MIB->getTargetSymbol(Instr); - const BinaryFunction *Callee = setCSIDestination(BC, CSI, CalleeSymbol); + const BinaryFunction *const Callee = + setCSIDestination(BC, CSI, CalleeSymbol); + if (Callee) + TargetName = Callee->getOneName(); auto getAnnotationWithDefault = [&](const MCInst &Inst, StringRef Ann) { return BC.MIB->getAnnotationWithDefault(Instr, Ann, 0ull); @@ -117,8 +123,8 @@ YAMLProfileWriter::convert(const BinaryFunction &BF, bool UseDFS) { CSI.Count = getAnnotationWithDefault(Instr, "Count"); } - if (CSI.Count && Callee) - CSTargets.emplace_back(Callee->getOneName(), CSI); + if (CSI.Count) + CSTargets.emplace_back(TargetName, CSI); } // Sort targets in a similar way to getBranchData, see Location::operator< llvm::sort(CSTargets, [](const auto &RHS, const auto &LHS) { 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/bolt/test/X86/yaml-secondary-entry-discriminator.s b/bolt/test/X86/yaml-secondary-entry-discriminator.s new file mode 100644 index 0000000000000000000000000000000000000000..43c2e2a7f05549289293a39808762cc5a68cc285 --- /dev/null +++ b/bolt/test/X86/yaml-secondary-entry-discriminator.s @@ -0,0 +1,74 @@ +# This reproduces a bug with BOLT setting incorrect discriminator for +# secondary entry points in YAML profile. + +# REQUIRES: system-linux +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: link_fdata %s %t.o %t.fdata +# RUN: llvm-strip --strip-unneeded %t.o +# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib +# RUN: llvm-bolt %t.exe -o %t.out --data %t.fdata -w %t.yaml --print-profile \ +# RUN: --print-only=main | FileCheck %s --check-prefix=CHECK-CFG +# RUN: FileCheck %s -input-file %t.yaml +# CHECK: - name: main +# CHECK-NEXT: fid: 2 +# CHECK-NEXT: hash: 0xADF270D550151185 +# CHECK-NEXT: exec: 0 +# CHECK-NEXT: nblocks: 4 +# CHECK-NEXT: blocks: +# CHECK: - bid: 1 +# CHECK-NEXT: insns: 1 +# CHECK-NEXT: hash: 0x36A303CBA4360014 +# CHECK-NEXT: calls: [ { off: 0x0, fid: 1, disc: 1, cnt: 1 } ] +# CHECK: - bid: 2 +# CHECK-NEXT: insns: 5 +# CHECK-NEXT: hash: 0x8B2F5747CD0019 +# CHECK-NEXT: calls: [ { off: 0x0, fid: 1, disc: 1, cnt: 1, mis: 1 } ] + +# Make sure that the profile is attached correctly +# RUN: llvm-bolt %t.exe -o %t.out --data %t.yaml --print-profile \ +# RUN: --print-only=main | FileCheck %s --check-prefix=CHECK-CFG + +# CHECK-CFG: Binary Function "main" after attaching profile { +# CHECK-CFG: callq secondary_entry # Offset: [[#]] # Count: 1 +# CHECK-CFG: callq *%rax # Offset: [[#]] # CallProfile: 1 (1 misses) : +# CHECK-CFG-NEXT: { secondary_entry: 1 (1 misses) } + +.globl func +.type func, @function +func: +# FDATA: 0 [unknown] 0 1 func 0 1 0 + .cfi_startproc + pushq %rbp + movq %rsp, %rbp +.globl secondary_entry +secondary_entry: + popq %rbp + retq + nopl (%rax) + .cfi_endproc + .size func, .-func + +.globl main +.type main, @function +main: + .cfi_startproc + pushq %rbp + movq %rsp, %rbp + subq $16, %rsp + movl $0, -4(%rbp) + testq %rax, %rax + jne Lindcall +Lcall: + call secondary_entry +# FDATA: 1 main #Lcall# 1 secondary_entry 0 1 1 +Lindcall: + callq *%rax +# FDATA: 1 main #Lindcall# 1 secondary_entry 0 1 1 + xorl %eax, %eax + addq $16, %rsp + popq %rbp + retq +# For relocations against .text + call exit + .cfi_endproc + .size main, .-main 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/clang-tidy/google/IntegerTypesCheck.cpp b/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp index ef511e9108f2ee957c9ff466fc8aa069b137312b..359d8efd100bad9bdbfe369afec099a20f87834d 100644 --- a/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp @@ -40,6 +40,34 @@ namespace { AST_MATCHER(FunctionDecl, isUserDefineLiteral) { return Node.getLiteralIdentifier() != nullptr; } + +AST_MATCHER(TypeLoc, isValidAndNotInMacro) { + const SourceLocation Loc = Node.getBeginLoc(); + return Loc.isValid() && !Loc.isMacroID(); +} + +AST_MATCHER(TypeLoc, isBuiltinType) { + TypeLoc TL = Node; + if (auto QualLoc = Node.getAs()) + TL = QualLoc.getUnqualifiedLoc(); + + const auto BuiltinLoc = TL.getAs(); + if (!BuiltinLoc) + return false; + + switch (BuiltinLoc.getTypePtr()->getKind()) { + case BuiltinType::Short: + case BuiltinType::Long: + case BuiltinType::LongLong: + case BuiltinType::UShort: + case BuiltinType::ULong: + case BuiltinType::ULongLong: + return true; + default: + return false; + } +} + } // namespace namespace tidy::google::runtime { @@ -63,11 +91,11 @@ void IntegerTypesCheck::registerMatchers(MatchFinder *Finder) { // "Where possible, avoid passing arguments of types specified by // bitwidth typedefs to printf-based APIs." Finder->addMatcher( - typeLoc(loc(isInteger()), - unless(anyOf(hasAncestor(callExpr( - callee(functionDecl(hasAttr(attr::Format))))), - hasParent(parmVarDecl(hasAncestor( - functionDecl(isUserDefineLiteral()))))))) + typeLoc(loc(isInteger()), isValidAndNotInMacro(), isBuiltinType(), + unless(hasAncestor( + callExpr(callee(functionDecl(hasAttr(attr::Format)))))), + unless(hasParent(parmVarDecl( + hasAncestor(functionDecl(isUserDefineLiteral())))))) .bind("tl"), this); IdentTable = std::make_unique(getLangOpts()); @@ -77,9 +105,6 @@ void IntegerTypesCheck::check(const MatchFinder::MatchResult &Result) { auto TL = *Result.Nodes.getNodeAs("tl"); SourceLocation Loc = TL.getBeginLoc(); - if (Loc.isInvalid() || Loc.isMacroID()) - return; - // Look through qualification. if (auto QualLoc = TL.getAs()) TL = QualLoc.getUnqualifiedLoc(); diff --git a/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h b/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h index 3be7d24021b9ffcbc25f35321d3af2a6d9f05a76..c62bda67ae2d987d68dc7cb1dc78b506e0ac6f63 100644 --- a/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h +++ b/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h @@ -35,6 +35,9 @@ public: void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + std::optional getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } private: const StringRef UnsignedTypePrefix; diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp index bb05f206c717cea3a4c2067e7473d4a30dccdc12..24eefdb082eb32ad2c0195030d1e1d3f10f2af67 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp @@ -8,6 +8,7 @@ #include "UseUsingCheck.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/DeclGroup.h" #include "clang/Lex/Lexer.h" using namespace clang::ast_matchers; @@ -24,6 +25,7 @@ static constexpr llvm::StringLiteral ExternCDeclName = "extern-c-decl"; static constexpr llvm::StringLiteral ParentDeclName = "parent-decl"; static constexpr llvm::StringLiteral TagDeclName = "tag-decl"; static constexpr llvm::StringLiteral TypedefName = "typedef"; +static constexpr llvm::StringLiteral DeclStmtName = "decl-stmt"; UseUsingCheck::UseUsingCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), @@ -41,7 +43,8 @@ void UseUsingCheck::registerMatchers(MatchFinder *Finder) { unless(isInstantiated()), optionally(hasAncestor( linkageSpecDecl(isExternCLinkage()).bind(ExternCDeclName))), - hasParent(decl().bind(ParentDeclName))) + anyOf(hasParent(decl().bind(ParentDeclName)), + hasParent(declStmt().bind(DeclStmtName)))) .bind(TypedefName), this); @@ -51,17 +54,32 @@ void UseUsingCheck::registerMatchers(MatchFinder *Finder) { tagDecl( anyOf(allOf(unless(anyOf(isImplicit(), classTemplateSpecializationDecl())), - hasParent(decl().bind(ParentDeclName))), + anyOf(hasParent(decl().bind(ParentDeclName)), + hasParent(declStmt().bind(DeclStmtName)))), // We want the parent of the ClassTemplateDecl, not the parent // of the specialization. classTemplateSpecializationDecl(hasAncestor(classTemplateDecl( - hasParent(decl().bind(ParentDeclName))))))) + anyOf(hasParent(decl().bind(ParentDeclName)), + hasParent(declStmt().bind(DeclStmtName)))))))) .bind(TagDeclName), this); } void UseUsingCheck::check(const MatchFinder::MatchResult &Result) { const auto *ParentDecl = Result.Nodes.getNodeAs(ParentDeclName); + + if (!ParentDecl) { + const auto *ParentDeclStmt = Result.Nodes.getNodeAs(DeclStmtName); + if (ParentDeclStmt) { + if (ParentDeclStmt->isSingleDecl()) + ParentDecl = ParentDeclStmt->getSingleDecl(); + else + ParentDecl = + ParentDeclStmt->getDeclGroup().getDeclGroup() + [ParentDeclStmt->getDeclGroup().getDeclGroup().size() - 1]; + } + } + if (!ParentDecl) return; diff --git a/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h b/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h index c28087e07e9b61f55a048c4b533c9045b44c9fe6..620cd6e3f2f8779792ddec763a7d636234217698 100644 --- a/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h +++ b/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h @@ -24,6 +24,12 @@ public: : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus; + } + std::optional getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } }; } // namespace clang::tidy::readability diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index f29dadde2b86d5a20d542e0c6812d42ba2be1910..7fd599d4e1a0b0e393ee6a36291955496073f12e 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -1390,7 +1390,7 @@ void ClangdLSPServer::onClangdInlayHints(const InlayHintsParams &Params, // Extension doesn't have paddingLeft/Right so adjust the label // accordingly. {"label", - ((Hint.paddingLeft ? " " : "") + llvm::StringRef(Hint.label) + + ((Hint.paddingLeft ? " " : "") + llvm::StringRef(Hint.joinLabels()) + (Hint.paddingRight ? " " : "")) .str()}, }); diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index a0ebc631ef8285ad37ac5da70df63bb3152494f7..cd4f1931b3ce1dabd27195366c66349f0ff01cf0 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -977,8 +977,9 @@ private: return; bool PadLeft = Prefix.consume_front(" "); bool PadRight = Suffix.consume_back(" "); - Results.push_back(InlayHint{LSPPos, (Prefix + Label + Suffix).str(), Kind, - PadLeft, PadRight, LSPRange}); + Results.push_back(InlayHint{LSPPos, + /*label=*/{(Prefix + Label + Suffix).str()}, + Kind, PadLeft, PadRight, LSPRange}); } // Get the range of the main file that *exactly* corresponds to R. diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index c6553e00dcae28209da96ff0eb6a7dd2288d008f..c08f80442eaa0605c1a7513ace13cb57032518c3 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -1501,6 +1501,10 @@ bool operator<(const InlayHint &A, const InlayHint &B) { return std::tie(A.position, A.range, A.kind, A.label) < std::tie(B.position, B.range, B.kind, B.label); } +std::string InlayHint::joinLabels() const { + return llvm::join(llvm::map_range(label, [](auto &L) { return L.value; }), + ""); +} llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, InlayHintKind Kind) { auto ToString = [](InlayHintKind K) { @@ -1519,6 +1523,33 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, InlayHintKind Kind) { return OS << ToString(Kind); } +llvm::json::Value toJSON(const InlayHintLabelPart &L) { + llvm::json::Object Result{{"value", L.value}}; + if (L.tooltip) + Result["tooltip"] = *L.tooltip; + if (L.location) + Result["location"] = *L.location; + if (L.command) + Result["command"] = *L.command; + return Result; +} + +bool operator==(const InlayHintLabelPart &LHS, const InlayHintLabelPart &RHS) { + return std::tie(LHS.value, LHS.location) == std::tie(RHS.value, RHS.location); +} + +bool operator<(const InlayHintLabelPart &LHS, const InlayHintLabelPart &RHS) { + return std::tie(LHS.value, LHS.location) < std::tie(RHS.value, RHS.location); +} + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const InlayHintLabelPart &L) { + OS << L.value; + if (L.location) + OS << " (" << L.location << ")"; + return OS; +} + static const char *toString(OffsetEncoding OE) { switch (OE) { case OffsetEncoding::UTF8: diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h index 358d4c6feaf87d45c5f0a3fc4f3f0635af168a8d..a0f8b04bc4ffdb043212d13861d78e7dbc8ecdd2 100644 --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -1689,6 +1689,48 @@ enum class InlayHintKind { }; llvm::json::Value toJSON(const InlayHintKind &); +/// An inlay hint label part allows for interactive and composite labels +/// of inlay hints. +struct InlayHintLabelPart { + + InlayHintLabelPart() = default; + + InlayHintLabelPart(std::string value, + std::optional location = std::nullopt) + : value(std::move(value)), location(std::move(location)) {} + + /// The value of this label part. + std::string value; + + /// The tooltip text when you hover over this label part. Depending on + /// the client capability `inlayHint.resolveSupport`, clients might resolve + /// this property late using the resolve request. + std::optional tooltip; + + /// An optional source code location that represents this + /// label part. + /// + /// The editor will use this location for the hover and for code navigation + /// features: This part will become a clickable link that resolves to the + /// definition of the symbol at the given location (not necessarily the + /// location itself), it shows the hover that shows at the given location, + /// and it shows a context menu with further code navigation commands. + /// + /// Depending on the client capability `inlayHint.resolveSupport` clients + /// might resolve this property late using the resolve request. + std::optional location; + + /// An optional command for this label part. + /// + /// Depending on the client capability `inlayHint.resolveSupport` clients + /// might resolve this property late using the resolve request. + std::optional command; +}; +llvm::json::Value toJSON(const InlayHintLabelPart &); +bool operator==(const InlayHintLabelPart &, const InlayHintLabelPart &); +bool operator<(const InlayHintLabelPart &, const InlayHintLabelPart &); +llvm::raw_ostream &operator<<(llvm::raw_ostream &, const InlayHintLabelPart &); + /// Inlay hint information. struct InlayHint { /// The position of this hint. @@ -1698,7 +1740,7 @@ struct InlayHint { /// InlayHintLabelPart label parts. /// /// *Note* that neither the string nor the label part can be empty. - std::string label; + std::vector label; /// The kind of this hint. Can be omitted in which case the client should fall /// back to a reasonable default. @@ -1724,6 +1766,9 @@ struct InlayHint { /// The range allows clients more flexibility of when/how to display the hint. /// This is an (unserialized) clangd extension. Range range; + + /// Join the label[].value together. + std::string joinLabels() const; }; llvm::json::Value toJSON(const InlayHint &); bool operator==(const InlayHint &, const InlayHint &); diff --git a/clang-tools-extra/clangd/test/inlayHints.test b/clang-tools-extra/clangd/test/inlayHints.test index 8f302dd17a5494f246d15b9a2468c04664d1d105..e5b3c0fb0b960aa13a1acefb184e9795ff4854c8 100644 --- a/clang-tools-extra/clangd/test/inlayHints.test +++ b/clang-tools-extra/clangd/test/inlayHints.test @@ -51,7 +51,11 @@ # CHECK-NEXT: "result": [ # CHECK-NEXT: { # CHECK-NEXT: "kind": 2, -# CHECK-NEXT: "label": "bar:", +# CHECK-NEXT: "label": [ +# CHECK-NEXT: { +# CHECK-NEXT: "value": "bar:" +# CHECK-NEXT: } +# CHECK-NEXT: ], # CHECK-NEXT: "paddingLeft": false, # CHECK-NEXT: "paddingRight": true, # CHECK-NEXT: "position": { diff --git a/clang-tools-extra/clangd/tool/Check.cpp b/clang-tools-extra/clangd/tool/Check.cpp index 45e2e1e278deafa4843d8f7945472b961f7519a4..25005ec1bd04532093d24334ece75f7661f5c0e7 100644 --- a/clang-tools-extra/clangd/tool/Check.cpp +++ b/clang-tools-extra/clangd/tool/Check.cpp @@ -367,7 +367,13 @@ public: auto Hints = inlayHints(*AST, LineRange); for (const auto &Hint : Hints) { - vlog(" {0} {1} {2}", Hint.kind, Hint.position, Hint.label); + vlog(" {0} {1} [{2}]", Hint.kind, Hint.position, [&] { + return llvm::join(llvm::map_range(Hint.label, + [&](auto &L) { + return llvm::formatv("{{{0}}", L); + }), + ", "); + }()); } } diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp index 0fff0dfca6c9b8f21a459a4ec63b4821555c21a0..5b1531eb2fa60bcd0ae81137fcc3cf5b26fd79ee 100644 --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -25,7 +25,7 @@ namespace clangd { llvm::raw_ostream &operator<<(llvm::raw_ostream &Stream, const InlayHint &Hint) { - return Stream << Hint.label << "@" << Hint.range; + return Stream << Hint.joinLabels() << "@" << Hint.range; } namespace { @@ -57,10 +57,11 @@ struct ExpectedHint { MATCHER_P2(HintMatcher, Expected, Code, llvm::to_string(Expected)) { llvm::StringRef ExpectedView(Expected.Label); - if (arg.label != ExpectedView.trim(" ") || + std::string ResultLabel = arg.joinLabels(); + if (ResultLabel != ExpectedView.trim(" ") || arg.paddingLeft != ExpectedView.starts_with(" ") || arg.paddingRight != ExpectedView.ends_with(" ")) { - *result_listener << "label is '" << arg.label << "'"; + *result_listener << "label is '" << ResultLabel << "'"; return false; } if (arg.range != Code.range(Expected.RangeName)) { @@ -72,7 +73,7 @@ MATCHER_P2(HintMatcher, Expected, Code, llvm::to_string(Expected)) { return true; } -MATCHER_P(labelIs, Label, "") { return arg.label == Label; } +MATCHER_P(labelIs, Label, "") { return arg.joinLabels() == Label; } Config noHintsConfig() { Config C; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index a604e9276668aecfab23cd583b83fcb71682a958..78b09d23d4427f567e40e7c1d4ef479992760abe 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 @@ -176,13 +180,13 @@ Changes in existing checks ` check to properly handle return type in lambdas and in nested functions. -- Cleaned up :doc:`cppcoreguidelines-prefer-member-initializer - ` +- Improved :doc:`cppcoreguidelines-prefer-member-initializer + ` check by removing enforcement of rule `C.48 `_, which was deprecated since :program:`clang-tidy` 17. This rule is now covered by :doc:`cppcoreguidelines-use-default-member-init - ` and fixes + `. Fixed incorrect hints when using list-initialization. - Improved :doc:`google-build-namespaces @@ -197,6 +201,9 @@ Changes in existing checks ` check by replacing the local option `HeaderFileExtensions` by the global option of the same name. +- Improved :doc:`google-runtime-int ` + check performance through optimizations. + - Improved :doc:`llvm-header-guard ` check by replacing the local option `HeaderFileExtensions` by the global option of the same name. @@ -229,12 +236,20 @@ Changes in existing checks ` check to also remove any trailing whitespace when deleting the ``virtual`` keyword. +- Improved :doc:`modernize-use-using ` + check by adding support for detection of typedefs declared on function level. + - Improved :doc:`performance-unnecessary-copy-initialization ` check by detecting more cases of constant access. In particular, pointers can be analyzed, se the check now handles the common patterns `const auto e = (*vector_ptr)[i]` and `const auto e = vector_ptr->at(i);`. +- Improved :doc:`readability-identifier-naming + ` check in `GetConfigPerFile` + mode by resolving symbolic links to header files. Fixed handling of Hungarian + Prefix when configured to `LowerCase`. + - Improved :doc:`readability-implicit-bool-conversion ` check to provide valid fix suggestions for ``static_cast`` without a preceding space and @@ -244,10 +259,10 @@ Changes in existing checks ` check to properly emit warnings for static data member with an in-class initializer. -- Improved :doc:`readability-identifier-naming - ` check in `GetConfigPerFile` - mode by resolving symbolic links to header files. Fixed handling of Hungarian - Prefix when configured to `LowerCase`. +- Improved :doc:`readability-static-definition-in-anonymous-namespace + ` + check by resolving fix-it overlaps in template code by disregarding implicit + instances. Removed checks ^^^^^^^^^^^^^^ @@ -258,9 +273,9 @@ Removed checks Miscellaneous ^^^^^^^^^^^^^ -- Fixed incorrect formatting in ``clang-apply-replacements`` when no ``--format`` - option is specified. Now ``clang-apply-replacements`` applies formatting only with - the option. +- Fixed incorrect formatting in :program:`clang-apply-replacements` when no + ``--format`` option is specified. Now :program:`clang-apply-replacements` + applies formatting only with the option. Improvements to include-fixer ----------------------------- 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-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp index 462bc984fd3ad5609fabde7a313d9c03e4de8abd..925e5f9c1ca54e8b274139ee114b1556dcfeb327 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s modernize-use-using %t -- -- -I %S/Inputs/use-using/ +// RUN: %check_clang_tidy %s modernize-use-using %t -- -- -fno-delayed-template-parsing -I %S/Inputs/use-using/ typedef int Type; // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' [modernize-use-using] @@ -342,3 +342,44 @@ typedef int InExternCPP; // CHECK-FIXES: using InExternCPP = int; } + +namespace ISSUE_72179 +{ + void foo() + { + typedef int a; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'using' instead of 'typedef' [modernize-use-using] + // CHECK-FIXES: using a = int; + + } + + void foo2() + { + typedef struct { int a; union { int b; }; } c; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'using' instead of 'typedef' [modernize-use-using] + // CHECK-FIXES: using c = struct { int a; union { int b; }; }; + } + + template + void foo3() + { + typedef T b; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'using' instead of 'typedef' [modernize-use-using] + // CHECK-FIXES: using b = T; + } + + template + class MyClass + { + void foo() + { + typedef MyClass c; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use 'using' instead of 'typedef' [modernize-use-using] + // CHECK-FIXES: using c = MyClass; + } + }; + + const auto foo4 = [](int a){typedef int d;}; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use 'using' instead of 'typedef' [modernize-use-using] + // CHECK-FIXES: const auto foo4 = [](int a){using d = int;}; +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/static-definition-in-anonymous-namespace.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/static-definition-in-anonymous-namespace.cpp index e9938db4f5b83f216570aefe9001010b3f05e2ec..e204199393db4221feb89a4366673b92deb96ece 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/static-definition-in-anonymous-namespace.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/static-definition-in-anonymous-namespace.cpp @@ -51,6 +51,17 @@ static int c = 1; } // namespace deep_inner } // namespace inner +template +static void printTemplate(T&&) {} +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: 'printTemplate' is a static definition in anonymous namespace; static is redundant here [readability-static-definition-in-anonymous-namespace] +// CHECK-FIXES: {{^}}void printTemplate(T&&) {} + +void testTemplate() { + printTemplate(5); + printTemplate(5U); + printTemplate("some string"); +} + } // namespace namespace N { 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/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 5711972b55e6c03de349a7bc39157b34acb1e27e..7b23e4d1c2f30c1544b2eba17b2a53849a6bc6a9 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -5420,10 +5420,12 @@ The following builtin intrinsics can be used in constant expressions: * ``__builtin_clzl`` * ``__builtin_clzll`` * ``__builtin_clzs`` +* ``__builtin_clzg`` * ``__builtin_ctz`` * ``__builtin_ctzl`` * ``__builtin_ctzll`` * ``__builtin_ctzs`` +* ``__builtin_ctzg`` * ``__builtin_ffs`` * ``__builtin_ffsl`` * ``__builtin_ffsll`` diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index fd12bb41be47a3e16f28e477b425b6b367e49173..ccc399d36dbb54ef1c4b8f5e103108e8ad6e4640 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 ---------------------------------------- @@ -182,6 +188,11 @@ Non-comprehensive list of changes in this release - Lambda expressions are now accepted in C++03 mode as an extension. +- Added ``__builtin_clzg`` and ``__builtin_ctzg`` as type-generic alternatives + to ``__builtin_clz{,s,l,ll}`` and ``__builtin_ctz{,s,l,ll}`` respectively, + with support for any unsigned integer type. Like the previous builtins, these + new builtins are constexpr and may be used in constant expressions. + New Compiler Flags ------------------ @@ -289,6 +300,13 @@ Improvements to Clang's diagnostics - Clang now correctly diagnoses no arguments to a variadic macro parameter as a C23/C++20 extension. Fixes #GH84495. +- Clang no longer emits a ``-Wexit-time destructors`` warning on static variables explicitly + annotated with the ``clang::always_destroy`` attribute. + Fixes #GH68686, #GH86486 + +- ``-Wmicrosoft``, ``-Wgnu``, or ``-pedantic`` is now required to diagnose C99 + flexible array members in a union or alone in a struct. Fixes GH#84565. + Improvements to Clang's time-trace ---------------------------------- @@ -437,6 +455,9 @@ 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). +- Fix an out-of-bounds crash when checking the validity of template partial specializations. (part of #GH86757). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -520,6 +541,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 +598,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 ^^^^^^^^^^^^ @@ -607,6 +630,10 @@ Sanitizers manually disable potentially noisy signed integer overflow checks with ``-fno-sanitize=signed-integer-overflow`` +- ``-fsanitize=cfi -fsanitize-cfi-cross-dso`` (cross-DSO CFI instrumentation) + now generates the ``__cfi_check`` function with proper target-specific + attributes, for example allowing unwind table generation. + Python Binding Changes ---------------------- diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 129e75fc9a785a65a3a3028eeb439f7f8075858b..c464bc3a69adc51c1f59db5245f1fc077aed4a11 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -2441,20 +2441,39 @@ usual build cycle when using sample profilers for optimization: 1. Build the code with source line table information. You can use all the usual build flags that you always build your application with. The only - requirement is that you add ``-gline-tables-only`` or ``-g`` to the - command line. This is important for the profiler to be able to map - instructions back to source line locations. + requirement is that DWARF debug info including source line information is + generated. This DWARF information is important for the profiler to be able + to map instructions back to source line locations. + + On Linux, ``-g`` or just ``-gline-tables-only`` is sufficient: .. code-block:: console $ clang++ -O2 -gline-tables-only code.cc -o code + While MSVC-style targets default to CodeView debug information, DWARF debug + information is required to generate source-level LLVM profiles. Use + ``-gdwarf`` to include DWARF debug information: + + .. code-block:: console + + $ clang-cl -O2 -gdwarf -gline-tables-only coff-profile.cpp -fuse-ld=lld -link -debug:dwarf + 2. Run the executable under a sampling profiler. The specific profiler you use does not really matter, as long as its output can be converted - into the format that the LLVM optimizer understands. Currently, there - exists a conversion tool for the Linux Perf profiler - (https://perf.wiki.kernel.org/), so these examples assume that you - are using Linux Perf to profile your code. + into the format that the LLVM optimizer understands. + + Two such profilers are the the Linux Perf profiler + (https://perf.wiki.kernel.org/) and Intel's Sampling Enabling Product (SEP), + available as part of `Intel VTune + `_. + While Perf is Linux-specific, SEP can be used on Linux, Windows, and FreeBSD. + + The LLVM tool ``llvm-profgen`` can convert output of either Perf or SEP. An + external project, `AutoFDO `_, also + provides a ``create_llvm_prof`` tool which supports Linux Perf output. + + When using Perf: .. code-block:: console @@ -2465,11 +2484,19 @@ usual build cycle when using sample profilers for optimization: it provides better call information, which improves the accuracy of the profile data. -3. Convert the collected profile data to LLVM's sample profile format. - This is currently supported via the AutoFDO converter ``create_llvm_prof``. - It is available at https://github.com/google/autofdo. Once built and - installed, you can convert the ``perf.data`` file to LLVM using - the command: + When using SEP: + + .. code-block:: console + + $ sep -start -out code.tb7 -ec BR_INST_RETIRED.NEAR_TAKEN:precise=yes:pdir -lbr no_filter:usr -perf-script brstack -app ./code + + This produces a ``code.perf.data.script`` output which can be used with + ``llvm-profgen``'s ``--perfscript`` input option. + +3. Convert the collected profile data to LLVM's sample profile format. This is + currently supported via the `AutoFDO `_ + converter ``create_llvm_prof``. Once built and installed, you can convert + the ``perf.data`` file to LLVM using the command: .. code-block:: console @@ -2485,7 +2512,14 @@ usual build cycle when using sample profilers for optimization: .. code-block:: console - $ llvm-profgen --binary=./code --output=code.prof--perfdata=perf.data + $ llvm-profgen --binary=./code --output=code.prof --perfdata=perf.data + + When using SEP the output is in the textual format corresponding to + ``llvm-profgen --perfscript``. For example: + + .. code-block:: console + + $ llvm-profgen --binary=./code --output=code.prof --perfscript=code.perf.data.script 4. Build the code again using the collected profile. This step feeds diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index fe2115149142723724feea43e0af6d285d9dd604..8af99a021ebdfd643223e77411839002031130f9 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++) @@ -804,10 +849,89 @@ Check for performance anti-patterns when using Grand Central Dispatch. .. _optin-performance-Padding: -optin.performance.Padding -""""""""""""""""""""""""" +optin.performance.Padding (C, C++, ObjC) +"""""""""""""""""""""""""""""""""""""""" Check for excessively padded structs. +This checker detects structs with excessive padding, which can lead to wasted +memory thus decreased performance by reducing the effectiveness of the +processor cache. Padding bytes are added by compilers to align data accesses +as some processors require data to be aligned to certain boundaries. On others, +unaligned data access are possible, but impose significantly larger latencies. + +To avoid padding bytes, the fields of a struct should be ordered by decreasing +by alignment. Usually, its easier to think of the ``sizeof`` of the fields, and +ordering the fields by ``sizeof`` would usually also lead to the same optimal +layout. + +In rare cases, one can use the ``#pragma pack(1)`` directive to enforce a packed +layout too, but it can significantly increase the access times, so reordering the +fields is usually a better solution. + + +.. code-block:: cpp + + // warn: Excessive padding in 'struct NonOptimal' (35 padding bytes, where 3 is optimal) + struct NonOptimal { + char c1; + // 7 bytes of padding + std::int64_t big1; // 8 bytes + char c2; + // 7 bytes of padding + std::int64_t big2; // 8 bytes + char c3; + // 7 bytes of padding + std::int64_t big3; // 8 bytes + char c4; + // 7 bytes of padding + std::int64_t big4; // 8 bytes + char c5; + // 7 bytes of padding + }; + static_assert(sizeof(NonOptimal) == 4*8+5+5*7); + + // no-warning: The fields are nicely aligned to have the minimal amount of padding bytes. + struct Optimal { + std::int64_t big1; // 8 bytes + std::int64_t big2; // 8 bytes + std::int64_t big3; // 8 bytes + std::int64_t big4; // 8 bytes + char c1; + char c2; + char c3; + char c4; + char c5; + // 3 bytes of padding + }; + static_assert(sizeof(Optimal) == 4*8+5+3); + + // no-warning: Bit packing representation is also accepted by this checker, but + // it can significantly increase access times, so prefer reordering the fields. + #pragma pack(1) + struct BitPacked { + char c1; + std::int64_t big1; // 8 bytes + char c2; + std::int64_t big2; // 8 bytes + char c3; + std::int64_t big3; // 8 bytes + char c4; + std::int64_t big4; // 8 bytes + char c5; + }; + static_assert(sizeof(BitPacked) == 4*8+5); + +The ``AllowedPad`` option can be used to specify a threshold for the number +padding bytes raising the warning. If the number of padding bytes of the struct +and the optimal number of padding bytes differ by more than the threshold value, +a warning will be raised. + +By default, the ``AllowedPad`` threshold is 24 bytes. + +To override this threshold to e.g. 4 bytes, use the +``-analyzer-config optin.performance.Padding:AllowedPad=4`` option. + + .. _optin-portability-UnixAPI: optin.portability.UnixAPI @@ -2139,30 +2263,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-c/Index.h b/clang/include/clang-c/Index.h index 60db3cf0966c0263083b82e1dec923ffe42bcff2..7a8bd985a91fc00b2c3a6c488aca5030fc211c8d 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2991,6 +2991,7 @@ enum CXCallingConv { CXCallingConv_AArch64SVEPCS = 18, CXCallingConv_M68kRTD = 19, CXCallingConv_PreserveNone = 20, + CXCallingConv_RISCVVectorCall = 21, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 diff --git a/clang/include/clang/AST/DeclContextInternals.h b/clang/include/clang/AST/DeclContextInternals.h index 903cdb7bfcc822a2a066fe0e96d96f44f1e6e217..c4734ab578953835ee9719264ae2e9279d7d979f 100644 --- a/clang/include/clang/AST/DeclContextInternals.h +++ b/clang/include/clang/AST/DeclContextInternals.h @@ -205,7 +205,7 @@ public: Data.setPointer(Head); } - /// Return an array of all the decls that this list represents. + /// Return the list of all the decls. DeclContext::lookup_result getLookupResult() const { return DeclContext::lookup_result(Data.getPointer()); } diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index b3bf23227a47f2c1d8ed876bc3c722b04987cdf4..5d8dde37e769698d30a40ed23d273ce9305c2fa8 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1690,7 +1690,10 @@ protected: /// Whether we have a stored size expression. LLVM_PREFERRED_TYPE(bool) - unsigned HasStoredSizeExpr : 1; + unsigned HasExternalSize : 1; + + LLVM_PREFERRED_TYPE(unsigned) + unsigned SizeWidth : 5; }; class BuiltinTypeBitfields { @@ -3338,35 +3341,93 @@ public: /// Represents the canonical version of C arrays with a specified constant size. /// For example, the canonical type for 'int A[4 + 4*100]' is a /// ConstantArrayType where the element type is 'int' and the size is 404. -class ConstantArrayType final - : public ArrayType, - private llvm::TrailingObjects { +class ConstantArrayType final : public ArrayType { friend class ASTContext; // ASTContext creates these. - friend TrailingObjects; - llvm::APInt Size; // Allows us to unique the type. + struct ExternalSize { + ExternalSize(const llvm::APInt &Sz, const Expr *SE) + : Size(Sz), SizeExpr(SE) {} + llvm::APInt Size; // Allows us to unique the type. + const Expr *SizeExpr; + }; - ConstantArrayType(QualType et, QualType can, const llvm::APInt &size, - const Expr *sz, ArraySizeModifier sm, unsigned tq) - : ArrayType(ConstantArray, et, can, sm, tq, sz), Size(size) { - ConstantArrayTypeBits.HasStoredSizeExpr = sz != nullptr; - if (ConstantArrayTypeBits.HasStoredSizeExpr) { - assert(!can.isNull() && "canonical constant array should not have size"); - *getTrailingObjects() = sz; - } + union { + uint64_t Size; + ExternalSize *SizePtr; + }; + + ConstantArrayType(QualType Et, QualType Can, uint64_t Width, uint64_t Sz, + ArraySizeModifier SM, unsigned TQ) + : ArrayType(ConstantArray, Et, Can, SM, TQ, nullptr), Size(Sz) { + ConstantArrayTypeBits.HasExternalSize = false; + ConstantArrayTypeBits.SizeWidth = Width / 8; + // The in-structure size stores the size in bytes rather than bits so we + // drop the three least significant bits since they're always zero anyways. + assert(Width < 0xFF && "Type width in bits must be less than 8 bits"); } - unsigned numTrailingObjects(OverloadToken) const { - return ConstantArrayTypeBits.HasStoredSizeExpr; + ConstantArrayType(QualType Et, QualType Can, ExternalSize *SzPtr, + ArraySizeModifier SM, unsigned TQ) + : ArrayType(ConstantArray, Et, Can, SM, TQ, SzPtr->SizeExpr), + SizePtr(SzPtr) { + ConstantArrayTypeBits.HasExternalSize = true; + ConstantArrayTypeBits.SizeWidth = 0; + + assert((SzPtr->SizeExpr == nullptr || !Can.isNull()) && + "canonical constant array should not have size expression"); } + static ConstantArrayType *Create(const ASTContext &Ctx, QualType ET, + QualType Can, const llvm::APInt &Sz, + const Expr *SzExpr, ArraySizeModifier SzMod, + unsigned Qual); + public: - const llvm::APInt &getSize() const { return Size; } + /// Return the constant array size as an APInt. + llvm::APInt getSize() const { + return ConstantArrayTypeBits.HasExternalSize + ? SizePtr->Size + : llvm::APInt(ConstantArrayTypeBits.SizeWidth * 8, Size); + } + + /// Return the bit width of the size type. + unsigned getSizeBitWidth() const { + return ConstantArrayTypeBits.HasExternalSize + ? SizePtr->Size.getBitWidth() + : static_cast(ConstantArrayTypeBits.SizeWidth * 8); + } + + /// Return true if the size is zero. + bool isZeroSize() const { + return ConstantArrayTypeBits.HasExternalSize ? SizePtr->Size.isZero() + : 0 == Size; + } + + /// Return the size zero-extended as a uint64_t. + uint64_t getZExtSize() const { + return ConstantArrayTypeBits.HasExternalSize ? SizePtr->Size.getZExtValue() + : Size; + } + + /// Return the size sign-extended as a uint64_t. + int64_t getSExtSize() const { + return ConstantArrayTypeBits.HasExternalSize ? SizePtr->Size.getSExtValue() + : static_cast(Size); + } + + /// Return the size zero-extended to uint64_t or UINT64_MAX if the value is + /// larger than UINT64_MAX. + uint64_t getLimitedSize() const { + return ConstantArrayTypeBits.HasExternalSize + ? SizePtr->Size.getLimitedValue() + : Size; + } + + /// Return a pointer to the size expression. const Expr *getSizeExpr() const { - return ConstantArrayTypeBits.HasStoredSizeExpr - ? *getTrailingObjects() - : nullptr; + return ConstantArrayTypeBits.HasExternalSize ? SizePtr->SizeExpr : nullptr; } + bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -3383,14 +3444,13 @@ public: static unsigned getMaxSizeBits(const ASTContext &Context); void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { - Profile(ID, Ctx, getElementType(), getSize(), getSizeExpr(), + Profile(ID, Ctx, getElementType(), getZExtSize(), getSizeExpr(), getSizeModifier(), getIndexTypeCVRQualifiers()); } static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx, - QualType ET, const llvm::APInt &ArraySize, - const Expr *SizeExpr, ArraySizeModifier SizeMod, - unsigned TypeQuals); + QualType ET, uint64_t ArraySize, const Expr *SizeExpr, + ArraySizeModifier SizeMod, unsigned TypeQuals); static bool classof(const Type *T) { return T->getTypeClass() == ConstantArray; 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/Attr.td b/clang/include/clang/Basic/Attr.td index 3e03e55612645bd8c521524bfc29e70756d1e317..80e607525a0a37dcdaff9f508cb222b3a402da8d 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3011,6 +3011,13 @@ def PreserveNone : DeclOrTypeAttr, TargetSpecificAttr { let Documentation = [PreserveNoneDocs]; } +def RISCVVectorCC: DeclOrTypeAttr, TargetSpecificAttr { + let Spellings = [CXX11<"riscv", "vector_cc">, + C23<"riscv", "vector_cc">, + Clang<"riscv_vector_cc">]; + let Documentation = [RISCVVectorCCDocs]; +} + def Target : InheritableAttr { let Spellings = [GCC<"target">]; let Args = [StringArgument<"featuresStr">]; @@ -3088,6 +3095,20 @@ def TargetClones : InheritableAttr { StringRef getFeatureStr(unsigned Index) const { return *(featuresStrs_begin() + Index); } + bool isDefaultVersion(unsigned Index) const { + return getFeatureStr(Index) == "default"; + } + void getFeatures(llvm::SmallVectorImpl &Out, + unsigned Index) const { + if (isDefaultVersion(Index)) return; + StringRef Features = getFeatureStr(Index); + SmallVector AttrFeatures; + Features.split(AttrFeatures, "+"); + for (auto &Feature : AttrFeatures) { + Feature = Feature.trim(); + Out.push_back(Feature); + } + } // Given an index into the 'featuresStrs' sequence, compute a unique // ID to be used with function name mangling for the associated variant. // This mapping is necessary due to a requirement that the mangling ID diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 9de14f608fd114792d10bffc04f3fa64be3a3a41..3ea4d676b4f89d30eb03a5e80419dfccfeca06e9 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -5494,6 +5494,17 @@ for clang builtin functions. }]; } +def RISCVVectorCCDocs : Documentation { + let Category = DocCatCallingConvs; + let Heading = "riscv::vector_cc, riscv_vector_cc, clang::riscv_vector_cc"; + let Content = [{ +The ``riscv_vector_cc`` attribute can be applied to a function. It preserves 15 +registers namely, v1-v7 and v24-v31 as callee-saved. Callers thus don't need +to save these registers before function calls, and callees only need to save +them if they use them. + }]; +} + def PreferredNameDocs : Documentation { let Category = DocCatDecl; let Content = [{ @@ -6069,6 +6080,9 @@ def AlwaysDestroyDocs : Documentation { The ``always_destroy`` attribute specifies that a variable with static or thread storage duration should have its exit-time destructor run. This attribute is the default unless clang was invoked with -fno-c++-static-destructors. + +If a variable is explicitly declared with this attribute, Clang will silence +otherwise applicable ``-Wexit-time-destructors`` warnings. }]; } diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 21ab9bb86d1b8ca080e23e6155cc172aa9a34546..52c0dd52c28b11baf2ed087f1b12865a5e51cdb0 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -678,7 +678,7 @@ def Clz : Builtin, BitShort_Int_Long_LongLongTemplate { def Clzg : Builtin { let Spellings = ["__builtin_clzg"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; let Prototype = "int(...)"; } @@ -690,7 +690,7 @@ def Ctz : Builtin, BitShort_Int_Long_LongLongTemplate { def Ctzg : Builtin { let Spellings = ["__builtin_ctzg"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; let Prototype = "int(...)"; } diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def index 61ec8b79bf054daa03e02fddca3c4edb2da75088..c660582cc98e666031ae1dfbecf9d9b4612c9eae 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -432,13 +432,10 @@ 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_b64_i32, "ii*1", "nc", "gfx12-insts,wavefrontsize64") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v4i16, "V4sV4s*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..e3263fe9ccb9d4177a70b83ab5cf260693ed7278 100644 --- a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td +++ b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td @@ -15,6 +15,10 @@ 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; +def err_no_such_umbrella_header_file : Error<"%select{public|private|project}1 umbrella header file not found in input: '%0'">; } // end of command line category. let CategoryName = "Verification" in { @@ -26,6 +30,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/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index fc727cef9cd835805ad1641f7045aa3a447c912f..51af81bf1f6fc5a0382980761ff22bafbaa2037c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6464,9 +6464,6 @@ def ext_c99_flexible_array_member : Extension< def err_flexible_array_virtual_base : Error< "flexible array member %0 not allowed in " "%select{struct|interface|union|class|enum}1 which has a virtual base class">; -def err_flexible_array_empty_aggregate : Error< - "flexible array member %0 not allowed in otherwise empty " - "%select{struct|interface|union|class|enum}1">; def err_flexible_array_has_nontrivial_dtor : Error< "flexible array member %0 of type %1 with non-trivial destruction">; def ext_flexible_array_in_struct : Extension< @@ -6481,8 +6478,6 @@ def ext_flexible_array_empty_aggregate_ms : Extension< "flexible array member %0 in otherwise empty " "%select{struct|interface|union|class|enum}1 is a Microsoft extension">, InGroup; -def err_flexible_array_union : Error< - "flexible array member %0 in a union is not allowed">; def ext_flexible_array_union_ms : Extension< "flexible array member %0 in a union is a Microsoft extension">, InGroup; 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/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index 8586405825cfe01514754591f0855be2f5667c62..fb11e8212f8b68f235faa690aab875b56096c8f6 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -273,29 +273,30 @@ namespace clang { /// CallingConv - Specifies the calling convention that a function uses. enum CallingConv { - CC_C, // __attribute__((cdecl)) - CC_X86StdCall, // __attribute__((stdcall)) - CC_X86FastCall, // __attribute__((fastcall)) - CC_X86ThisCall, // __attribute__((thiscall)) - CC_X86VectorCall, // __attribute__((vectorcall)) - CC_X86Pascal, // __attribute__((pascal)) - CC_Win64, // __attribute__((ms_abi)) - CC_X86_64SysV, // __attribute__((sysv_abi)) - CC_X86RegCall, // __attribute__((regcall)) - CC_AAPCS, // __attribute__((pcs("aapcs"))) - CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp"))) - CC_IntelOclBicc, // __attribute__((intel_ocl_bicc)) - CC_SpirFunction, // default for OpenCL functions on SPIR target - CC_OpenCLKernel, // inferred for OpenCL kernels - CC_Swift, // __attribute__((swiftcall)) + CC_C, // __attribute__((cdecl)) + CC_X86StdCall, // __attribute__((stdcall)) + CC_X86FastCall, // __attribute__((fastcall)) + CC_X86ThisCall, // __attribute__((thiscall)) + CC_X86VectorCall, // __attribute__((vectorcall)) + CC_X86Pascal, // __attribute__((pascal)) + CC_Win64, // __attribute__((ms_abi)) + CC_X86_64SysV, // __attribute__((sysv_abi)) + CC_X86RegCall, // __attribute__((regcall)) + CC_AAPCS, // __attribute__((pcs("aapcs"))) + CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp"))) + CC_IntelOclBicc, // __attribute__((intel_ocl_bicc)) + CC_SpirFunction, // default for OpenCL functions on SPIR target + CC_OpenCLKernel, // inferred for OpenCL kernels + CC_Swift, // __attribute__((swiftcall)) CC_SwiftAsync, // __attribute__((swiftasynccall)) - CC_PreserveMost, // __attribute__((preserve_most)) - CC_PreserveAll, // __attribute__((preserve_all)) + CC_PreserveMost, // __attribute__((preserve_most)) + CC_PreserveAll, // __attribute__((preserve_all)) CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs)) - CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs)) - CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel)) - CC_M68kRTD, // __attribute__((m68k_rtd)) - CC_PreserveNone, // __attribute__((preserve_none)) + CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs)) + CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel)) + CC_M68kRTD, // __attribute__((m68k_rtd)) + CC_PreserveNone, // __attribute__((preserve_none)) + CC_RISCVVectorCall, // __attribute__((riscv_vector_cc)) }; /// Checks whether the given calling convention supports variadic diff --git a/clang/include/clang/Basic/SyncScope.h b/clang/include/clang/Basic/SyncScope.h index bc7ec7b5cf777ef4556678445dc44fed078dcfb5..45beff41afa11d3286afad7b2336567b4aa72c8a 100644 --- a/clang/include/clang/Basic/SyncScope.h +++ b/clang/include/clang/Basic/SyncScope.h @@ -252,8 +252,7 @@ public: } bool isValid(unsigned S) const override { - return S >= static_cast(System) && - S <= static_cast(Last); + return S <= static_cast(Last); } ArrayRef getRuntimeValues() const override { diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 4a954258ce40b6a7050c66a478f7bcc9d866b9cf..29066ea14280c2a38663a55f0ba5bab8453b6d86 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4105,12 +4105,8 @@ defm strict_return : BoolFOption<"strict-return", " of a non-void function as unreachable">, PosFlag>; -let Group = f_Group in { - let Visibility = [ClangOption,CC1Option] in { - def fptrauth_intrinsics : Flag<["-"], "fptrauth-intrinsics">, - HelpText<"Enable pointer authentication intrinsics">; - } - def fno_ptrauth_intrinsics : Flag<["-"], "fno-ptrauth-intrinsics">; +let Flags = [TargetSpecific] in { +defm ptrauth_intrinsics : OptInCC1FFlag<"ptrauth-intrinsics", "Enable pointer authentication intrinsics">; } def fenable_matrix : Flag<["-"], "fenable-matrix">, Group, @@ -6688,6 +6684,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..c67503d4ad49e934a6e4ac6927e9bd95fabd4567 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" @@ -22,8 +24,6 @@ namespace clang::installapi { enum class HeaderType { - /// Unset or unknown type. - Unknown, /// Represents declarations accessible to all clients. Public, /// Represents declarations accessible to a disclosed set of clients. @@ -31,6 +31,8 @@ enum class HeaderType { /// Represents declarations only accessible as implementation details to the /// input library. Project, + /// Unset or unknown type. + Unknown, }; inline StringRef getName(const HeaderType T) { @@ -56,6 +58,12 @@ 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}; + /// Specify that header file is the umbrella header for library. + bool Umbrella{false}; public: HeaderFile() = delete; @@ -71,17 +79,52 @@ 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; } + void setUmbrellaHeader(bool V = true) { Umbrella = V; } + bool isExtra() const { return Extra; } + bool isExcluded() const { return Excluded; } + bool isUmbrellaHeader() const { return Umbrella; } + bool useIncludeName() const { return Type != HeaderType::Project && !IncludeName.empty(); } bool operator==(const HeaderFile &Other) const { - return std::tie(Type, FullPath, IncludeName, Language) == - std::tie(Other.Type, Other.FullPath, Other.IncludeName, - Other.Language); + return std::tie(Type, FullPath, IncludeName, Language, Excluded, Extra, + Umbrella) == std::tie(Other.Type, Other.FullPath, + Other.IncludeName, Other.Language, + Other.Excluded, Other.Extra, + Other.Umbrella); } }; +/// 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 +136,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/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 5ecd2f9eb2881f3d6e5e19a0409b8b8f5d533117..3a1abd4c7892b82ef30db2e17ec319eb814137b9 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2234,7 +2234,8 @@ private: bool CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum); bool CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall); - void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D); + void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D, + const llvm::StringMap &FeatureMap); bool CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall); bool CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 686e5e99f4a62c4a2649ea40849998968aa3e92b..5fe5c9286dabb791937aa53041252745a605afe5 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">, @@ -908,7 +908,7 @@ def PaddingChecker : Checker<"Padding">, "24", Released> ]>, - Documentation; + Documentation; } // end: "padding" 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/APValue.cpp b/clang/lib/AST/APValue.cpp index 4eae308ef5b34c608df0783c187130ae5bcf792b..d8042321319a67b253b034d8a0d4572a97f14d2f 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -704,6 +704,9 @@ void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy, return; } + if (const auto *AT = Ty->getAs()) + Ty = AT->getValueType(); + switch (getKind()) { case APValue::None: Out << ""; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index fcf801adeaf5ef55e05393f6426eabae18e4cfcd..c90fafb6f653d0543b58246335e069746e277f18 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1766,7 +1766,7 @@ TypeInfoChars static getConstantArrayInfoInChars(const ASTContext &Context, const ConstantArrayType *CAT) { TypeInfoChars EltInfo = Context.getTypeInfoInChars(CAT->getElementType()); - uint64_t Size = CAT->getSize().getZExtValue(); + uint64_t Size = CAT->getZExtSize(); assert((Size == 0 || static_cast(EltInfo.Width.getQuantity()) <= (uint64_t)(-1)/Size) && "Overflow in array type char size evaluation"); @@ -1910,7 +1910,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { // Model non-constant sized arrays as size zero, but track the alignment. uint64_t Size = 0; if (const auto *CAT = dyn_cast(T)) - Size = CAT->getSize().getZExtValue(); + Size = CAT->getZExtSize(); TypeInfo EltInfo = getTypeInfo(cast(T)->getElementType()); assert((Size == 0 || EltInfo.Width <= (uint64_t)(-1) / Size) && @@ -3560,8 +3560,8 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, ArySize = ArySize.zextOrTrunc(Target->getMaxPointerWidth()); llvm::FoldingSetNodeID ID; - ConstantArrayType::Profile(ID, *this, EltTy, ArySize, SizeExpr, ASM, - IndexTypeQuals); + ConstantArrayType::Profile(ID, *this, EltTy, ArySize.getZExtValue(), SizeExpr, + ASM, IndexTypeQuals); void *InsertPos = nullptr; if (ConstantArrayType *ATP = @@ -3585,11 +3585,8 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - void *Mem = Allocate( - ConstantArrayType::totalSizeToAlloc(SizeExpr ? 1 : 0), - alignof(ConstantArrayType)); - auto *New = new (Mem) - ConstantArrayType(EltTy, Canon, ArySize, SizeExpr, ASM, IndexTypeQuals); + auto *New = ConstantArrayType::Create(*this, EltTy, Canon, ArySize, SizeExpr, + ASM, IndexTypeQuals); ConstantArrayTypes.InsertNode(New, InsertPos); Types.push_back(New); return QualType(New, 0); @@ -7051,7 +7048,7 @@ uint64_t ASTContext::getConstantArrayElementCount(const ConstantArrayType *CA) const { uint64_t ElementCount = 1; do { - ElementCount *= CA->getSize().getZExtValue(); + ElementCount *= CA->getZExtSize(); CA = dyn_cast_or_null( CA->getElementType()->getAsArrayTypeUnsafe()); } while (CA); @@ -8374,7 +8371,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S, S += '['; if (const auto *CAT = dyn_cast(AT)) - S += llvm::utostr(CAT->getSize().getZExtValue()); + S += llvm::utostr(CAT->getZExtSize()); else { //Variable length arrays are encoded as a regular array with 0 elements. assert((isa(AT) || isa(AT)) && @@ -9603,11 +9600,11 @@ static uint64_t getRVVTypeSize(ASTContext &Context, const BuiltinType *Ty) { ASTContext::BuiltinVectorTypeInfo Info = Context.getBuiltinVectorTypeInfo(Ty); - unsigned EltSize = Context.getTypeSize(Info.ElementType); + uint64_t EltSize = Context.getTypeSize(Info.ElementType); if (Info.ElementType == Context.BoolTy) EltSize = 1; - unsigned MinElts = Info.EC.getKnownMinValue(); + uint64_t MinElts = Info.EC.getKnownMinValue(); return VScale->first * MinElts * EltSize; } @@ -10808,7 +10805,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool OfBlockPointer, { const ConstantArrayType* LCAT = getAsConstantArrayType(LHS); const ConstantArrayType* RCAT = getAsConstantArrayType(RHS); - if (LCAT && RCAT && RCAT->getSize() != LCAT->getSize()) + if (LCAT && RCAT && RCAT->getZExtSize() != LCAT->getZExtSize()) return {}; QualType LHSElem = getAsArrayType(LHS)->getElementType(); @@ -13676,22 +13673,19 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap &FeatureMap, Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features); } else if (const auto *TC = FD->getAttr()) { std::vector Features; - StringRef VersionStr = TC->getFeatureStr(GD.getMultiVersionIndex()); if (Target->getTriple().isAArch64()) { // TargetClones for AArch64 - if (VersionStr != "default") { - SmallVector VersionFeatures; - VersionStr.split(VersionFeatures, "+"); - for (auto &VFeature : VersionFeatures) { - VFeature = VFeature.trim(); + llvm::SmallVector Feats; + TC->getFeatures(Feats, GD.getMultiVersionIndex()); + for (StringRef Feat : Feats) + if (Target->validateCpuSupports(Feat.str())) // Use '?' to mark features that came from AArch64 TargetClones. - Features.push_back((StringRef{"?"} + VFeature).str()); - } - } + Features.push_back("?" + Feat.str()); Features.insert(Features.begin(), Target->getTargetOpts().FeaturesAsWritten.begin(), Target->getTargetOpts().FeaturesAsWritten.end()); } else { + StringRef VersionStr = TC->getFeatureStr(GD.getMultiVersionIndex()); if (VersionStr.starts_with("arch=")) TargetCPU = VersionStr.drop_front(sizeof("arch=") - 1); else if (VersionStr != "default") diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 95900afdd2c5d8e17e68a0fe38f9fd38a751c4da..131f82985e903bb6e2e76458fc03686f0702e3ef 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2840,7 +2840,7 @@ bool VarDecl::hasFlexibleArrayInit(const ASTContext &Ctx) const { auto InitTy = Ctx.getAsConstantArrayType(FlexibleInit->getType()); if (!InitTy) return false; - return InitTy->getSize() != 0; + return !InitTy->isZeroSize(); } CharUnits VarDecl::getFlexibleArrayInitChars(const ASTContext &Ctx) const { diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 592d43597dc1b45a4f325602f80bb39da5758c78..5a36621dc5cce28780753e647219c806e7fb9f5f 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -209,7 +209,7 @@ namespace { IsArray = true; if (auto *CAT = dyn_cast(AT)) { - ArraySize = CAT->getSize().getZExtValue(); + ArraySize = CAT->getZExtSize(); } else { assert(I == 0 && "unexpected unsized array designator"); FirstEntryIsUnsizedArray = true; @@ -401,7 +401,7 @@ namespace { // This is a most-derived object. MostDerivedType = CAT->getElementType(); MostDerivedIsArrayElement = true; - MostDerivedArraySize = CAT->getSize().getZExtValue(); + MostDerivedArraySize = CAT->getZExtSize(); MostDerivedPathLength = Entries.size(); } /// Update this designator to refer to the first element within the array of @@ -3476,7 +3476,7 @@ static void expandStringLiteral(EvalInfo &Info, const StringLiteral *S, QualType CharType = CAT->getElementType(); assert(CharType->isIntegerType() && "unexpected character type"); - unsigned Elts = CAT->getSize().getZExtValue(); + unsigned Elts = CAT->getZExtSize(); Result = APValue(APValue::UninitArray(), std::min(S->getLength(), Elts), Elts); APSInt Value(Info.Ctx.getTypeSize(CharType), @@ -3619,7 +3619,7 @@ static bool CheckArraySize(EvalInfo &Info, const ConstantArrayType *CAT, SourceLocation CallLoc = {}) { return Info.CheckArraySize( CAT->getSizeExpr() ? CAT->getSizeExpr()->getBeginLoc() : CallLoc, - CAT->getNumAddressingBits(Info.Ctx), CAT->getSize().getZExtValue(), + CAT->getNumAddressingBits(Info.Ctx), CAT->getZExtSize(), /*Diag=*/true); } @@ -4908,7 +4908,7 @@ static bool handleDefaultInitValue(QualType T, APValue &Result) { if (auto *AT = dyn_cast_or_null(T->getAsArrayTypeUnsafe())) { - Result = APValue(APValue::UninitArray(), 0, AT->getSize().getZExtValue()); + Result = APValue(APValue::UninitArray(), 0, AT->getZExtSize()); if (Result.hasArrayFiller()) Success &= handleDefaultInitValue(AT->getElementType(), Result.getArrayFiller()); @@ -6595,7 +6595,7 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceRange CallRange, // For arrays, destroy elements right-to-left. if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(T)) { - uint64_t Size = CAT->getSize().getZExtValue(); + uint64_t Size = CAT->getZExtSize(); QualType ElemT = CAT->getElementType(); if (!CheckArraySize(Info, CAT, CallRange.getBegin())) @@ -7396,7 +7396,7 @@ class BufferToAPValueConverter { } std::optional visit(const ConstantArrayType *Ty, CharUnits Offset) { - size_t Size = Ty->getSize().getLimitedValue(); + size_t Size = Ty->getLimitedSize(); CharUnits ElementWidth = Info.Ctx.getTypeSizeInChars(Ty->getElementType()); APValue ArrayValue(APValue::UninitArray(), Size, Size); @@ -9951,7 +9951,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { assert(CAT && "unexpected type for array initializer"); unsigned Bits = - std::max(CAT->getSize().getBitWidth(), ArrayBound.getBitWidth()); + std::max(CAT->getSizeBitWidth(), ArrayBound.getBitWidth()); llvm::APInt InitBound = CAT->getSize().zext(Bits); llvm::APInt AllocBound = ArrayBound.zext(Bits); if (InitBound.ugt(AllocBound)) { @@ -10410,7 +10410,7 @@ bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr( if (Field->getType()->isIncompleteArrayType()) { if (auto *CAT = Info.Ctx.getAsConstantArrayType(Init->getType())) { - if (!CAT->getSize().isZero()) { + if (!CAT->isZeroSize()) { // Bail out for now. This might sort of "work", but the rest of the // code isn't really prepared to handle it. Info.FFDiag(Init, diag::note_constexpr_unsupported_flexible_array); @@ -10554,7 +10554,7 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr( // End pointer. if (!HandleLValueArrayAdjustment(Info, E, Array, ArrayType->getElementType(), - ArrayType->getSize().getZExtValue())) + ArrayType->getZExtSize())) return false; Array.moveInto(Result.getStructField(1)); } else if (Info.Ctx.hasSameType(Field->getType(), Info.Ctx.getSizeType())) @@ -10996,8 +10996,7 @@ namespace { return Error(E); } - Result = APValue(APValue::UninitArray(), 0, - CAT->getSize().getZExtValue()); + Result = APValue(APValue::UninitArray(), 0, CAT->getZExtSize()); if (!Result.hasArrayFiller()) return true; @@ -11122,7 +11121,7 @@ bool ArrayExprEvaluator::VisitCXXParenListOrInitListExpr( Filler = Result.getArrayFiller(); unsigned NumEltsToInit = Args.size(); - unsigned NumElts = CAT->getSize().getZExtValue(); + unsigned NumElts = CAT->getZExtSize(); // If the initializer might depend on the array index, run it for each // array element. @@ -11180,7 +11179,7 @@ bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { auto *CAT = cast(E->getType()->castAsArrayTypeUnsafe()); - uint64_t Elements = CAT->getSize().getZExtValue(); + uint64_t Elements = CAT->getZExtSize(); Result = APValue(APValue::UninitArray(), Elements, Elements); LValue Subobject = This; @@ -11225,7 +11224,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, bool HadZeroInit = Value->hasValue(); if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(Type)) { - unsigned FinalSize = CAT->getSize().getZExtValue(); + unsigned FinalSize = CAT->getZExtSize(); // Preserve the array filler if we had prior zero-initialization. APValue Filler = @@ -11940,7 +11939,7 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { return true; const auto *CAT = cast(Ctx.getAsArrayType(BaseType)); uint64_t Index = Entry.getAsArrayIndex(); - if (Index + 1 != CAT->getSize()) + if (Index + 1 != CAT->getZExtSize()) return false; BaseType = CAT->getElementType(); } else if (BaseType->isAnyComplexType()) { @@ -12354,6 +12353,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, case Builtin::BI__builtin_clzl: case Builtin::BI__builtin_clzll: case Builtin::BI__builtin_clzs: + case Builtin::BI__builtin_clzg: case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes case Builtin::BI__lzcnt: case Builtin::BI__lzcnt64: { @@ -12361,14 +12361,23 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; - // When the argument is 0, the result of GCC builtins is undefined, whereas - // for Microsoft intrinsics, the result is the bit-width of the argument. - bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 && - BuiltinOp != Builtin::BI__lzcnt && - BuiltinOp != Builtin::BI__lzcnt64; + if (!Val) { + if (BuiltinOp == Builtin::BI__builtin_clzg && E->getNumArgs() > 1) { + if (!EvaluateInteger(E->getArg(1), Val, Info)) + return false; + return Success(Val, E); + } - if (ZeroIsUndefined && !Val) - return Error(E); + // When the argument is 0, the result of GCC builtins is undefined, + // whereas for Microsoft intrinsics, the result is the bit-width of the + // argument. + bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 && + BuiltinOp != Builtin::BI__lzcnt && + BuiltinOp != Builtin::BI__lzcnt64; + + if (ZeroIsUndefined) + return Error(E); + } return Success(Val.countl_zero(), E); } @@ -12410,12 +12419,21 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: case Builtin::BI__builtin_ctzll: - case Builtin::BI__builtin_ctzs: { + case Builtin::BI__builtin_ctzs: + case Builtin::BI__builtin_ctzg: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; - if (!Val) + + if (!Val) { + if (BuiltinOp == Builtin::BI__builtin_ctzg && E->getNumArgs() > 1) { + if (!EvaluateInteger(E->getArg(1), Val, Info)) + return false; + return Success(Val, E); + } + return Error(E); + } return Success(Val.countr_zero(), E); } diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 73831eefba45687a9a469cd722f3aedf312c8fd7..46182809810bcf5108e90ff8a05b84dbc35d8d07 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -819,7 +819,7 @@ bool ByteCodeExprGen::VisitImplicitValueInitExpr(const ImplicitValueIni const ArrayType *AT = QT->getAsArrayTypeUnsafe(); assert(AT); const auto *CAT = cast(AT); - size_t NumElems = CAT->getSize().getZExtValue(); + size_t NumElems = CAT->getZExtSize(); PrimType ElemT = classifyPrim(CAT->getElementType()); for (size_t I = 0; I != NumElems; ++I) { @@ -992,7 +992,7 @@ bool ByteCodeExprGen::VisitInitListExpr(const InitListExpr *E) { if (const Expr *Filler = E->getArrayFiller()) { const ConstantArrayType *CAT = Ctx.getASTContext().getAsConstantArrayType(E->getType()); - uint64_t NumElems = CAT->getSize().getZExtValue(); + uint64_t NumElems = CAT->getZExtSize(); for (; ElementIndex != NumElems; ++ElementIndex) { if (!this->visitArrayElemInit(ElementIndex, Filler)) @@ -1318,7 +1318,7 @@ bool ByteCodeExprGen::VisitStringLiteral(const StringLiteral *E) { // If the initializer string is too long, a diagnostic has already been // emitted. Read only the array length from the string literal. - unsigned ArraySize = CAT->getSize().getZExtValue(); + unsigned ArraySize = CAT->getZExtSize(); unsigned N = std::min(ArraySize, E->getLength()); size_t CharWidth = E->getCharByteWidth(); @@ -1919,7 +1919,7 @@ bool ByteCodeExprGen::VisitCXXConstructExpr( const ConstantArrayType *CAT = Ctx.getASTContext().getAsConstantArrayType(E->getType()); assert(CAT); - size_t NumElems = CAT->getSize().getZExtValue(); + size_t NumElems = CAT->getZExtSize(); const Function *Func = getFunction(E->getConstructor()); if (!Func || !Func->isConstexpr()) return false; diff --git a/clang/lib/AST/Interp/EvaluationResult.cpp b/clang/lib/AST/Interp/EvaluationResult.cpp index 07b28d07326f9017bfd0a0a6311f7fe0b75024fe..d567b551f7f6fcffbab18b4c067572f8f4960f15 100644 --- a/clang/lib/AST/Interp/EvaluationResult.cpp +++ b/clang/lib/AST/Interp/EvaluationResult.cpp @@ -66,7 +66,7 @@ static bool CheckArrayInitialized(InterpState &S, SourceLocation Loc, const Pointer &BasePtr, const ConstantArrayType *CAT) { bool Result = true; - size_t NumElems = CAT->getSize().getZExtValue(); + size_t NumElems = CAT->getZExtSize(); QualType ElemType = CAT->getElementType(); if (ElemType->isRecordType()) { diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index da6f72c62115dd94a3c216ce9cbbc2351aaadf3e..25e938e0150322109fd619eada6970f7b6c09d8f 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -355,7 +355,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, QualType ElemTy = ArrayType->getElementType(); // Array of well-known bounds. if (auto CAT = dyn_cast(ArrayType)) { - size_t NumElems = CAT->getSize().getZExtValue(); + size_t NumElems = CAT->getZExtSize(); if (std::optional T = Ctx.classify(ElemTy)) { // Arrays of primitives. unsigned ElemSize = primSize(*T); diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index f619d657ae9f50c4491532d497eaf7d54522acdd..425f84e8af1fe79bc4acfb38024c47cfa09d8eec 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3445,6 +3445,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) { case CC_PreserveAll: case CC_M68kRTD: case CC_PreserveNone: + case CC_RISCVVectorCall: // FIXME: we should be mangling all of the above. return ""; diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index e27d44fc2ffe67316d2f4175c4c04856e8ae222e..5861d5a7ea0dd2df6686f4f61f086bf9e58275c5 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -695,7 +695,7 @@ void JSONNodeDumper::VisitArrayType(const ArrayType *AT) { void JSONNodeDumper::VisitConstantArrayType(const ConstantArrayType *CAT) { // FIXME: this should use ZExt instead of SExt, but JSON doesn't allow a // narrowing conversion to int64_t so it cannot be expressed. - JOS.attribute("size", CAT->getSize().getSExtValue()); + JOS.attribute("size", CAT->getSExtSize()); VisitArrayType(CAT); } diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index aa26bb7ed46f482cfa4b7e02dee65c0f69a303b0..addc3140546a46385618e72b24362f8a510a59fb 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, ""); } @@ -4022,10 +4023,8 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, // char bar[42] = "foobar"; // Where it is truncated or zero-padded to fit the array. This is the length // used for mangling, and any trailing null-bytes also need to be mangled. - unsigned StringLength = getASTContext() - .getAsConstantArrayType(SL->getType()) - ->getSize() - .getZExtValue(); + unsigned StringLength = + getASTContext().getAsConstantArrayType(SL->getType())->getZExtSize(); unsigned StringByteLength = StringLength * SL->getCharByteWidth(); // : The "kind" of string literal is encoded into the mangled name. diff --git a/clang/lib/AST/ScanfFormatString.cpp b/clang/lib/AST/ScanfFormatString.cpp index 64c430e623b577e1101f5807bea2d57b95b8ec56..7ee21c8c619544009c454cae8940832b2a40a967 100644 --- a/clang/lib/AST/ScanfFormatString.cpp +++ b/clang/lib/AST/ScanfFormatString.cpp @@ -448,9 +448,7 @@ bool ScanfSpecifier::fixType(QualType QT, QualType RawQT, if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) { if (CAT->getSizeModifier() == ArraySizeModifier::Normal) FieldWidth = OptionalAmount(OptionalAmount::Constant, - CAT->getSize().getZExtValue() - 1, - "", 0, false); - + CAT->getZExtSize() - 1, "", 0, false); } return true; } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index c6fe90ba5e292736976286bffcdc5caa30b1f508..8f3e26d4601921660685f74cf4e63e216482c4d0 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -159,6 +159,22 @@ ArrayType::ArrayType(TypeClass tc, QualType et, QualType can, ArrayTypeBits.SizeModifier = llvm::to_underlying(sm); } +ConstantArrayType * +ConstantArrayType::Create(const ASTContext &Ctx, QualType ET, QualType Can, + const llvm::APInt &Sz, const Expr *SzExpr, + ArraySizeModifier SzMod, unsigned Qual) { + bool NeedsExternalSize = SzExpr != nullptr || Sz.ugt(0x0FFFFFFFFFFFFFFF) || + Sz.getBitWidth() > 0xFF; + if (!NeedsExternalSize) + return new (Ctx, alignof(ConstantArrayType)) ConstantArrayType( + ET, Can, Sz.getBitWidth(), Sz.getZExtValue(), SzMod, Qual); + + auto *SzPtr = new (Ctx, alignof(ConstantArrayType::ExternalSize)) + ConstantArrayType::ExternalSize(Sz, SzExpr); + return new (Ctx, alignof(ConstantArrayType)) + ConstantArrayType(ET, Can, SzPtr, SzMod, Qual); +} + unsigned ConstantArrayType::getNumAddressingBits(const ASTContext &Context, QualType ElementType, const llvm::APInt &NumElements) { @@ -213,11 +229,10 @@ unsigned ConstantArrayType::getMaxSizeBits(const ASTContext &Context) { void ConstantArrayType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, QualType ET, - const llvm::APInt &ArraySize, - const Expr *SizeExpr, ArraySizeModifier SizeMod, - unsigned TypeQuals) { + uint64_t ArraySize, const Expr *SizeExpr, + ArraySizeModifier SizeMod, unsigned TypeQuals) { ID.AddPointer(ET.getAsOpaquePtr()); - ID.AddInteger(ArraySize.getZExtValue()); + ID.AddInteger(ArraySize); ID.AddInteger(llvm::to_underlying(SizeMod)); ID.AddInteger(TypeQuals); ID.AddBoolean(SizeExpr != nullptr); @@ -452,12 +467,8 @@ QualType QualType::getSingleStepDesugaredTypeImpl(QualType type, // Check that no type class has a non-trival destructor. Types are // allocated with the BumpPtrAllocator from ASTContext and therefore // their destructor is not executed. -// -// FIXME: ConstantArrayType is not trivially destructible because of its -// APInt member. It should be replaced in favor of ASTContext allocation. #define TYPE(CLASS, BASE) \ - static_assert(std::is_trivially_destructible::value || \ - std::is_same::value, \ + static_assert(std::is_trivially_destructible::value, \ #CLASS "Type should be trivially destructible!"); #include "clang/AST/TypeNodes.inc" @@ -3473,6 +3484,9 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_PreserveAll: return "preserve_all"; case CC_M68kRTD: return "m68k_rtd"; case CC_PreserveNone: return "preserve_none"; + // clang-format off + case CC_RISCVVectorCall: return "riscv_vector_cc"; + // clang-format on } llvm_unreachable("Invalid calling convention."); @@ -4063,6 +4077,7 @@ bool AttributedType::isCallingConv() const { case attr::PreserveAll: case attr::M68kRTD: case attr::PreserveNone: + case attr::RISCVVectorCC: return true; } llvm_unreachable("invalid attr kind"); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 7032ff2f18468c2a23c6a2dd4fa9041cc0b0bf2b..0aa1d9327d7707fbe41095c6955bf3f01bc601d1 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -538,7 +538,7 @@ void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T, if (T->getSizeModifier() == ArraySizeModifier::Static) OS << "static "; - OS << T->getSize().getZExtValue() << ']'; + OS << T->getZExtSize() << ']'; printAfter(T->getElementType(), OS); } @@ -1071,6 +1071,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info, case CC_PreserveNone: OS << " __attribute__((preserve_none))"; break; + case CC_RISCVVectorCall: + OS << "__attribute__((riscv_vector_cc))"; + break; } } @@ -1960,6 +1963,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case attr::PreserveNone: OS << "preserve_none"; break; + case attr::RISCVVectorCC: + OS << "riscv_vector_cc"; + break; case attr::NoDeref: OS << "noderef"; break; @@ -2303,15 +2309,10 @@ printTo(raw_ostream &OS, ArrayRef Args, const PrintingPolicy &Policy, } else { if (!FirstArg) OS << Comma; - if (!Policy.SuppressTagKeyword && - Argument.getKind() == TemplateArgument::Type && - isa(Argument.getAsType())) - OS << Argument.getAsType().getAsString(); - else - // Tries to print the argument with location info if exists. - printArgument(Arg, Policy, ArgOS, - TemplateParameterList::shouldIncludeTypeForArgument( - Policy, TPL, ParmIndex)); + // Tries to print the argument with location info if exists. + printArgument(Arg, Policy, ArgOS, + TemplateParameterList::shouldIncludeTypeForArgument( + Policy, TPL, ParmIndex)); } StringRef ArgString = ArgOS.str(); diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index de70cbbf6cdb3801709cced4e36e2c1bd1859c8e..64e6155de090c5f3e0626968485ca104baa00f9e 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -2039,7 +2039,7 @@ void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { QualType QT = FI->getType(); // It may be a multidimensional array. while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { - if (AT->getSize() == 0) + if (AT->isZeroSize()) break; QT = AT->getElementType(); } @@ -2133,7 +2133,7 @@ bool CFGBuilder::hasTrivialDestructor(const VarDecl *VD) const { // Check for constant size array. Set type to array element type. while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { - if (AT->getSize() == 0) + if (AT->isZeroSize()) return true; QT = AT->getElementType(); } 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/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index cc1ebd511191a93d76a0528ee95ba6dd1907044c..70e0623805a8cfb46fb7c76237b4af9a5083a550 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -416,7 +416,7 @@ void Environment::initialize() { assert(Parent != nullptr); if (Parent->isLambda()) { - for (auto Capture : Parent->captures()) { + for (const auto &Capture : Parent->captures()) { if (Capture.capturesVariable()) { const auto *VarDecl = Capture.getCapturedVar(); assert(VarDecl != nullptr); 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/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e1ff0d92f6b2f87e39be002044d1d372c92e7af5..e03fe1b68300435f41c73ab9e44fdd7a33884a35 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -403,10 +403,11 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) { QualType Arg0Ty = Arg0->IgnoreImplicit()->getType(); if (Arg0Ty->isConstantArrayType()) { - const APInt &ConstArrSize = cast(Arg0Ty)->getSize(); + const APSInt ConstArrSize = + APSInt(cast(Arg0Ty)->getSize()); // Check form 4: - return Arg1CV && APSInt::compareValues(APSInt(ConstArrSize), *Arg1CV) == 0; + return Arg1CV && APSInt::compareValues(ConstArrSize, *Arg1CV) == 0; } return false; } @@ -429,14 +430,13 @@ AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) { BaseDRE->getDecl()->getType()); if (!CATy) return false; - const APInt ArrSize = CATy->getSize(); if (const auto *IdxLit = dyn_cast(Node.getIdx())) { const APInt ArrIdx = IdxLit->getValue(); // FIXME: ArrIdx.isNegative() we could immediately emit an error as that's a // bug if (ArrIdx.isNonNegative() && - ArrIdx.getLimitedValue() < ArrSize.getLimitedValue()) + ArrIdx.getLimitedValue() < CATy->getLimitedSize()) return true; } 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/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index a6d4af2b88111a4821b7292d3eacb3c1eafab6b5..f3d705e1551fe29fca69fcb610b9bc15d7ee3b24 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -467,3 +467,14 @@ ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const { } return Ret; } + +TargetInfo::CallingConvCheckResult +RISCVTargetInfo::checkCallingConvention(CallingConv CC) const { + switch (CC) { + default: + return CCCR_Warning; + case CC_C: + case CC_RISCVVectorCall: + return CCCR_OK; + } +} diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index bfbdafb682c851333d8371de12436f9dfaed278c..78580b5b1c1063cd5f39f44ca20dbafff121818a 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -110,6 +110,8 @@ public: bool hasBFloat16Type() const override { return true; } + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override; + bool useFP16ConversionIntrinsics() const override { return false; } diff --git a/clang/lib/CodeGen/ABIInfo.cpp b/clang/lib/CodeGen/ABIInfo.cpp index efcff958ce545223d11932243f1fd7d8a9f3e2e0..acaae9f8c3d8437c840012a438978ee09f3507a5 100644 --- a/clang/lib/CodeGen/ABIInfo.cpp +++ b/clang/lib/CodeGen/ABIInfo.cpp @@ -61,7 +61,7 @@ bool ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() const { bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base, uint64_t &Members) const { if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) { - uint64_t NElements = AT->getSize().getZExtValue(); + uint64_t NElements = AT->getZExtSize(); if (NElements == 0) return false; if (!isHomogeneousAggregate(AT->getElementType(), Base, Members)) @@ -98,7 +98,7 @@ bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base, QualType FT = FD->getType(); while (const ConstantArrayType *AT = getContext().getAsConstantArrayType(FT)) { - if (AT->getSize().getZExtValue() == 0) + if (AT->isZeroSize()) return false; FT = AT->getElementType(); } diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index 2b20d5a13346d3414430268ef53dc8e0dcbf8972..3e34d82cb399ba05f880cc7fd470cfac0af08a8d 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -187,7 +187,7 @@ CodeGen::emitVoidPtrDirectVAArg(CodeGenFunction &CGF, Address VAListAddr, CharUnits FullDirectSize = DirectSize.alignTo(SlotSize); Address NextPtr = CGF.Builder.CreateConstInBoundsByteGEP(Addr, FullDirectSize, "argp.next"); - CGF.Builder.CreateStore(NextPtr.getPointer(), VAListAddr); + CGF.Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr); // If the argument is smaller than a slot, and this is a big-endian // target, the argument will be right-adjusted in its slot. @@ -239,8 +239,8 @@ Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1, const llvm::Twine &Name) { assert(Addr1.getType() == Addr2.getType()); llvm::PHINode *PHI = CGF.Builder.CreatePHI(Addr1.getType(), 2, Name); - PHI->addIncoming(Addr1.getPointer(), Block1); - PHI->addIncoming(Addr2.getPointer(), Block2); + PHI->addIncoming(Addr1.emitRawPointer(CGF), Block1); + PHI->addIncoming(Addr2.emitRawPointer(CGF), Block2); CharUnits Align = std::min(Addr1.getAlignment(), Addr2.getAlignment()); return Address(PHI, Addr1.getElementType(), Align); } @@ -257,7 +257,7 @@ bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD, bool WasArray = false; if (AllowArrays) while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) { - if (AT->getSize() == 0) + if (AT->isZeroSize()) return true; FT = AT->getElementType(); // The [[no_unique_address]] special case below does not apply to @@ -352,7 +352,7 @@ const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) { // Treat single element arrays as the element. while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) { - if (AT->getSize().getZExtValue() != 1) + if (AT->getZExtSize() != 1) break; FT = AT->getElementType(); } @@ -400,7 +400,7 @@ Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, llvm::Type *ElementTy = CGF.ConvertTypeForMem(Ty); llvm::Type *BaseTy = llvm::PointerType::getUnqual(ElementTy); llvm::Value *Addr = - CGF.Builder.CreateVAArg(VAListAddr.getPointer(), BaseTy); + CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF), BaseTy); return Address(Addr, ElementTy, TyAlignForABI); } else { assert((AI.isDirect() || AI.isExtend()) && @@ -416,7 +416,7 @@ Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, "Unexpected CoerceToType seen in arginfo in generic VAArg emitter!"); Address Temp = CGF.CreateMemTemp(Ty, "varet"); - Val = CGF.Builder.CreateVAArg(VAListAddr.getPointer(), + Val = CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF), CGF.ConvertTypeForMem(Ty)); CGF.Builder.CreateStore(Val, Temp); return Temp; diff --git a/clang/lib/CodeGen/Address.h b/clang/lib/CodeGen/Address.h index cf48df8f5e7367e0c3737f837b83cd057dc07142..35ec370a139c92efc4686eac311947d74952a270 100644 --- a/clang/lib/CodeGen/Address.h +++ b/clang/lib/CodeGen/Address.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H #include "clang/AST/CharUnits.h" +#include "clang/AST/Type.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/IR/Constants.h" #include "llvm/Support/MathExtras.h" @@ -22,28 +23,41 @@ namespace clang { namespace CodeGen { +class Address; +class CGBuilderTy; +class CodeGenFunction; +class CodeGenModule; + // Indicates whether a pointer is known not to be null. enum KnownNonNull_t { NotKnownNonNull, KnownNonNull }; -/// An aligned address. -class Address { +/// An abstract representation of an aligned address. This is designed to be an +/// IR-level abstraction, carrying just the information necessary to perform IR +/// operations on an address like loads and stores. In particular, it doesn't +/// carry C type information or allow the representation of things like +/// bit-fields; clients working at that level should generally be using +/// `LValue`. +/// The pointer contained in this class is known to be unsigned. +class RawAddress { llvm::PointerIntPair PointerAndKnownNonNull; llvm::Type *ElementType; CharUnits Alignment; protected: - Address(std::nullptr_t) : ElementType(nullptr) {} + RawAddress(std::nullptr_t) : ElementType(nullptr) {} public: - Address(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment, - KnownNonNull_t IsKnownNonNull = NotKnownNonNull) + RawAddress(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) : PointerAndKnownNonNull(Pointer, IsKnownNonNull), ElementType(ElementType), Alignment(Alignment) { assert(Pointer != nullptr && "Pointer cannot be null"); assert(ElementType != nullptr && "Element type cannot be null"); } - static Address invalid() { return Address(nullptr); } + inline RawAddress(Address Addr); + + static RawAddress invalid() { return RawAddress(nullptr); } bool isValid() const { return PointerAndKnownNonNull.getPointer() != nullptr; } @@ -80,6 +94,133 @@ public: return Alignment; } + /// Return address with different element type, but same pointer and + /// alignment. + RawAddress withElementType(llvm::Type *ElemTy) const { + return RawAddress(getPointer(), ElemTy, getAlignment(), isKnownNonNull()); + } + + KnownNonNull_t isKnownNonNull() const { + assert(isValid()); + return (KnownNonNull_t)PointerAndKnownNonNull.getInt(); + } +}; + +/// Like RawAddress, an abstract representation of an aligned address, but the +/// pointer contained in this class is possibly signed. +class Address { + friend class CGBuilderTy; + + // The boolean flag indicates whether the pointer is known to be non-null. + llvm::PointerIntPair Pointer; + + /// The expected IR type of the pointer. Carrying accurate element type + /// information in Address makes it more convenient to work with Address + /// values and allows frontend assertions to catch simple mistakes. + llvm::Type *ElementType = nullptr; + + CharUnits Alignment; + + /// Offset from the base pointer. + llvm::Value *Offset = nullptr; + + llvm::Value *emitRawPointerSlow(CodeGenFunction &CGF) const; + +protected: + Address(std::nullptr_t) : ElementType(nullptr) {} + +public: + Address(llvm::Value *pointer, llvm::Type *elementType, CharUnits alignment, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) + : Pointer(pointer, IsKnownNonNull), ElementType(elementType), + Alignment(alignment) { + assert(pointer != nullptr && "Pointer cannot be null"); + assert(elementType != nullptr && "Element type cannot be null"); + assert(!alignment.isZero() && "Alignment cannot be zero"); + } + + Address(llvm::Value *BasePtr, llvm::Type *ElementType, CharUnits Alignment, + llvm::Value *Offset, KnownNonNull_t IsKnownNonNull = NotKnownNonNull) + : Pointer(BasePtr, IsKnownNonNull), ElementType(ElementType), + Alignment(Alignment), Offset(Offset) {} + + Address(RawAddress RawAddr) + : Pointer(RawAddr.isValid() ? RawAddr.getPointer() : nullptr), + ElementType(RawAddr.isValid() ? RawAddr.getElementType() : nullptr), + Alignment(RawAddr.isValid() ? RawAddr.getAlignment() + : CharUnits::Zero()) {} + + static Address invalid() { return Address(nullptr); } + bool isValid() const { return Pointer.getPointer() != nullptr; } + + /// This function is used in situations where the caller is doing some sort of + /// opaque "laundering" of the pointer. + void replaceBasePointer(llvm::Value *P) { + assert(isValid() && "pointer isn't valid"); + assert(P->getType() == Pointer.getPointer()->getType() && + "Pointer's type changed"); + Pointer.setPointer(P); + assert(isValid() && "pointer is invalid after replacement"); + } + + CharUnits getAlignment() const { return Alignment; } + + void setAlignment(CharUnits Value) { Alignment = Value; } + + llvm::Value *getBasePointer() const { + assert(isValid() && "pointer isn't valid"); + return Pointer.getPointer(); + } + + /// Return the type of the pointer value. + llvm::PointerType *getType() const { + return llvm::PointerType::get( + ElementType, + llvm::cast(Pointer.getPointer()->getType()) + ->getAddressSpace()); + } + + /// Return the type of the values stored in this address. + llvm::Type *getElementType() const { + assert(isValid()); + return ElementType; + } + + /// Return the address space that this address resides in. + unsigned getAddressSpace() const { return getType()->getAddressSpace(); } + + /// Return the IR name of the pointer value. + llvm::StringRef getName() const { return Pointer.getPointer()->getName(); } + + // This function is called only in CGBuilderBaseTy::CreateElementBitCast. + void setElementType(llvm::Type *Ty) { + assert(hasOffset() && + "this funcion shouldn't be called when there is no offset"); + ElementType = Ty; + } + + /// Whether the pointer is known not to be null. + KnownNonNull_t isKnownNonNull() const { + assert(isValid()); + return (KnownNonNull_t)Pointer.getInt(); + } + + Address setKnownNonNull() { + assert(isValid()); + Pointer.setInt(KnownNonNull); + return *this; + } + + bool hasOffset() const { return Offset; } + + llvm::Value *getOffset() const { return Offset; } + + /// Return the pointer contained in this class after authenticating it and + /// adding offset to it if necessary. + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { + return getBasePointer(); + } + /// Return address with different pointer, but same element type and /// alignment. Address withPointer(llvm::Value *NewPointer, @@ -91,61 +232,59 @@ public: /// Return address with different alignment, but same pointer and element /// type. Address withAlignment(CharUnits NewAlignment) const { - return Address(getPointer(), getElementType(), NewAlignment, + return Address(Pointer.getPointer(), getElementType(), NewAlignment, isKnownNonNull()); } /// Return address with different element type, but same pointer and /// alignment. Address withElementType(llvm::Type *ElemTy) const { - return Address(getPointer(), ElemTy, getAlignment(), isKnownNonNull()); - } - - /// Whether the pointer is known not to be null. - KnownNonNull_t isKnownNonNull() const { - assert(isValid()); - return (KnownNonNull_t)PointerAndKnownNonNull.getInt(); - } - - /// Set the non-null bit. - Address setKnownNonNull() { - assert(isValid()); - PointerAndKnownNonNull.setInt(true); - return *this; + if (!hasOffset()) + return Address(getBasePointer(), ElemTy, getAlignment(), nullptr, + isKnownNonNull()); + Address A(*this); + A.ElementType = ElemTy; + return A; } }; +inline RawAddress::RawAddress(Address Addr) + : PointerAndKnownNonNull(Addr.isValid() ? Addr.getBasePointer() : nullptr, + Addr.isValid() ? Addr.isKnownNonNull() + : NotKnownNonNull), + ElementType(Addr.isValid() ? Addr.getElementType() : nullptr), + Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {} + /// A specialization of Address that requires the address to be an /// LLVM Constant. -class ConstantAddress : public Address { - ConstantAddress(std::nullptr_t) : Address(nullptr) {} +class ConstantAddress : public RawAddress { + ConstantAddress(std::nullptr_t) : RawAddress(nullptr) {} public: ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType, CharUnits alignment) - : Address(pointer, elementType, alignment) {} + : RawAddress(pointer, elementType, alignment) {} static ConstantAddress invalid() { return ConstantAddress(nullptr); } llvm::Constant *getPointer() const { - return llvm::cast(Address::getPointer()); + return llvm::cast(RawAddress::getPointer()); } ConstantAddress withElementType(llvm::Type *ElemTy) const { return ConstantAddress(getPointer(), ElemTy, getAlignment()); } - static bool isaImpl(Address addr) { + static bool isaImpl(RawAddress addr) { return llvm::isa(addr.getPointer()); } - static ConstantAddress castImpl(Address addr) { + static ConstantAddress castImpl(RawAddress addr) { return ConstantAddress(llvm::cast(addr.getPointer()), addr.getElementType(), addr.getAlignment()); } }; - } // Present a minimal LLVM-like casting interface. diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index fb03d013e8afc7ba7c9e952eadabd44ae9e005a9..56198385de9dcbdec1a1990c22c5e5e80608b79e 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -80,7 +80,7 @@ namespace { AtomicSizeInBits = C.toBits( C.toCharUnitsFromBits(Offset + OrigBFI.Size + C.getCharWidth() - 1) .alignTo(lvalue.getAlignment())); - llvm::Value *BitFieldPtr = lvalue.getBitFieldPointer(); + llvm::Value *BitFieldPtr = lvalue.getRawBitFieldPointer(CGF); auto OffsetInChars = (C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.getAlignment()) * lvalue.getAlignment(); @@ -139,13 +139,13 @@ namespace { const LValue &getAtomicLValue() const { return LVal; } llvm::Value *getAtomicPointer() const { if (LVal.isSimple()) - return LVal.getPointer(CGF); + return LVal.emitRawPointer(CGF); else if (LVal.isBitField()) - return LVal.getBitFieldPointer(); + return LVal.getRawBitFieldPointer(CGF); else if (LVal.isVectorElt()) - return LVal.getVectorPointer(); + return LVal.getRawVectorPointer(CGF); assert(LVal.isExtVectorElt()); - return LVal.getExtVectorPointer(); + return LVal.getRawExtVectorPointer(CGF); } Address getAtomicAddress() const { llvm::Type *ElTy; @@ -368,7 +368,7 @@ bool AtomicInfo::emitMemSetZeroIfNecessary() const { return false; CGF.Builder.CreateMemSet( - addr.getPointer(), llvm::ConstantInt::get(CGF.Int8Ty, 0), + addr.emitRawPointer(CGF), llvm::ConstantInt::get(CGF.Int8Ty, 0), CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits).getQuantity(), LVal.getAlignment().getAsAlign()); return true; @@ -1055,7 +1055,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { return getTargetHooks().performAddrSpaceCast( *this, V, AS, LangAS::opencl_generic, DestType, false); }; - Args.add(RValue::get(CastToGenericAddrSpace(Ptr.getPointer(), + + Args.add(RValue::get(CastToGenericAddrSpace(Ptr.emitRawPointer(*this), E->getPtr()->getType())), getContext().VoidPtrTy); @@ -1086,10 +1087,10 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { LibCallName = "__atomic_compare_exchange"; RetTy = getContext().BoolTy; HaveRetTy = true; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), E->getVal1()->getType())), getContext().VoidPtrTy); - Args.add(RValue::get(CastToGenericAddrSpace(Val2.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val2.emitRawPointer(*this), E->getVal2()->getType())), getContext().VoidPtrTy); Args.add(RValue::get(Order), getContext().IntTy); @@ -1105,7 +1106,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__scoped_atomic_exchange: case AtomicExpr::AO__scoped_atomic_exchange_n: LibCallName = "__atomic_exchange"; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), E->getVal1()->getType())), getContext().VoidPtrTy); break; @@ -1120,7 +1121,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { LibCallName = "__atomic_store"; RetTy = getContext().VoidTy; HaveRetTy = true; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), E->getVal1()->getType())), getContext().VoidPtrTy); break; @@ -1199,7 +1200,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { if (!HaveRetTy) { // Value is returned through parameter before the order. RetTy = getContext().VoidTy; - Args.add(RValue::get(CastToGenericAddrSpace(Dest.getPointer(), RetTy)), + Args.add(RValue::get( + CastToGenericAddrSpace(Dest.emitRawPointer(*this), RetTy)), getContext().VoidPtrTy); } // Order is always the last parameter. @@ -1513,7 +1515,7 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc, } else TempAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(TempAddr.getPointer(), AO, IsVolatile); + EmitAtomicLoadLibcall(TempAddr.emitRawPointer(CGF), AO, IsVolatile); // Okay, turn that back into the original value or whole atomic (for // non-simple lvalues) type. @@ -1673,9 +1675,9 @@ std::pair AtomicInfo::EmitAtomicCompareExchange( if (shouldUseLibcall()) { // Produce a source address. Address ExpectedAddr = materializeRValue(Expected); - Address DesiredAddr = materializeRValue(Desired); - auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), + llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); + llvm::Value *DesiredPtr = materializeRValue(Desired).emitRawPointer(CGF); + auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, Success, Failure); return std::make_pair( convertAtomicTempToRValue(ExpectedAddr, AggValueSlot::ignored(), @@ -1757,7 +1759,7 @@ void AtomicInfo::EmitAtomicUpdateLibcall( Address ExpectedAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile); + EmitAtomicLoadLibcall(ExpectedAddr.emitRawPointer(CGF), AO, IsVolatile); auto *ContBB = CGF.createBasicBlock("atomic_cont"); auto *ExitBB = CGF.createBasicBlock("atomic_exit"); CGF.EmitBlock(ContBB); @@ -1771,10 +1773,10 @@ void AtomicInfo::EmitAtomicUpdateLibcall( AggValueSlot::ignored(), SourceLocation(), /*AsValue=*/false); EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, DesiredAddr); + llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); + llvm::Value *DesiredPtr = DesiredAddr.emitRawPointer(CGF); auto *Res = - EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), - AO, Failure); + EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure); CGF.Builder.CreateCondBr(Res, ExitBB, ContBB); CGF.EmitBlock(ExitBB, /*IsFinished=*/true); } @@ -1843,7 +1845,7 @@ void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, Address ExpectedAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile); + EmitAtomicLoadLibcall(ExpectedAddr.emitRawPointer(CGF), AO, IsVolatile); auto *ContBB = CGF.createBasicBlock("atomic_cont"); auto *ExitBB = CGF.createBasicBlock("atomic_exit"); CGF.EmitBlock(ContBB); @@ -1854,10 +1856,10 @@ void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, CGF.Builder.CreateStore(OldVal, DesiredAddr); } EmitAtomicUpdateValue(CGF, *this, UpdateRVal, DesiredAddr); + llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); + llvm::Value *DesiredPtr = DesiredAddr.emitRawPointer(CGF); auto *Res = - EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), - AO, Failure); + EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure); CGF.Builder.CreateCondBr(Res, ExitBB, ContBB); CGF.EmitBlock(ExitBB, /*IsFinished=*/true); } @@ -1957,7 +1959,8 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, args.add(RValue::get(atomics.getAtomicSizeValue()), getContext().getSizeType()); args.add(RValue::get(atomics.getAtomicPointer()), getContext().VoidPtrTy); - args.add(RValue::get(srcAddr.getPointer()), getContext().VoidPtrTy); + args.add(RValue::get(srcAddr.emitRawPointer(*this)), + getContext().VoidPtrTy); args.add( RValue::get(llvm::ConstantInt::get(IntTy, (int)llvm::toCABI(AO))), getContext().IntTy); diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index ad0b50d799618ed7ec7ecb581dd1bec84538a40c..a01f2c7c979840ca8be2cf10c6462633e70855bb 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -36,7 +36,8 @@ CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name) : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false), NoEscape(false), HasCXXObject(false), UsesStret(false), HasCapturedVariableLayout(false), CapturesNonExternalType(false), - LocalAddress(Address::invalid()), StructureType(nullptr), Block(block) { + LocalAddress(RawAddress::invalid()), StructureType(nullptr), + Block(block) { // Skip asm prefix, if any. 'name' is usually taken directly from // the mangled name of the enclosing function. @@ -794,7 +795,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { // Otherwise, we have to emit this as a local block. - Address blockAddr = blockInfo.LocalAddress; + RawAddress blockAddr = blockInfo.LocalAddress; assert(blockAddr.isValid() && "block has no address!"); llvm::Constant *isa; @@ -939,7 +940,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { if (CI.isNested()) byrefPointer = Builder.CreateLoad(src, "byref.capture"); else - byrefPointer = src.getPointer(); + byrefPointer = src.emitRawPointer(*this); // Write that void* into the capture field. Builder.CreateStore(byrefPointer, blockField); @@ -961,10 +962,10 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { } // If it's a reference variable, copy the reference into the block field. - } else if (type->isReferenceType()) { - Builder.CreateStore(src.getPointer(), blockField); + } else if (auto refType = type->getAs()) { + Builder.CreateStore(src.emitRawPointer(*this), blockField); - // If type is const-qualified, copy the value into the block field. + // If type is const-qualified, copy the value into the block field. } else if (type.isConstQualified() && type.getObjCLifetime() == Qualifiers::OCL_Strong && CGM.getCodeGenOpts().OptimizationLevel != 0) { @@ -1377,7 +1378,7 @@ void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D, // Allocate a stack slot like for any local variable to guarantee optimal // debug info at -O0. The mem2reg pass will eliminate it when optimizing. - Address alloc = CreateMemTemp(D->getType(), D->getName() + ".addr"); + RawAddress alloc = CreateMemTemp(D->getType(), D->getName() + ".addr"); Builder.CreateStore(arg, alloc); if (CGDebugInfo *DI = getDebugInfo()) { if (CGM.getCodeGenOpts().hasReducedDebugInfo()) { @@ -1497,7 +1498,7 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction( // frame setup instruction by llvm::DwarfDebug::beginFunction(). auto NL = ApplyDebugLocation::CreateEmpty(*this); Builder.CreateStore(BlockPointer, Alloca); - BlockPointerDbgLoc = Alloca.getPointer(); + BlockPointerDbgLoc = Alloca.emitRawPointer(*this); } // If we have a C++ 'this' reference, go ahead and force it into @@ -1557,8 +1558,8 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction( const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); if (capture.isConstant()) { auto addr = LocalDeclMap.find(variable)->second; - (void)DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(), - Builder); + (void)DI->EmitDeclareOfAutoVariable( + variable, addr.emitRawPointer(*this), Builder); continue; } @@ -1662,7 +1663,7 @@ struct CallBlockRelease final : EHScopeStack::Cleanup { if (LoadBlockVarAddr) { BlockVarAddr = CGF.Builder.CreateLoad(Addr); } else { - BlockVarAddr = Addr.getPointer(); + BlockVarAddr = Addr.emitRawPointer(CGF); } CGF.BuildBlockRelease(BlockVarAddr, FieldFlags, CanThrow); @@ -1962,13 +1963,15 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { // it. It's not quite worth the annoyance to avoid creating it in the // first place. if (!needsEHCleanup(captureType.isDestructedType())) - cast(dstField.getPointer())->eraseFromParent(); + if (auto *I = + cast_or_null(dstField.getBasePointer())) + I->eraseFromParent(); } break; } case BlockCaptureEntityKind::BlockObject: { llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); - llvm::Value *dstAddr = dstField.getPointer(); + llvm::Value *dstAddr = dstField.emitRawPointer(*this); llvm::Value *args[] = { dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask()) }; @@ -2139,7 +2142,7 @@ public: llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags); llvm::FunctionCallee fn = CGF.CGM.getBlockObjectAssign(); - llvm::Value *args[] = { destField.getPointer(), srcValue, flagsVal }; + llvm::Value *args[] = {destField.emitRawPointer(CGF), srcValue, flagsVal}; CGF.EmitNounwindRuntimeCall(fn, args); } @@ -2696,7 +2699,8 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { storeHeaderField(V, getPointerSize(), "byref.isa"); // Store the address of the variable into its own forwarding pointer. - storeHeaderField(addr.getPointer(), getPointerSize(), "byref.forwarding"); + storeHeaderField(addr.emitRawPointer(*this), getPointerSize(), + "byref.forwarding"); // Blocks ABI: // c) the flags field is set to either 0 if no helper functions are diff --git a/clang/lib/CodeGen/CGBlocks.h b/clang/lib/CodeGen/CGBlocks.h index 4ef1ae9f33655cb8b76fbf19af4557be46f140c4..8d10c4f69b2026b4c5d254eadc2d037e88058d36 100644 --- a/clang/lib/CodeGen/CGBlocks.h +++ b/clang/lib/CodeGen/CGBlocks.h @@ -271,7 +271,8 @@ public: /// The block's captures. Non-constant captures are sorted by their offsets. llvm::SmallVector SortedCaptures; - Address LocalAddress; + // Currently we assume that block-pointer types are never signed. + RawAddress LocalAddress; llvm::StructType *StructureType; const BlockDecl *Block; const BlockExpr *BlockExpression; diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index bf5ab171d720d9b148544ac6467652a5efea0edb..6dd9da7c4cadefb2063b5f55fdf3230476128c22 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -10,7 +10,9 @@ #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H #include "Address.h" +#include "CGValue.h" #include "CodeGenTypeCache.h" +#include "llvm/Analysis/Utils/Local.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Type.h" @@ -18,12 +20,15 @@ namespace clang { namespace CodeGen { +class CGBuilderTy; class CodeGenFunction; /// This is an IRBuilder insertion helper that forwards to /// CodeGenFunction::InsertHelper, which adds necessary metadata to /// instructions. class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter { + friend CGBuilderTy; + public: CGBuilderInserter() = default; explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {} @@ -43,10 +48,42 @@ typedef llvm::IRBuilder CGBuilderBaseTy; class CGBuilderTy : public CGBuilderBaseTy { + friend class Address; + /// Storing a reference to the type cache here makes it a lot easier /// to build natural-feeling, target-specific IR. const CodeGenTypeCache &TypeCache; + CodeGenFunction *getCGF() const { return getInserter().CGF; } + + llvm::Value *emitRawPointerFromAddress(Address Addr) const { + return Addr.getBasePointer(); + } + + template + Address createConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, + const llvm::Twine &Name) { + const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + llvm::GetElementPtrInst *GEP; + if (IsInBounds) + GEP = cast(CreateConstInBoundsGEP2_32( + Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1, + Name)); + else + GEP = cast(CreateConstGEP2_32( + Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1, + Name)); + llvm::APInt Offset( + DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, + /*isSigned=*/true); + if (!GEP->accumulateConstantOffset(DL, Offset)) + llvm_unreachable("offset of GEP with constants is always computable"); + return Address(GEP, GEP->getResultElementType(), + Addr.getAlignment().alignmentAtOffset( + CharUnits::fromQuantity(Offset.getSExtValue())), + IsInBounds ? Addr.isKnownNonNull() : NotKnownNonNull); + } + public: CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C) : CGBuilderBaseTy(C), TypeCache(TypeCache) {} @@ -69,20 +106,22 @@ public: // Note that we intentionally hide the CreateLoad APIs that don't // take an alignment. llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") { - return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), + return CreateAlignedLoad(Addr.getElementType(), + emitRawPointerFromAddress(Addr), Addr.getAlignment().getAsAlign(), Name); } llvm::LoadInst *CreateLoad(Address Addr, const char *Name) { // This overload is required to prevent string literals from // ending up in the IsVolatile overload. - return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), + return CreateAlignedLoad(Addr.getElementType(), + emitRawPointerFromAddress(Addr), Addr.getAlignment().getAsAlign(), Name); } llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile, const llvm::Twine &Name = "") { - return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), - Addr.getAlignment().getAsAlign(), IsVolatile, - Name); + return CreateAlignedLoad( + Addr.getElementType(), emitRawPointerFromAddress(Addr), + Addr.getAlignment().getAsAlign(), IsVolatile, Name); } using CGBuilderBaseTy::CreateAlignedLoad; @@ -96,7 +135,7 @@ public: // take an alignment. llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile = false) { - return CreateAlignedStore(Val, Addr.getPointer(), + return CreateAlignedStore(Val, emitRawPointerFromAddress(Addr), Addr.getAlignment().getAsAlign(), IsVolatile); } @@ -132,33 +171,41 @@ public: llvm::AtomicOrdering FailureOrdering, llvm::SyncScope::ID SSID = llvm::SyncScope::System) { return CGBuilderBaseTy::CreateAtomicCmpXchg( - Addr.getPointer(), Cmp, New, Addr.getAlignment().getAsAlign(), - SuccessOrdering, FailureOrdering, SSID); + Addr.emitRawPointer(*getCGF()), Cmp, New, + Addr.getAlignment().getAsAlign(), SuccessOrdering, FailureOrdering, + SSID); } llvm::AtomicRMWInst * CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Ordering, llvm::SyncScope::ID SSID = llvm::SyncScope::System) { - return CGBuilderBaseTy::CreateAtomicRMW(Op, Addr.getPointer(), Val, - Addr.getAlignment().getAsAlign(), - Ordering, SSID); + return CGBuilderBaseTy::CreateAtomicRMW( + Op, Addr.emitRawPointer(*getCGF()), Val, + Addr.getAlignment().getAsAlign(), Ordering, SSID); } using CGBuilderBaseTy::CreateAddrSpaceCast; Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, + llvm::Type *ElementTy, const llvm::Twine &Name = "") { - return Addr.withPointer(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name), - Addr.isKnownNonNull()); + if (!Addr.hasOffset()) + return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name), + ElementTy, Addr.getAlignment(), nullptr, + Addr.isKnownNonNull()); + // Eagerly force a raw address if these is an offset. + return RawAddress( + CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name), + ElementTy, Addr.getAlignment(), Addr.isKnownNonNull()); } using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name = "") { - llvm::Value *Ptr = - CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name); - return Address(Ptr, ElementTy, Addr.getAlignment(), Addr.isKnownNonNull()); + if (Addr.getType()->getAddressSpace() == Ty->getPointerAddressSpace()) + return Addr.withElementType(ElementTy); + return CreateAddrSpaceCast(Addr, Ty, ElementTy, Name); } /// Given @@ -176,10 +223,11 @@ public: const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - return Address( - CreateStructGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), - ElTy->getElementType(Index), - Addr.getAlignment().alignmentAtOffset(Offset), Addr.isKnownNonNull()); + return Address(CreateStructGEP(Addr.getElementType(), Addr.getBasePointer(), + Index, Name), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset), + Addr.isKnownNonNull()); } /// Given @@ -198,7 +246,7 @@ public: CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType())); return Address( - CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), + CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), {getSize(CharUnits::Zero()), getSize(Index)}, Name), ElTy->getElementType(), Addr.getAlignment().alignmentAtOffset(Index * EltSize), @@ -216,10 +264,10 @@ public: const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), - getSize(Index), Name), - ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), - Addr.isKnownNonNull()); + return Address( + CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), + ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), + Addr.isKnownNonNull()); } /// Given @@ -229,110 +277,133 @@ public: /// where i64 is actually the target word size. Address CreateConstGEP(Address Addr, uint64_t Index, const llvm::Twine &Name = "") { + llvm::Type *ElTy = Addr.getElementType(); const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); - CharUnits EltSize = - CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); + CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), - getSize(Index), Name), + return Address(CreateGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Index * EltSize), - NotKnownNonNull); + Addr.getAlignment().alignmentAtOffset(Index * EltSize)); } /// Create GEP with single dynamic index. The address alignment is reduced /// according to the element size. using CGBuilderBaseTy::CreateGEP; - Address CreateGEP(Address Addr, llvm::Value *Index, + Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name = "") { const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); return Address( - CreateGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), + CreateGEP(Addr.getElementType(), Addr.emitRawPointer(CGF), Index, Name), Addr.getElementType(), - Addr.getAlignment().alignmentOfArrayElement(EltSize), NotKnownNonNull); + Addr.getAlignment().alignmentOfArrayElement(EltSize)); } /// Given a pointer to i8, adjust it by a given constant offset. Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), - getSize(Offset), Name), - Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Offset), - Addr.isKnownNonNull()); + return Address( + CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), + getSize(Offset), Name), + Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset), + Addr.isKnownNonNull()); } + Address CreateConstByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), + return Address(CreateGEP(Addr.getElementType(), Addr.getBasePointer(), getSize(Offset), Name), Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Offset), - NotKnownNonNull); + Addr.getAlignment().alignmentAtOffset(Offset)); } using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, const llvm::Twine &Name = "") { - const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + return createConstGEP2_32(Addr, Idx0, Idx1, Name); + } - auto *GEP = cast(CreateConstInBoundsGEP2_32( - Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name)); - llvm::APInt Offset( - DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, - /*isSigned=*/true); - if (!GEP->accumulateConstantOffset(DL, Offset)) - llvm_unreachable("offset of GEP with constants is always computable"); - return Address(GEP, GEP->getResultElementType(), - Addr.getAlignment().alignmentAtOffset( - CharUnits::fromQuantity(Offset.getSExtValue())), - Addr.isKnownNonNull()); + using CGBuilderBaseTy::CreateConstGEP2_32; + Address CreateConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, + const llvm::Twine &Name = "") { + return createConstGEP2_32(Addr, Idx0, Idx1, Name); + } + + Address CreateGEP(Address Addr, ArrayRef IdxList, + llvm::Type *ElementType, CharUnits Align, + const Twine &Name = "") { + llvm::Value *Ptr = emitRawPointerFromAddress(Addr); + return RawAddress(CreateGEP(Addr.getElementType(), Ptr, IdxList, Name), + ElementType, Align); + } + + using CGBuilderBaseTy::CreateInBoundsGEP; + Address CreateInBoundsGEP(Address Addr, ArrayRef IdxList, + llvm::Type *ElementType, CharUnits Align, + const Twine &Name = "") { + return RawAddress(CreateInBoundsGEP(Addr.getElementType(), + emitRawPointerFromAddress(Addr), + IdxList, Name), + ElementType, Align, Addr.isKnownNonNull()); + } + + using CGBuilderBaseTy::CreateIsNull; + llvm::Value *CreateIsNull(Address Addr, const Twine &Name = "") { + if (!Addr.hasOffset()) + return CreateIsNull(Addr.getBasePointer(), Name); + // The pointer isn't null if Addr has an offset since offsets can always + // be applied inbound. + return llvm::ConstantInt::getFalse(Context); } using CGBuilderBaseTy::CreateMemCpy; llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile = false) { - return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), - Src.getPointer(), Src.getAlignment().getAsAlign(), Size, - IsVolatile); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), Size, IsVolatile); } llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, bool IsVolatile = false) { - return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), - Src.getPointer(), Src.getAlignment().getAsAlign(), Size, - IsVolatile); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), Size, IsVolatile); } using CGBuilderBaseTy::CreateMemCpyInline; llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) { - return CreateMemCpyInline( - Dest.getPointer(), Dest.getAlignment().getAsAlign(), Src.getPointer(), - Src.getAlignment().getAsAlign(), getInt64(Size)); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemCpyInline(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), getInt64(Size)); } using CGBuilderBaseTy::CreateMemMove; llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile = false) { - return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(), - Src.getPointer(), Src.getAlignment().getAsAlign(), - Size, IsVolatile); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemMove(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), Size, IsVolatile); } using CGBuilderBaseTy::CreateMemSet; llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, llvm::Value *Size, bool IsVolatile = false) { - return CreateMemSet(Dest.getPointer(), Value, Size, + return CreateMemSet(emitRawPointerFromAddress(Dest), Value, Size, Dest.getAlignment().getAsAlign(), IsVolatile); } using CGBuilderBaseTy::CreateMemSetInline; llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value, uint64_t Size) { - return CreateMemSetInline(Dest.getPointer(), + return CreateMemSetInline(emitRawPointerFromAddress(Dest), Dest.getAlignment().getAsAlign(), Value, getInt64(Size)); } @@ -346,16 +417,31 @@ public: const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(), - Index, FieldIndex, DbgInfo), - ElTy->getElementType(Index), - Addr.getAlignment().alignmentAtOffset(Offset)); + return Address( + CreatePreserveStructAccessIndex(ElTy, emitRawPointerFromAddress(Addr), + Index, FieldIndex, DbgInfo), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset)); + } + + using CGBuilderBaseTy::CreatePreserveUnionAccessIndex; + Address CreatePreserveUnionAccessIndex(Address Addr, unsigned FieldIndex, + llvm::MDNode *DbgInfo) { + Addr.replaceBasePointer(CreatePreserveUnionAccessIndex( + Addr.getBasePointer(), FieldIndex, DbgInfo)); + return Addr; } using CGBuilderBaseTy::CreateLaunderInvariantGroup; Address CreateLaunderInvariantGroup(Address Addr) { - return Addr.withPointer(CreateLaunderInvariantGroup(Addr.getPointer()), - Addr.isKnownNonNull()); + Addr.replaceBasePointer(CreateLaunderInvariantGroup(Addr.getBasePointer())); + return Addr; + } + + using CGBuilderBaseTy::CreateStripInvariantGroup; + Address CreateStripInvariantGroup(Address Addr) { + Addr.replaceBasePointer(CreateStripInvariantGroup(Addr.getBasePointer())); + return Addr; } }; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index e14e890882821853378fd7e814bb3bdb1093ecc2..5ab5917c0c8da7c7fd5de9506afc046cc98df486 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -792,7 +792,8 @@ EncompassingIntegerType(ArrayRef Types) { Value *CodeGenFunction::EmitVAStartEnd(Value *ArgValue, bool IsStart) { Intrinsic::ID inst = IsStart ? Intrinsic::vastart : Intrinsic::vaend; - return Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue); + return Builder.CreateCall(CGM.getIntrinsic(inst, {ArgValue->getType()}), + ArgValue); } /// Checks if using the result of __builtin_object_size(p, @p From) in place of @@ -2116,9 +2117,9 @@ llvm::Function *CodeGenFunction::generateBuiltinOSLogHelperFunction( auto AL = ApplyDebugLocation::CreateArtificial(*this); CharUnits Offset; - Address BufAddr = - Address(Builder.CreateLoad(GetAddrOfLocalVar(Args[0]), "buf"), Int8Ty, - BufferAlignment); + Address BufAddr = makeNaturalAddressForPointer( + Builder.CreateLoad(GetAddrOfLocalVar(Args[0]), "buf"), Ctx.VoidTy, + BufferAlignment); Builder.CreateStore(Builder.getInt8(Layout.getSummaryByte()), Builder.CreateConstByteGEP(BufAddr, Offset++, "summary")); Builder.CreateStore(Builder.getInt8(Layout.getNumArgsByte()), @@ -2161,7 +2162,7 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { // Ignore argument 1, the format string. It is not currently used. CallArgList Args; - Args.add(RValue::get(BufAddr.getPointer()), Ctx.VoidPtrTy); + Args.add(RValue::get(BufAddr.emitRawPointer(*this)), Ctx.VoidPtrTy); for (const auto &Item : Layout.Items) { int Size = Item.getSizeByte(); @@ -2201,8 +2202,8 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { if (!isa(ArgVal)) { CleanupKind Cleanup = getARCCleanupKind(); QualType Ty = TheExpr->getType(); - Address Alloca = Address::invalid(); - Address Addr = CreateMemTemp(Ty, "os.log.arg", &Alloca); + RawAddress Alloca = RawAddress::invalid(); + RawAddress Addr = CreateMemTemp(Ty, "os.log.arg", &Alloca); ArgVal = EmitARCRetain(Ty, ArgVal); Builder.CreateStore(ArgVal, Addr); pushLifetimeExtendedDestroy(Cleanup, Alloca, Ty, @@ -2235,7 +2236,7 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { llvm::Function *F = CodeGenFunction(CGM).generateBuiltinOSLogHelperFunction( Layout, BufAddr.getAlignment()); EmitCall(FI, CGCallee::forDirect(F), ReturnValueSlot(), Args); - return RValue::get(BufAddr.getPointer()); + return RValue::get(BufAddr, *this); } static bool isSpecialUnsignedMultiplySignedResult( @@ -2983,7 +2984,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Check NonnullAttribute/NullabilityArg and Alignment. auto EmitArgCheck = [&](TypeCheckKind Kind, Address A, const Expr *Arg, unsigned ParmNum) { - Value *Val = A.getPointer(); + Value *Val = A.emitRawPointer(*this); EmitNonNullArgCheck(RValue::get(Val), Arg->getType(), Arg->getExprLoc(), FD, ParmNum); @@ -3012,13 +3013,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_va_end: EmitVAStartEnd(BuiltinID == Builtin::BI__va_start ? EmitScalarExpr(E->getArg(0)) - : EmitVAListRef(E->getArg(0)).getPointer(), + : EmitVAListRef(E->getArg(0)).emitRawPointer(*this), BuiltinID != Builtin::BI__builtin_va_end); return RValue::get(nullptr); case Builtin::BI__builtin_va_copy: { - Value *DstPtr = EmitVAListRef(E->getArg(0)).getPointer(); - Value *SrcPtr = EmitVAListRef(E->getArg(1)).getPointer(); - Builder.CreateCall(CGM.getIntrinsic(Intrinsic::vacopy), {DstPtr, SrcPtr}); + Value *DstPtr = EmitVAListRef(E->getArg(0)).emitRawPointer(*this); + Value *SrcPtr = EmitVAListRef(E->getArg(1)).emitRawPointer(*this); + Builder.CreateCall(CGM.getIntrinsic(Intrinsic::vacopy, {DstPtr->getType()}), + {DstPtr, SrcPtr}); return RValue::get(nullptr); } case Builtin::BIabs: @@ -3847,13 +3849,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, bool IsVolatile = PtrTy->getPointeeType().isVolatileQualified(); Address Src = EmitPointerWithAlignment(E->getArg(0)); - EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Src.emitRawPointer(*this)), + E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, + 0); Value *Result = MB.CreateColumnMajorLoad( - Src.getElementType(), Src.getPointer(), + Src.getElementType(), Src.emitRawPointer(*this), Align(Src.getAlignment().getQuantity()), Stride, IsVolatile, - ResultTy->getNumRows(), ResultTy->getNumColumns(), - "matrix"); + ResultTy->getNumRows(), ResultTy->getNumColumns(), "matrix"); return RValue::get(Result); } @@ -3868,11 +3870,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, assert(PtrTy && "arg1 must be of pointer type"); bool IsVolatile = PtrTy->getPointeeType().isVolatileQualified(); - EmitNonNullArgCheck(RValue::get(Dst.getPointer()), E->getArg(1)->getType(), - E->getArg(1)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Dst.emitRawPointer(*this)), + E->getArg(1)->getType(), E->getArg(1)->getExprLoc(), FD, + 0); Value *Result = MB.CreateColumnMajorStore( - Matrix, Dst.getPointer(), Align(Dst.getAlignment().getQuantity()), - Stride, IsVolatile, MatrixTy->getNumRows(), MatrixTy->getNumColumns()); + Matrix, Dst.emitRawPointer(*this), + Align(Dst.getAlignment().getQuantity()), Stride, IsVolatile, + MatrixTy->getNumRows(), MatrixTy->getNumColumns()); return RValue::get(Result); } @@ -4031,7 +4035,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_bzero: { Address Dest = EmitPointerWithAlignment(E->getArg(0)); Value *SizeVal = EmitScalarExpr(E->getArg(1)); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), + EmitNonNullArgCheck(Dest, E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, 0); Builder.CreateMemSet(Dest, Builder.getInt8(0), SizeVal, false); return RValue::get(nullptr); @@ -4042,10 +4046,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(0)); Address Dest = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = EmitScalarExpr(E->getArg(2)); - EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(1)->getType(), - E->getArg(1)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Src.emitRawPointer(*this)), + E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, + 0); + EmitNonNullArgCheck(RValue::get(Dest.emitRawPointer(*this)), + E->getArg(1)->getType(), E->getArg(1)->getExprLoc(), FD, + 0); Builder.CreateMemMove(Dest, Src, SizeVal, false); return RValue::get(nullptr); } @@ -4062,10 +4068,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.CreateMemCpy(Dest, Src, SizeVal, false); if (BuiltinID == Builtin::BImempcpy || BuiltinID == Builtin::BI__builtin_mempcpy) - return RValue::get(Builder.CreateInBoundsGEP(Dest.getElementType(), - Dest.getPointer(), SizeVal)); + return RValue::get(Builder.CreateInBoundsGEP( + Dest.getElementType(), Dest.emitRawPointer(*this), SizeVal)); else - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_memcpy_inline: { @@ -4097,7 +4103,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemCpy(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_objc_memmove_collectable: { @@ -4106,7 +4112,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Value *SizeVal = EmitScalarExpr(E->getArg(2)); CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestAddr, SrcAddr, SizeVal); - return RValue::get(DestAddr.getPointer()); + return RValue::get(DestAddr, *this); } case Builtin::BI__builtin___memmove_chk: { @@ -4123,7 +4129,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemMove(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BImemmove: @@ -4134,7 +4140,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, EmitArgCheck(TCK_Store, Dest, E->getArg(0), 0); EmitArgCheck(TCK_Load, Src, E->getArg(1), 1); Builder.CreateMemMove(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BImemset: case Builtin::BI__builtin_memset: { @@ -4142,10 +4148,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), Builder.getInt8Ty()); Value *SizeVal = EmitScalarExpr(E->getArg(2)); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), + EmitNonNullArgCheck(Dest, E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, 0); Builder.CreateMemSet(Dest, ByteVal, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_memset_inline: { Address Dest = EmitPointerWithAlignment(E->getArg(0)); @@ -4153,8 +4159,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), Builder.getInt8Ty()); uint64_t Size = E->getArg(2)->EvaluateKnownConstInt(getContext()).getZExtValue(); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Dest.emitRawPointer(*this)), + E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, + 0); Builder.CreateMemSetInline(Dest, ByteVal, Size); return RValue::get(nullptr); } @@ -4173,7 +4180,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.getInt8Ty()); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemSet(Dest, ByteVal, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_wmemchr: { // The MSVC runtime library does not provide a definition of wmemchr, so we @@ -4395,14 +4402,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Store the stack pointer to the setjmp buffer. Value *StackAddr = Builder.CreateStackSave(); - assert(Buf.getPointer()->getType() == StackAddr->getType()); + assert(Buf.emitRawPointer(*this)->getType() == StackAddr->getType()); Address StackSaveSlot = Builder.CreateConstInBoundsGEP(Buf, 2); Builder.CreateStore(StackAddr, StackSaveSlot); // Call LLVM's EH setjmp, which is lightweight. Function *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp); - return RValue::get(Builder.CreateCall(F, Buf.getPointer())); + return RValue::get(Builder.CreateCall(F, Buf.emitRawPointer(*this))); } case Builtin::BI__builtin_longjmp: { Value *Buf = EmitScalarExpr(E->getArg(0)); @@ -5575,7 +5582,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::Value *Queue = EmitScalarExpr(E->getArg(0)); llvm::Value *Flags = EmitScalarExpr(E->getArg(1)); LValue NDRangeL = EmitAggExprToLValue(E->getArg(2)); - llvm::Value *Range = NDRangeL.getAddress(*this).getPointer(); + llvm::Value *Range = NDRangeL.getAddress(*this).emitRawPointer(*this); llvm::Type *RangeTy = NDRangeL.getAddress(*this).getType(); if (NumArgs == 4) { @@ -5684,9 +5691,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, getContext(), Expr::NPC_ValueDependentIsNotNull)) { EventWaitList = llvm::ConstantPointerNull::get(PtrTy); } else { - EventWaitList = E->getArg(4)->getType()->isArrayType() - ? EmitArrayToPointerDecay(E->getArg(4)).getPointer() - : EmitScalarExpr(E->getArg(4)); + EventWaitList = + E->getArg(4)->getType()->isArrayType() + ? EmitArrayToPointerDecay(E->getArg(4)).emitRawPointer(*this) + : EmitScalarExpr(E->getArg(4)); // Convert to generic address space. EventWaitList = Builder.CreatePointerCast(EventWaitList, PtrTy); } @@ -5782,7 +5790,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::Type *GenericVoidPtrTy = Builder.getPtrTy( getContext().getTargetAddressSpace(LangAS::opencl_generic)); LValue NDRangeL = EmitAggExprToLValue(E->getArg(0)); - llvm::Value *NDRange = NDRangeL.getAddress(*this).getPointer(); + llvm::Value *NDRange = NDRangeL.getAddress(*this).emitRawPointer(*this); auto Info = CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(1)); Value *Kernel = @@ -5867,7 +5875,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, auto PTy0 = FTy->getParamType(0); if (PTy0 != Arg0Val->getType()) { if (Arg0Ty->isArrayType()) - Arg0Val = EmitArrayToPointerDecay(Arg0).getPointer(); + Arg0Val = EmitArrayToPointerDecay(Arg0).emitRawPointer(*this); else Arg0Val = Builder.CreatePointerCast(Arg0Val, PTy0); } @@ -5905,7 +5913,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, auto PTy1 = FTy->getParamType(1); if (PTy1 != Arg1Val->getType()) { if (Arg1Ty->isArrayType()) - Arg1Val = EmitArrayToPointerDecay(Arg1).getPointer(); + Arg1Val = EmitArrayToPointerDecay(Arg1).emitRawPointer(*this); else Arg1Val = Builder.CreatePointerCast(Arg1Val, PTy1); } @@ -5919,7 +5927,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_ms_va_start: case Builtin::BI__builtin_ms_va_end: return RValue::get( - EmitVAStartEnd(EmitMSVAListRef(E->getArg(0)).getPointer(), + EmitVAStartEnd(EmitMSVAListRef(E->getArg(0)).emitRawPointer(*this), BuiltinID == Builtin::BI__builtin_ms_va_start)); case Builtin::BI__builtin_ms_va_copy: { @@ -5961,8 +5969,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // If this is a predefined lib function (e.g. malloc), emit the call // using exactly the normal call path. if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return emitLibraryCall(*this, FD, E, - cast(EmitScalarExpr(E->getCallee()))); + return emitLibraryCall( + *this, FD, E, cast(EmitScalarExpr(E->getCallee()))); // Check that a call to a target specific builtin has the correct target // features. @@ -6079,7 +6087,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(nullptr); return RValue::get(V); case TEK_Aggregate: - return RValue::getAggregate(ReturnValue.getValue(), + return RValue::getAggregate(ReturnValue.getAddress(), ReturnValue.isVolatile()); case TEK_Complex: llvm_unreachable("No current target builtin returns complex"); @@ -8849,7 +8857,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp0 = EmitPointerWithAlignment(E->getArg(0)); - Ops.push_back(PtrOp0.getPointer()); + Ops.push_back(PtrOp0.emitRawPointer(*this)); continue; } } @@ -8876,7 +8884,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp1 = EmitPointerWithAlignment(E->getArg(1)); - Ops.push_back(PtrOp1.getPointer()); + Ops.push_back(PtrOp1.emitRawPointer(*this)); continue; } } @@ -9297,7 +9305,7 @@ Value *CodeGenFunction::EmitARMMVEBuiltinExpr(unsigned BuiltinID, if (ReturnValue.isNull()) return MvecOut; else - return Builder.CreateStore(MvecOut, ReturnValue.getValue()); + return Builder.CreateStore(MvecOut, ReturnValue.getAddress()); } case CustomCodeGen::VST24: { @@ -11477,7 +11485,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp0 = EmitPointerWithAlignment(E->getArg(0)); - Ops.push_back(PtrOp0.getPointer()); + Ops.push_back(PtrOp0.emitRawPointer(*this)); continue; } } @@ -13343,15 +13351,15 @@ Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID, if (!getDebugInfo()) { CGM.Error(E->getExprLoc(), "using __builtin_preserve_field_info() without -g"); - return IsBitField ? EmitLValue(Arg).getBitFieldPointer() - : EmitLValue(Arg).getPointer(*this); + return IsBitField ? EmitLValue(Arg).getRawBitFieldPointer(*this) + : EmitLValue(Arg).emitRawPointer(*this); } // Enable underlying preserve_*_access_index() generation. bool OldIsInPreservedAIRegion = IsInPreservedAIRegion; IsInPreservedAIRegion = true; - Value *FieldAddr = IsBitField ? EmitLValue(Arg).getBitFieldPointer() - : EmitLValue(Arg).getPointer(*this); + Value *FieldAddr = IsBitField ? EmitLValue(Arg).getRawBitFieldPointer(*this) + : EmitLValue(Arg).emitRawPointer(*this); IsInPreservedAIRegion = OldIsInPreservedAIRegion; ConstantInt *C = cast(EmitScalarExpr(E->getArg(1))); @@ -14343,14 +14351,14 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, } case X86::BI_mm_setcsr: case X86::BI__builtin_ia32_ldmxcsr: { - Address Tmp = CreateMemTemp(E->getArg(0)->getType()); + RawAddress Tmp = CreateMemTemp(E->getArg(0)->getType()); Builder.CreateStore(Ops[0], Tmp); return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr), Tmp.getPointer()); } case X86::BI_mm_getcsr: case X86::BI__builtin_ia32_stmxcsr: { - Address Tmp = CreateMemTemp(E->getType()); + RawAddress Tmp = CreateMemTemp(E->getType()); Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr), Tmp.getPointer()); return Builder.CreateLoad(Tmp, "stmxcsr"); @@ -17625,7 +17633,8 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, SmallVector Ops; for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) if (E->getArg(i)->getType()->isArrayType()) - Ops.push_back(EmitArrayToPointerDecay(E->getArg(i)).getPointer()); + Ops.push_back( + EmitArrayToPointerDecay(E->getArg(i)).emitRawPointer(*this)); else Ops.push_back(EmitScalarExpr(E->getArg(i))); // The first argument of these two builtins is a pointer used to store their @@ -18066,15 +18075,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 +18144,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 +18153,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,43 +18547,25 @@ 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_v4i16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8i16: { - llvm::Type *ArgTy; + Intrinsic::ID IID; switch (BuiltinID) { - case AMDGPU::BI__builtin_amdgcn_global_load_tr_i32: - ArgTy = llvm::Type::getInt32Ty(getLLVMContext()); - break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v2i32: - ArgTy = llvm::FixedVectorType::get( - llvm::Type::getInt32Ty(getLLVMContext()), 2); - break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4f16: - ArgTy = llvm::FixedVectorType::get( - llvm::Type::getHalfTy(getLLVMContext()), 4); - break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4i16: - ArgTy = llvm::FixedVectorType::get( - llvm::Type::getInt16Ty(getLLVMContext()), 4); + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_i32: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_v2i32: + IID = Intrinsic::amdgcn_global_load_tr_b64; break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8f16: - ArgTy = llvm::FixedVectorType::get( - llvm::Type::getHalfTy(getLLVMContext()), 8); - break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8i16: - ArgTy = llvm::FixedVectorType::get( - llvm::Type::getInt16Ty(getLLVMContext()), 8); + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4i16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8i16: + IID = Intrinsic::amdgcn_global_load_tr_b128; break; } - + llvm::Type *LoadTy = ConvertType(E->getType()); llvm::Value *Addr = EmitScalarExpr(E->getArg(0)); - llvm::Function *F = - CGM.getIntrinsic(Intrinsic::amdgcn_global_load_tr, {ArgTy}); + llvm::Function *F = CGM.getIntrinsic(IID, {LoadTy}); return Builder.CreateCall(F, {Addr}); } case AMDGPU::BI__builtin_amdgcn_get_fpenv: { @@ -20098,14 +20096,14 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, // Save returned values. assert(II.NumResults); if (II.NumResults == 1) { - Builder.CreateAlignedStore(Result, Dst.getPointer(), + Builder.CreateAlignedStore(Result, Dst.emitRawPointer(*this), CharUnits::fromQuantity(4)); } else { for (unsigned i = 0; i < II.NumResults; ++i) { Builder.CreateAlignedStore( Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), Dst.getElementType()), - Builder.CreateGEP(Dst.getElementType(), Dst.getPointer(), + Builder.CreateGEP(Dst.getElementType(), Dst.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); } @@ -20145,7 +20143,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < II.NumResults; ++i) { Value *V = Builder.CreateAlignedLoad( Src.getElementType(), - Builder.CreateGEP(Src.getElementType(), Src.getPointer(), + Builder.CreateGEP(Src.getElementType(), Src.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, ParamType)); @@ -20217,7 +20215,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsA; ++i) { Value *V = Builder.CreateAlignedLoad( SrcA.getElementType(), - Builder.CreateGEP(SrcA.getElementType(), SrcA.getPointer(), + Builder.CreateGEP(SrcA.getElementType(), SrcA.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, AType)); @@ -20227,7 +20225,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsB; ++i) { Value *V = Builder.CreateAlignedLoad( SrcB.getElementType(), - Builder.CreateGEP(SrcB.getElementType(), SrcB.getPointer(), + Builder.CreateGEP(SrcB.getElementType(), SrcB.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, BType)); @@ -20238,7 +20236,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsC; ++i) { Value *V = Builder.CreateAlignedLoad( SrcC.getElementType(), - Builder.CreateGEP(SrcC.getElementType(), SrcC.getPointer(), + Builder.CreateGEP(SrcC.getElementType(), SrcC.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, CType)); @@ -20248,7 +20246,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsD; ++i) Builder.CreateAlignedStore( Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), DType), - Builder.CreateGEP(Dst.getElementType(), Dst.getPointer(), + Builder.CreateGEP(Dst.getElementType(), Dst.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); return Result; @@ -20506,7 +20504,7 @@ struct BuiltinAlignArgs { BuiltinAlignArgs(const CallExpr *E, CodeGenFunction &CGF) { QualType AstType = E->getArg(0)->getType(); if (AstType->isArrayType()) - Src = CGF.EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Src = CGF.EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(CGF); else Src = CGF.EmitScalarExpr(E->getArg(0)); SrcType = Src->getType(); @@ -21124,7 +21122,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_get: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Index = EmitScalarExpr(E->getArg(1)); Function *Callee; if (E->getType().isWebAssemblyExternrefType()) @@ -21138,7 +21136,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_set: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Index = EmitScalarExpr(E->getArg(1)); Value *Val = EmitScalarExpr(E->getArg(2)); Function *Callee; @@ -21153,13 +21151,13 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_size: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Value = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Value = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_table_size); return Builder.CreateCall(Callee, Value); } case WebAssembly::BI__builtin_wasm_table_grow: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Val = EmitScalarExpr(E->getArg(1)); Value *NElems = EmitScalarExpr(E->getArg(2)); @@ -21176,7 +21174,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_fill: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Index = EmitScalarExpr(E->getArg(1)); Value *Val = EmitScalarExpr(E->getArg(2)); Value *NElems = EmitScalarExpr(E->getArg(3)); @@ -21194,8 +21192,8 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_copy: { assert(E->getArg(0)->getType()->isArrayType()); - Value *TableX = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); - Value *TableY = EmitArrayToPointerDecay(E->getArg(1)).getPointer(); + Value *TableX = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); + Value *TableY = EmitArrayToPointerDecay(E->getArg(1)).emitRawPointer(*this); Value *DstIdx = EmitScalarExpr(E->getArg(2)); Value *SrcIdx = EmitScalarExpr(E->getArg(3)); Value *NElems = EmitScalarExpr(E->getArg(4)); @@ -21274,7 +21272,7 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, auto MakeCircOp = [this, E](unsigned IntID, bool IsLoad) { // The base pointer is passed by address, so it needs to be loaded. Address A = EmitPointerWithAlignment(E->getArg(0)); - Address BP = Address(A.getPointer(), Int8PtrTy, A.getAlignment()); + Address BP = Address(A.emitRawPointer(*this), Int8PtrTy, A.getAlignment()); llvm::Value *Base = Builder.CreateLoad(BP); // The treatment of both loads and stores is the same: the arguments for // the builtin are the same as the arguments for the intrinsic. @@ -21315,8 +21313,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, // EmitPointerWithAlignment and EmitScalarExpr evaluates the expression // per call. Address DestAddr = EmitPointerWithAlignment(E->getArg(1)); - DestAddr = Address(DestAddr.getPointer(), Int8Ty, DestAddr.getAlignment()); - llvm::Value *DestAddress = DestAddr.getPointer(); + DestAddr = DestAddr.withElementType(Int8Ty); + llvm::Value *DestAddress = DestAddr.emitRawPointer(*this); // Operands are Base, Dest, Modifier. // The intrinsic format in LLVM IR is defined as @@ -21367,8 +21365,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), PredIn}); llvm::Value *PredOut = Builder.CreateExtractValue(Result, 1); - Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.getPointer(), - PredAddr.getAlignment()); + Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.emitRawPointer(*this), + PredAddr.getAlignment()); return Builder.CreateExtractValue(Result, 0); } // These are identical to the builtins above, except they don't consume @@ -21386,8 +21384,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1))}); llvm::Value *PredOut = Builder.CreateExtractValue(Result, 1); - Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.getPointer(), - PredAddr.getAlignment()); + Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.emitRawPointer(*this), + PredAddr.getAlignment()); return Builder.CreateExtractValue(Result, 0); } diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp index d3f2573fd5e38abd8e87b88a07dc2c7970638a45..0cb5b06a519c0098773e6ecafdd1c315048a8007 100644 --- a/clang/lib/CodeGen/CGCUDANV.cpp +++ b/clang/lib/CodeGen/CGCUDANV.cpp @@ -331,11 +331,11 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, llvm::ConstantInt::get(SizeTy, std::max(1, Args.size()))); // Store pointers to the arguments in a locally allocated launch_args. for (unsigned i = 0; i < Args.size(); ++i) { - llvm::Value* VarPtr = CGF.GetAddrOfLocalVar(Args[i]).getPointer(); + llvm::Value *VarPtr = CGF.GetAddrOfLocalVar(Args[i]).emitRawPointer(CGF); llvm::Value *VoidVarPtr = CGF.Builder.CreatePointerCast(VarPtr, PtrTy); CGF.Builder.CreateDefaultAlignedStore( - VoidVarPtr, - CGF.Builder.CreateConstGEP1_32(PtrTy, KernelArgs.getPointer(), i)); + VoidVarPtr, CGF.Builder.CreateConstGEP1_32( + PtrTy, KernelArgs.emitRawPointer(CGF), i)); } llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end"); @@ -393,9 +393,10 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, /*isVarArg=*/false), addUnderscoredPrefixToName("PopCallConfiguration")); - CGF.EmitRuntimeCallOrInvoke(cudaPopConfigFn, - {GridDim.getPointer(), BlockDim.getPointer(), - ShmemSize.getPointer(), Stream.getPointer()}); + CGF.EmitRuntimeCallOrInvoke(cudaPopConfigFn, {GridDim.emitRawPointer(CGF), + BlockDim.emitRawPointer(CGF), + ShmemSize.emitRawPointer(CGF), + Stream.emitRawPointer(CGF)}); // Emit the call to cudaLaunch llvm::Value *Kernel = @@ -405,7 +406,7 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, cudaLaunchKernelFD->getParamDecl(0)->getType()); LaunchKernelArgs.add(RValue::getAggregate(GridDim), Dim3Ty); LaunchKernelArgs.add(RValue::getAggregate(BlockDim), Dim3Ty); - LaunchKernelArgs.add(RValue::get(KernelArgs.getPointer()), + LaunchKernelArgs.add(RValue::get(KernelArgs, CGF), cudaLaunchKernelFD->getParamDecl(3)->getType()); LaunchKernelArgs.add(RValue::get(CGF.Builder.CreateLoad(ShmemSize)), cudaLaunchKernelFD->getParamDecl(4)->getType()); @@ -438,8 +439,8 @@ void CGNVCUDARuntime::emitDeviceStubBodyLegacy(CodeGenFunction &CGF, auto TInfo = CGM.getContext().getTypeInfoInChars(A->getType()); Offset = Offset.alignTo(TInfo.Align); llvm::Value *Args[] = { - CGF.Builder.CreatePointerCast(CGF.GetAddrOfLocalVar(A).getPointer(), - PtrTy), + CGF.Builder.CreatePointerCast( + CGF.GetAddrOfLocalVar(A).emitRawPointer(CGF), PtrTy), llvm::ConstantInt::get(SizeTy, TInfo.Width.getQuantity()), llvm::ConstantInt::get(SizeTy, Offset.getQuantity()), }; @@ -605,20 +606,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 +1084,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 +1095,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 +1153,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/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index a8bf57a277e90963350a58848acdaa6579ce2236..7c6dfc3e59d8c0eb547fbd786378db2457f6a96f 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -20,6 +20,12 @@ using namespace CodeGen; CGCXXABI::~CGCXXABI() { } +Address CGCXXABI::getThisAddress(CodeGenFunction &CGF) { + return CGF.makeNaturalAddressForPointer( + CGF.CXXABIThisValue, CGF.CXXABIThisDecl->getType()->getPointeeType(), + CGF.CXXABIThisAlignment); +} + void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) { DiagnosticsEngine &Diags = CGF.CGM.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -44,8 +50,12 @@ CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer( llvm::Value *MemPtr, const MemberPointerType *MPT) { ErrorUnsupportedABI(CGF, "calls through member pointers"); - ThisPtrForCall = This.getPointer(); - const auto *FPT = MPT->getPointeeType()->castAs(); + const auto *RD = + cast(MPT->getClass()->castAs()->getDecl()); + ThisPtrForCall = + CGF.getAsNaturalPointerTo(This, CGF.getContext().getRecordType(RD)); + const FunctionProtoType *FPT = + MPT->getPointeeType()->getAs(); llvm::Constant *FnPtr = llvm::Constant::getNullValue( llvm::PointerType::getUnqual(CGM.getLLVMContext())); return CGCallee::forDirect(FnPtr, FPT); @@ -251,16 +261,15 @@ void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr, // If we don't need an array cookie, bail out early. if (!requiresArrayCookie(expr, eltTy)) { - allocPtr = ptr.getPointer(); + allocPtr = ptr.emitRawPointer(CGF); numElements = nullptr; cookieSize = CharUnits::Zero(); return; } cookieSize = getArrayCookieSizeImpl(eltTy); - Address allocAddr = - CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); - allocPtr = allocAddr.getPointer(); + Address allocAddr = CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); + allocPtr = allocAddr.emitRawPointer(CGF); numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize); } diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index ad1ad08d0856887e9c37e9d9358e76a87f521a39..c7eccbd0095a94c494e13f9f3785294adad95aae 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -57,12 +57,8 @@ protected: llvm::Value *getThisValue(CodeGenFunction &CGF) { return CGF.CXXABIThisValue; } - Address getThisAddress(CodeGenFunction &CGF) { - return Address( - CGF.CXXABIThisValue, - CGF.ConvertTypeForMem(CGF.CXXABIThisDecl->getType()->getPointeeType()), - CGF.CXXABIThisAlignment); - } + + Address getThisAddress(CodeGenFunction &CGF); /// Issue a diagnostic about unsupported features in the ABI. void ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S); @@ -475,12 +471,6 @@ public: BaseSubobject Base, const CXXRecordDecl *NearestVBase) = 0; - /// Get the address point of the vtable for the given base subobject while - /// building a constexpr. - virtual llvm::Constant * - getVTableAddressPointForConstExpr(BaseSubobject Base, - const CXXRecordDecl *VTableClass) = 0; - /// Get the address of the vtable for the given record decl which should be /// used for the vptr at the given offset in RD. virtual llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index a28d7888715d858430ff9893a80a4d86c23f9dfd..fb0078214b07ff8454998a6872d5964b2d87951b 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -74,6 +74,9 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) { case CC_SwiftAsync: return llvm::CallingConv::SwiftTail; case CC_M68kRTD: return llvm::CallingConv::M68k_RTD; case CC_PreserveNone: return llvm::CallingConv::PreserveNone; + // clang-format off + case CC_RISCVVectorCall: return llvm::CallingConv::RISCV_VectorCall; + // clang-format on } } @@ -260,6 +263,9 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D, if (D->hasAttr()) return CC_PreserveNone; + if (D->hasAttr()) + return CC_RISCVVectorCall; + return CC_C; } @@ -933,8 +939,8 @@ struct NoExpansion : TypeExpansion { static std::unique_ptr getTypeExpansion(QualType Ty, const ASTContext &Context) { if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) { - return std::make_unique( - AT->getElementType(), AT->getSize().getZExtValue()); + return std::make_unique(AT->getElementType(), + AT->getZExtSize()); } if (const RecordType *RT = Ty->getAs()) { SmallVector Bases; @@ -1031,15 +1037,9 @@ static void forConstantArrayExpansion(CodeGenFunction &CGF, ConstantArrayExpansion *CAE, Address BaseAddr, llvm::function_ref Fn) { - CharUnits EltSize = CGF.getContext().getTypeSizeInChars(CAE->EltTy); - CharUnits EltAlign = - BaseAddr.getAlignment().alignmentOfArrayElement(EltSize); - llvm::Type *EltTy = CGF.ConvertTypeForMem(CAE->EltTy); - for (int i = 0, n = CAE->NumElts; i < n; i++) { - llvm::Value *EltAddr = CGF.Builder.CreateConstGEP2_32( - BaseAddr.getElementType(), BaseAddr.getPointer(), 0, i); - Fn(Address(EltAddr, EltTy, EltAlign)); + Address EltAddr = CGF.Builder.CreateConstGEP2_32(BaseAddr, 0, i); + Fn(EltAddr); } } @@ -1154,9 +1154,10 @@ void CodeGenFunction::ExpandTypeToArgs( } /// Create a temporary allocation for the purposes of coercion. -static Address CreateTempAllocaForCoercion(CodeGenFunction &CGF, llvm::Type *Ty, - CharUnits MinAlign, - const Twine &Name = "tmp") { +static RawAddress CreateTempAllocaForCoercion(CodeGenFunction &CGF, + llvm::Type *Ty, + CharUnits MinAlign, + const Twine &Name = "tmp") { // Don't use an alignment that's worse than what LLVM would prefer. auto PrefAlign = CGF.CGM.getDataLayout().getPrefTypeAlign(Ty); CharUnits Align = std::max(MinAlign, CharUnits::fromQuantity(PrefAlign)); @@ -1326,11 +1327,11 @@ static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty, } // Otherwise do coercion through memory. This is stupid, but simple. - Address Tmp = + RawAddress Tmp = CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment(), Src.getName()); CGF.Builder.CreateMemCpy( - Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), Src.getPointer(), - Src.getAlignment().getAsAlign(), + Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), + Src.emitRawPointer(CGF), Src.getAlignment().getAsAlign(), llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize.getKnownMinValue())); return CGF.Builder.CreateLoad(Tmp); } @@ -1414,11 +1415,12 @@ static void CreateCoercedStore(llvm::Value *Src, // // FIXME: Assert that we aren't truncating non-padding bits when have access // to that information. - Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment()); + RawAddress Tmp = + CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment()); CGF.Builder.CreateStore(Src, Tmp); CGF.Builder.CreateMemCpy( - Dst.getPointer(), Dst.getAlignment().getAsAlign(), Tmp.getPointer(), - Tmp.getAlignment().getAsAlign(), + Dst.emitRawPointer(CGF), Dst.getAlignment().getAsAlign(), + Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), llvm::ConstantInt::get(CGF.IntPtrTy, DstSize.getFixedValue())); } } @@ -3018,17 +3020,17 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, case ABIArgInfo::Indirect: case ABIArgInfo::IndirectAliased: { assert(NumIRArgs == 1); - Address ParamAddr = Address(Fn->getArg(FirstIRArg), ConvertTypeForMem(Ty), - ArgI.getIndirectAlign(), KnownNonNull); + Address ParamAddr = makeNaturalAddressForPointer( + Fn->getArg(FirstIRArg), Ty, ArgI.getIndirectAlign(), false, nullptr, + nullptr, KnownNonNull); if (!hasScalarEvaluationKind(Ty)) { // Aggregates and complex variables are accessed by reference. All we // need to do is realign the value, if requested. Also, if the address // may be aliased, copy it to ensure that the parameter variable is // mutable and has a unique adress, as C requires. - Address V = ParamAddr; if (ArgI.getIndirectRealign() || ArgI.isIndirectAliased()) { - Address AlignedTemp = CreateMemTemp(Ty, "coerce"); + RawAddress AlignedTemp = CreateMemTemp(Ty, "coerce"); // Copy from the incoming argument pointer to the temporary with the // appropriate alignment. @@ -3038,11 +3040,12 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, CharUnits Size = getContext().getTypeSizeInChars(Ty); Builder.CreateMemCpy( AlignedTemp.getPointer(), AlignedTemp.getAlignment().getAsAlign(), - ParamAddr.getPointer(), ParamAddr.getAlignment().getAsAlign(), + ParamAddr.emitRawPointer(*this), + ParamAddr.getAlignment().getAsAlign(), llvm::ConstantInt::get(IntPtrTy, Size.getQuantity())); - V = AlignedTemp; + ParamAddr = AlignedTemp; } - ArgVals.push_back(ParamValue::forIndirect(V)); + ArgVals.push_back(ParamValue::forIndirect(ParamAddr)); } else { // Load scalar value from indirect argument. llvm::Value *V = @@ -3086,7 +3089,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, llvm::Align Alignment = CGM.getNaturalTypeAlignment(ETy).getAsAlign(); AI->addAttrs(llvm::AttrBuilder(getLLVMContext()).addAlignmentAttr(Alignment)); - uint64_t ArrSize = ArrTy->getSize().getZExtValue(); + uint64_t ArrSize = ArrTy->getZExtSize(); if (!ETy->isIncompleteType() && ETy->isConstantSizeType() && ArrSize) { llvm::AttrBuilder Attrs(getLLVMContext()); @@ -3156,10 +3159,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, == ParameterABI::SwiftErrorResult) { QualType pointeeTy = Ty->getPointeeType(); assert(pointeeTy->isPointerType()); - Address temp = - CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); - Address arg(V, ConvertTypeForMem(pointeeTy), - getContext().getTypeAlignInChars(pointeeTy)); + RawAddress temp = + CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); + Address arg = makeNaturalAddressForPointer( + V, pointeeTy, getContext().getTypeAlignInChars(pointeeTy)); llvm::Value *incomingErrorValue = Builder.CreateLoad(arg); Builder.CreateStore(incomingErrorValue, temp); V = temp.getPointer(); @@ -3496,7 +3499,7 @@ static llvm::Value *tryRemoveRetainOfSelf(CodeGenFunction &CGF, llvm::LoadInst *load = dyn_cast(retainedValue->stripPointerCasts()); if (!load || load->isAtomic() || load->isVolatile() || - load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getPointer()) + load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getBasePointer()) return nullptr; // Okay! Burn it all down. This relies for correctness on the @@ -3533,12 +3536,15 @@ static llvm::Value *emitAutoreleaseOfResult(CodeGenFunction &CGF, /// Heuristically search for a dominating store to the return-value slot. static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { + llvm::Value *ReturnValuePtr = CGF.ReturnValue.getBasePointer(); + // Check if a User is a store which pointerOperand is the ReturnValue. // We are looking for stores to the ReturnValue, not for stores of the // ReturnValue to some other location. - auto GetStoreIfValid = [&CGF](llvm::User *U) -> llvm::StoreInst * { + auto GetStoreIfValid = [&CGF, + ReturnValuePtr](llvm::User *U) -> llvm::StoreInst * { auto *SI = dyn_cast(U); - if (!SI || SI->getPointerOperand() != CGF.ReturnValue.getPointer() || + if (!SI || SI->getPointerOperand() != ReturnValuePtr || SI->getValueOperand()->getType() != CGF.ReturnValue.getElementType()) return nullptr; // These aren't actually possible for non-coerced returns, and we @@ -3552,7 +3558,7 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { // for something immediately preceding the IP. Sometimes this can // happen with how we generate implicit-returns; it can also happen // with noreturn cleanups. - if (!CGF.ReturnValue.getPointer()->hasOneUse()) { + if (!ReturnValuePtr->hasOneUse()) { llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock(); if (IP->empty()) return nullptr; @@ -3570,8 +3576,7 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { return nullptr; } - llvm::StoreInst *store = - GetStoreIfValid(CGF.ReturnValue.getPointer()->user_back()); + llvm::StoreInst *store = GetStoreIfValid(ReturnValuePtr->user_back()); if (!store) return nullptr; // Now do a first-and-dirty dominance check: just walk up the @@ -4115,7 +4120,11 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, } static bool isProvablyNull(llvm::Value *addr) { - return isa(addr); + return llvm::isa_and_nonnull(addr); +} + +static bool isProvablyNonNull(Address Addr, CodeGenFunction &CGF) { + return llvm::isKnownNonZero(Addr.getBasePointer(), CGF.CGM.getDataLayout()); } /// Emit the actual writing-back of a writeback. @@ -4123,21 +4132,20 @@ static void emitWriteback(CodeGenFunction &CGF, const CallArgList::Writeback &writeback) { const LValue &srcLV = writeback.Source; Address srcAddr = srcLV.getAddress(CGF); - assert(!isProvablyNull(srcAddr.getPointer()) && + assert(!isProvablyNull(srcAddr.getBasePointer()) && "shouldn't have writeback for provably null argument"); llvm::BasicBlock *contBB = nullptr; // If the argument wasn't provably non-null, we need to null check // before doing the store. - bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), - CGF.CGM.getDataLayout()); + bool provablyNonNull = isProvablyNonNull(srcAddr, CGF); + if (!provablyNonNull) { llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback"); contBB = CGF.createBasicBlock("icr.done"); - llvm::Value *isNull = - CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull"); + llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull"); CGF.Builder.CreateCondBr(isNull, contBB, writebackBB); CGF.EmitBlock(writebackBB); } @@ -4241,7 +4249,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, CGF.ConvertTypeForMem(CRE->getType()->getPointeeType()); // If the address is a constant null, just pass the appropriate null. - if (isProvablyNull(srcAddr.getPointer())) { + if (isProvablyNull(srcAddr.getBasePointer())) { args.add(RValue::get(llvm::ConstantPointerNull::get(destType)), CRE->getType()); return; @@ -4270,17 +4278,16 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, // If the address is *not* known to be non-null, we need to switch. llvm::Value *finalArgument; - bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), - CGF.CGM.getDataLayout()); + bool provablyNonNull = isProvablyNonNull(srcAddr, CGF); + if (provablyNonNull) { - finalArgument = temp.getPointer(); + finalArgument = temp.emitRawPointer(CGF); } else { - llvm::Value *isNull = - CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull"); + llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull"); - finalArgument = CGF.Builder.CreateSelect(isNull, - llvm::ConstantPointerNull::get(destType), - temp.getPointer(), "icr.argument"); + finalArgument = CGF.Builder.CreateSelect( + isNull, llvm::ConstantPointerNull::get(destType), + temp.emitRawPointer(CGF), "icr.argument"); // If we need to copy, then the load has to be conditional, which // means we need control flow. @@ -4404,6 +4411,16 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, std::nullopt); } +void CodeGenFunction::EmitNonNullArgCheck(Address Addr, QualType ArgType, + SourceLocation ArgLoc, + AbstractCallee AC, unsigned ParmNum) { + if (!AC.getDecl() || !(SanOpts.has(SanitizerKind::NonnullAttribute) || + SanOpts.has(SanitizerKind::NullabilityArg))) + return; + + EmitNonNullArgCheck(RValue::get(Addr, *this), ArgType, ArgLoc, AC, ParmNum); +} + // Check if the call is going to use the inalloca convention. This needs to // agree with CGFunctionInfo::usesInAlloca. The CGFunctionInfo is arranged // later, so we can't check it directly. @@ -4744,10 +4761,20 @@ CodeGenFunction::AddObjCARCExceptionMetadata(llvm::Instruction *Inst) { llvm::CallInst * CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const llvm::Twine &name) { - return EmitNounwindRuntimeCall(callee, std::nullopt, name); + return EmitNounwindRuntimeCall(callee, ArrayRef(), name); } /// Emits a call to the given nounwind runtime function. +llvm::CallInst * +CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, + ArrayRef
args, + const llvm::Twine &name) { + SmallVector values; + for (auto arg : args) + values.push_back(arg.emitRawPointer(*this)); + return EmitNounwindRuntimeCall(callee, values, name); +} + llvm::CallInst * CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, ArrayRef args, @@ -5026,7 +5053,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If we're using inalloca, insert the allocation after the stack save. // FIXME: Do this earlier rather than hacking it in here! - Address ArgMemory = Address::invalid(); + RawAddress ArgMemory = RawAddress::invalid(); if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) { const llvm::DataLayout &DL = CGM.getDataLayout(); llvm::Instruction *IP = CallArgs.getStackBase(); @@ -5042,7 +5069,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, AI->setAlignment(Align.getAsAlign()); AI->setUsedWithInAlloca(true); assert(AI->isUsedWithInAlloca() && !AI->isStaticAlloca()); - ArgMemory = Address(AI, ArgStruct, Align); + ArgMemory = RawAddress(AI, ArgStruct, Align); } ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), CallInfo); @@ -5051,11 +5078,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If the call returns a temporary with struct return, create a temporary // alloca to hold the result, unless one is given to us. Address SRetPtr = Address::invalid(); - Address SRetAlloca = Address::invalid(); + RawAddress SRetAlloca = RawAddress::invalid(); llvm::Value *UnusedReturnSizePtr = nullptr; if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) { if (!ReturnValue.isNull()) { - SRetPtr = ReturnValue.getValue(); + SRetPtr = ReturnValue.getAddress(); } else { SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca); if (HaveInsertPoint() && ReturnValue.isUnused()) { @@ -5065,15 +5092,16 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } } if (IRFunctionArgs.hasSRetArg()) { - IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr.getPointer(); + IRCallArgs[IRFunctionArgs.getSRetArgNo()] = + getAsNaturalPointerTo(SRetPtr, RetTy); } else if (RetAI.isInAlloca()) { Address Addr = Builder.CreateStructGEP(ArgMemory, RetAI.getInAllocaFieldIndex()); - Builder.CreateStore(SRetPtr.getPointer(), Addr); + Builder.CreateStore(getAsNaturalPointerTo(SRetPtr, RetTy), Addr); } } - Address swiftErrorTemp = Address::invalid(); + RawAddress swiftErrorTemp = RawAddress::invalid(); Address swiftErrorArg = Address::invalid(); // When passing arguments using temporary allocas, we need to add the @@ -5106,9 +5134,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(NumIRArgs == 0); assert(getTarget().getTriple().getArch() == llvm::Triple::x86); if (I->isAggregate()) { - Address Addr = I->hasLValue() - ? I->getKnownLValue().getAddress(*this) - : I->getKnownRValue().getAggregateAddress(); + RawAddress Addr = I->hasLValue() + ? I->getKnownLValue().getAddress(*this) + : I->getKnownRValue().getAggregateAddress(); llvm::Instruction *Placeholder = cast(Addr.getPointer()); @@ -5132,7 +5160,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } else if (ArgInfo.getInAllocaIndirect()) { // Make a temporary alloca and store the address of it into the argument // struct. - Address Addr = CreateMemTempWithoutCast( + RawAddress Addr = CreateMemTempWithoutCast( I->Ty, getContext().getTypeAlignInChars(I->Ty), "indirect-arg-temp"); I->copyInto(*this, Addr); @@ -5154,12 +5182,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(NumIRArgs == 1); if (!I->isAggregate()) { // Make a temporary alloca to pass the argument. - Address Addr = CreateMemTempWithoutCast( + RawAddress Addr = CreateMemTempWithoutCast( I->Ty, ArgInfo.getIndirectAlign(), "indirect-arg-temp"); - llvm::Value *Val = Addr.getPointer(); + llvm::Value *Val = getAsNaturalPointerTo(Addr, I->Ty); if (ArgHasMaybeUndefAttr) - Val = Builder.CreateFreeze(Addr.getPointer()); + Val = Builder.CreateFreeze(Val); IRCallArgs[FirstIRArg] = Val; I->copyInto(*this, Addr); @@ -5175,7 +5203,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Address Addr = I->hasLValue() ? I->getKnownLValue().getAddress(*this) : I->getKnownRValue().getAggregateAddress(); - llvm::Value *V = Addr.getPointer(); CharUnits Align = ArgInfo.getIndirectAlign(); const llvm::DataLayout *TD = &CGM.getDataLayout(); @@ -5186,8 +5213,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, bool NeedCopy = false; if (Addr.getAlignment() < Align && - llvm::getOrEnforceKnownAlignment(V, Align.getAsAlign(), *TD) < - Align.getAsAlign()) { + llvm::getOrEnforceKnownAlignment(Addr.emitRawPointer(*this), + Align.getAsAlign(), + *TD) < Align.getAsAlign()) { NeedCopy = true; } else if (I->hasLValue()) { auto LV = I->getKnownLValue(); @@ -5218,11 +5246,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (NeedCopy) { // Create an aligned temporary, and copy to it. - Address AI = CreateMemTempWithoutCast( + RawAddress AI = CreateMemTempWithoutCast( I->Ty, ArgInfo.getIndirectAlign(), "byval-temp"); - llvm::Value *Val = AI.getPointer(); + llvm::Value *Val = getAsNaturalPointerTo(AI, I->Ty); if (ArgHasMaybeUndefAttr) - Val = Builder.CreateFreeze(AI.getPointer()); + Val = Builder.CreateFreeze(Val); IRCallArgs[FirstIRArg] = Val; // Emit lifetime markers for the temporary alloca. @@ -5239,6 +5267,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, I->copyInto(*this, AI); } else { // Skip the extra memcpy call. + llvm::Value *V = getAsNaturalPointerTo(Addr, I->Ty); auto *T = llvm::PointerType::get( CGM.getLLVMContext(), CGM.getDataLayout().getAllocaAddrSpace()); @@ -5278,8 +5307,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(!swiftErrorTemp.isValid() && "multiple swifterror args"); QualType pointeeTy = I->Ty->getPointeeType(); - swiftErrorArg = Address(V, ConvertTypeForMem(pointeeTy), - getContext().getTypeAlignInChars(pointeeTy)); + swiftErrorArg = makeNaturalAddressForPointer( + V, pointeeTy, getContext().getTypeAlignInChars(pointeeTy)); swiftErrorTemp = CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); @@ -5416,7 +5445,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::Value *tempSize = nullptr; Address addr = Address::invalid(); - Address AllocaAddr = Address::invalid(); + RawAddress AllocaAddr = RawAddress::invalid(); if (I->isAggregate()) { addr = I->hasLValue() ? I->getKnownLValue().getAddress(*this) : I->getKnownRValue().getAggregateAddress(); @@ -5850,7 +5879,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, return RValue::getComplex(std::make_pair(Real, Imag)); } case TEK_Aggregate: { - Address DestPtr = ReturnValue.getValue(); + Address DestPtr = ReturnValue.getAddress(); bool DestIsVolatile = ReturnValue.isVolatile(); if (!DestPtr.isValid()) { diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h index 1bd48a07259307486a53f2eba0de9f221274d219..6b676ac196db2a9a19f721b924da2e9ea274324c 100644 --- a/clang/lib/CodeGen/CGCall.h +++ b/clang/lib/CodeGen/CGCall.h @@ -377,6 +377,7 @@ public: Address getValue() const { return Addr; } bool isUnused() const { return IsUnused; } bool isExternallyDestructed() const { return IsExternallyDestructed; } + Address getAddress() const { return Addr; } }; /// Adds attributes to \p F according to our \p CodeGenOpts and \p LangOpts, as diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 34319381901af6c9458fd6cea2af18cf97be75e7..8c1c8ee455d2e634dc83a8845f2a970125184b9d 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -139,8 +139,9 @@ Address CodeGenFunction::LoadCXXThisAddress() { CXXThisAlignment = CGM.getClassPointerAlignment(MD->getParent()); } - llvm::Type *Ty = ConvertType(MD->getFunctionObjectParameterType()); - return Address(LoadCXXThis(), Ty, CXXThisAlignment, KnownNonNull); + return makeNaturalAddressForPointer( + LoadCXXThis(), MD->getFunctionObjectParameterType(), CXXThisAlignment, + false, nullptr, nullptr, KnownNonNull); } /// Emit the address of a field using a member data pointer. @@ -270,7 +271,7 @@ ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr, } // Apply the base offset. - llvm::Value *ptr = addr.getPointer(); + llvm::Value *ptr = addr.emitRawPointer(CGF); ptr = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ptr, baseOffset, "add.ptr"); // If we have a virtual component, the alignment of the result will @@ -338,8 +339,8 @@ Address CodeGenFunction::GetAddressOfBaseClass( if (sanitizePerformTypeCheck()) { SanitizerSet SkippedChecks; SkippedChecks.set(SanitizerKind::Null, !NullCheckValue); - EmitTypeCheck(TCK_Upcast, Loc, Value.getPointer(), - DerivedTy, DerivedAlign, SkippedChecks); + EmitTypeCheck(TCK_Upcast, Loc, Value.emitRawPointer(*this), DerivedTy, + DerivedAlign, SkippedChecks); } return Value.withElementType(BaseValueTy); } @@ -354,7 +355,7 @@ Address CodeGenFunction::GetAddressOfBaseClass( llvm::BasicBlock *notNullBB = createBasicBlock("cast.notnull"); endBB = createBasicBlock("cast.end"); - llvm::Value *isNull = Builder.CreateIsNull(Value.getPointer()); + llvm::Value *isNull = Builder.CreateIsNull(Value); Builder.CreateCondBr(isNull, endBB, notNullBB); EmitBlock(notNullBB); } @@ -363,14 +364,15 @@ Address CodeGenFunction::GetAddressOfBaseClass( SanitizerSet SkippedChecks; SkippedChecks.set(SanitizerKind::Null, true); EmitTypeCheck(VBase ? TCK_UpcastToVirtualBase : TCK_Upcast, Loc, - Value.getPointer(), DerivedTy, DerivedAlign, SkippedChecks); + Value.emitRawPointer(*this), DerivedTy, DerivedAlign, + SkippedChecks); } // Compute the virtual offset. llvm::Value *VirtualOffset = nullptr; if (VBase) { VirtualOffset = - CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase); + CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase); } // Apply both offsets. @@ -387,7 +389,7 @@ Address CodeGenFunction::GetAddressOfBaseClass( EmitBlock(endBB); llvm::PHINode *PHI = Builder.CreatePHI(PtrTy, 2, "cast.result"); - PHI->addIncoming(Value.getPointer(), notNullBB); + PHI->addIncoming(Value.emitRawPointer(*this), notNullBB); PHI->addIncoming(llvm::Constant::getNullValue(PtrTy), origBB); Value = Value.withPointer(PHI, NotKnownNonNull); } @@ -424,15 +426,19 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr, CastNotNull = createBasicBlock("cast.notnull"); CastEnd = createBasicBlock("cast.end"); - llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr.getPointer()); + llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr); Builder.CreateCondBr(IsNull, CastNull, CastNotNull); EmitBlock(CastNotNull); } // Apply the offset. - llvm::Value *Value = BaseAddr.getPointer(); - Value = Builder.CreateInBoundsGEP( - Int8Ty, Value, Builder.CreateNeg(NonVirtualOffset), "sub.ptr"); + Address Addr = BaseAddr.withElementType(Int8Ty); + Addr = Builder.CreateInBoundsGEP( + Addr, Builder.CreateNeg(NonVirtualOffset), Int8Ty, + CGM.getClassPointerAlignment(Derived), "sub.ptr"); + + // Just cast. + Addr = Addr.withElementType(DerivedValueTy); // Produce a PHI if we had a null-check. if (NullCheckValue) { @@ -441,13 +447,15 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr, Builder.CreateBr(CastEnd); EmitBlock(CastEnd); + llvm::Value *Value = Addr.emitRawPointer(*this); llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2); PHI->addIncoming(Value, CastNotNull); PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull); - Value = PHI; + return Address(PHI, Addr.getElementType(), + CGM.getClassPointerAlignment(Derived)); } - return Address(Value, DerivedValueTy, CGM.getClassPointerAlignment(Derived)); + return Addr; } llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD, @@ -1719,7 +1727,7 @@ namespace { // Use the base class declaration location as inline DebugLocation. All // fields of the class are destroyed. DeclAsInlineDebugLocation InlineHere(CGF, *BaseClass); - EmitSanitizerDtorFieldsCallback(CGF, Addr.getPointer(), + EmitSanitizerDtorFieldsCallback(CGF, Addr.emitRawPointer(CGF), BaseSize.getQuantity()); // Prevent the current stack frame from disappearing from the stack trace. @@ -2022,7 +2030,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, // Find the end of the array. llvm::Type *elementType = arrayBase.getElementType(); - llvm::Value *arrayBegin = arrayBase.getPointer(); + llvm::Value *arrayBegin = arrayBase.emitRawPointer(*this); llvm::Value *arrayEnd = Builder.CreateInBoundsGEP( elementType, arrayBegin, numElements, "arrayctor.end"); @@ -2118,14 +2126,15 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, Address This = ThisAVS.getAddress(); LangAS SlotAS = ThisAVS.getQualifiers().getAddressSpace(); LangAS ThisAS = D->getFunctionObjectParameterType().getAddressSpace(); - llvm::Value *ThisPtr = This.getPointer(); + llvm::Value *ThisPtr = + getAsNaturalPointerTo(This, D->getThisType()->getPointeeType()); if (SlotAS != ThisAS) { unsigned TargetThisAS = getContext().getTargetAddressSpace(ThisAS); llvm::Type *NewType = llvm::PointerType::get(getLLVMContext(), TargetThisAS); - ThisPtr = getTargetHooks().performAddrSpaceCast(*this, This.getPointer(), - ThisAS, SlotAS, NewType); + ThisPtr = getTargetHooks().performAddrSpaceCast(*this, ThisPtr, ThisAS, + SlotAS, NewType); } // Push the this ptr. @@ -2194,7 +2203,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, const CXXRecordDecl *ClassDecl = D->getParent(); if (!NewPointerIsChecked) - EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This.getPointer(), + EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This, getContext().getRecordType(ClassDecl), CharUnits::Zero()); if (D->isTrivial() && D->isDefaultConstructor()) { @@ -2207,10 +2216,9 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, // model that copy. if (isMemcpyEquivalentSpecialMember(D)) { assert(Args.size() == 2 && "unexpected argcount for trivial ctor"); - QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType(); - Address Src = Address(Args[1].getRValue(*this).getScalarVal(), ConvertTypeForMem(SrcTy), - CGM.getNaturalTypeAlignment(SrcTy)); + Address Src = makeNaturalAddressForPointer( + Args[1].getRValue(*this).getScalarVal(), SrcTy); LValue SrcLVal = MakeAddrLValue(Src, SrcTy); QualType DestTy = getContext().getTypeDeclType(ClassDecl); LValue DestLVal = MakeAddrLValue(This, DestTy); @@ -2263,7 +2271,9 @@ void CodeGenFunction::EmitInheritedCXXConstructorCall( const CXXConstructorDecl *D, bool ForVirtualBase, Address This, bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) { CallArgList Args; - CallArg ThisArg(RValue::get(This.getPointer()), D->getThisType()); + CallArg ThisArg(RValue::get(getAsNaturalPointerTo( + This, D->getThisType()->getPointeeType())), + D->getThisType()); // Forward the parameters. if (InheritedFromVBase && @@ -2388,12 +2398,14 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, CallArgList Args; // Push the this ptr. - Args.add(RValue::get(This.getPointer()), D->getThisType()); + Args.add(RValue::get(getAsNaturalPointerTo(This, D->getThisType())), + D->getThisType()); // Push the src ptr. QualType QT = *(FPT->param_type_begin()); llvm::Type *t = CGM.getTypes().ConvertType(QT); - llvm::Value *SrcVal = Builder.CreateBitCast(Src.getPointer(), t); + llvm::Value *Val = getAsNaturalPointerTo(Src, D->getThisType()); + llvm::Value *SrcVal = Builder.CreateBitCast(Val, t); Args.add(RValue::get(SrcVal), QT); // Skip over first argument (Src). @@ -2418,7 +2430,9 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, // this Address This = LoadCXXThisAddress(); - DelegateArgs.add(RValue::get(This.getPointer()), (*I)->getType()); + DelegateArgs.add(RValue::get(getAsNaturalPointerTo( + This, (*I)->getType()->getPointeeType())), + (*I)->getType()); ++I; // FIXME: The location of the VTT parameter in the parameter list is @@ -2775,7 +2789,7 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, Address Derived, if (MayBeNull) { llvm::Value *DerivedNotNull = - Builder.CreateIsNotNull(Derived.getPointer(), "cast.nonnull"); + Builder.CreateIsNotNull(Derived.emitRawPointer(*this), "cast.nonnull"); llvm::BasicBlock *CheckBlock = createBasicBlock("cast.check"); ContBlock = createBasicBlock("cast.cont"); @@ -2976,7 +2990,7 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() { QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda)); Address ThisPtr = GetAddrOfBlockDecl(variable); - CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); + CallArgs.add(RValue::get(getAsNaturalPointerTo(ThisPtr, ThisType)), ThisType); // Add the rest of the parameters. for (auto *param : BD->parameters()) @@ -3004,7 +3018,7 @@ void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) { QualType LambdaType = getContext().getRecordType(Lambda); QualType ThisType = getContext().getPointerType(LambdaType); Address ThisPtr = CreateMemTemp(LambdaType, "unused.capture"); - CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); + CallArgs.add(RValue::get(ThisPtr.emitRawPointer(*this)), ThisType); EmitLambdaDelegatingInvokeBody(MD, CallArgs); } diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index f87caf050eeaa74b31de1452327e67f6139afaa8..e6f8e6873004f29d716caea0e82fb902be0f8117 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -27,7 +27,7 @@ bool DominatingValue::saved_type::needsSaving(RValue rv) { if (rv.isScalar()) return DominatingLLVMValue::needsSaving(rv.getScalarVal()); if (rv.isAggregate()) - return DominatingLLVMValue::needsSaving(rv.getAggregatePointer()); + return DominatingValue
::needsSaving(rv.getAggregateAddress()); return true; } @@ -35,69 +35,40 @@ DominatingValue::saved_type DominatingValue::saved_type::save(CodeGenFunction &CGF, RValue rv) { if (rv.isScalar()) { llvm::Value *V = rv.getScalarVal(); - - // These automatically dominate and don't need to be saved. - if (!DominatingLLVMValue::needsSaving(V)) - return saved_type(V, nullptr, ScalarLiteral); - - // Everything else needs an alloca. - Address addr = - CGF.CreateDefaultAlignTempAlloca(V->getType(), "saved-rvalue"); - CGF.Builder.CreateStore(V, addr); - return saved_type(addr.getPointer(), nullptr, ScalarAddress); + return saved_type(DominatingLLVMValue::save(CGF, V), + DominatingLLVMValue::needsSaving(V) ? ScalarAddress + : ScalarLiteral); } if (rv.isComplex()) { CodeGenFunction::ComplexPairTy V = rv.getComplexVal(); - llvm::Type *ComplexTy = - llvm::StructType::get(V.first->getType(), V.second->getType()); - Address addr = CGF.CreateDefaultAlignTempAlloca(ComplexTy, "saved-complex"); - CGF.Builder.CreateStore(V.first, CGF.Builder.CreateStructGEP(addr, 0)); - CGF.Builder.CreateStore(V.second, CGF.Builder.CreateStructGEP(addr, 1)); - return saved_type(addr.getPointer(), nullptr, ComplexAddress); + return saved_type(DominatingLLVMValue::save(CGF, V.first), + DominatingLLVMValue::save(CGF, V.second)); } assert(rv.isAggregate()); - Address V = rv.getAggregateAddress(); // TODO: volatile? - if (!DominatingLLVMValue::needsSaving(V.getPointer())) - return saved_type(V.getPointer(), V.getElementType(), AggregateLiteral, - V.getAlignment().getQuantity()); - - Address addr = - CGF.CreateTempAlloca(V.getType(), CGF.getPointerAlign(), "saved-rvalue"); - CGF.Builder.CreateStore(V.getPointer(), addr); - return saved_type(addr.getPointer(), V.getElementType(), AggregateAddress, - V.getAlignment().getQuantity()); + Address V = rv.getAggregateAddress(); + return saved_type( + DominatingValue
::save(CGF, V), rv.isVolatileQualified(), + DominatingValue
::needsSaving(V) ? AggregateAddress + : AggregateLiteral); } /// Given a saved r-value produced by SaveRValue, perform the code /// necessary to restore it to usability at the current insertion /// point. RValue DominatingValue::saved_type::restore(CodeGenFunction &CGF) { - auto getSavingAddress = [&](llvm::Value *value) { - auto *AI = cast(value); - return Address(value, AI->getAllocatedType(), - CharUnits::fromQuantity(AI->getAlign().value())); - }; switch (K) { case ScalarLiteral: - return RValue::get(Value); case ScalarAddress: - return RValue::get(CGF.Builder.CreateLoad(getSavingAddress(Value))); + return RValue::get(DominatingLLVMValue::restore(CGF, Vals.first)); case AggregateLiteral: + case AggregateAddress: return RValue::getAggregate( - Address(Value, ElementType, CharUnits::fromQuantity(Align))); - case AggregateAddress: { - auto addr = CGF.Builder.CreateLoad(getSavingAddress(Value)); - return RValue::getAggregate( - Address(addr, ElementType, CharUnits::fromQuantity(Align))); - } + DominatingValue
::restore(CGF, AggregateAddr), IsVolatile); case ComplexAddress: { - Address address = getSavingAddress(Value); - llvm::Value *real = - CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(address, 0)); - llvm::Value *imag = - CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(address, 1)); + llvm::Value *real = DominatingLLVMValue::restore(CGF, Vals.first); + llvm::Value *imag = DominatingLLVMValue::restore(CGF, Vals.second); return RValue::getComplex(real, imag); } } @@ -294,14 +265,14 @@ void EHScopeStack::popNullFixups() { BranchFixups.pop_back(); } -Address CodeGenFunction::createCleanupActiveFlag() { +RawAddress CodeGenFunction::createCleanupActiveFlag() { // Create a variable to decide whether the cleanup needs to be run. - Address active = CreateTempAllocaWithoutCast( + RawAddress active = CreateTempAllocaWithoutCast( Builder.getInt1Ty(), CharUnits::One(), "cleanup.cond"); // Initialize it to false at a site that's guaranteed to be run // before each evaluation. - setBeforeOutermostConditional(Builder.getFalse(), active); + setBeforeOutermostConditional(Builder.getFalse(), active, *this); // Initialize it to true at the current location. Builder.CreateStore(Builder.getTrue(), active); @@ -309,7 +280,7 @@ Address CodeGenFunction::createCleanupActiveFlag() { return active; } -void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) { +void CodeGenFunction::initFullExprCleanupWithFlag(RawAddress ActiveFlag) { // Set that as the active flag in the cleanup. EHCleanupScope &cleanup = cast(*EHStack.begin()); assert(!cleanup.hasActiveFlag() && "cleanup already has active flag?"); @@ -322,15 +293,17 @@ void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) { void EHScopeStack::Cleanup::anchor() {} static void createStoreInstBefore(llvm::Value *value, Address addr, - llvm::Instruction *beforeInst) { - auto store = new llvm::StoreInst(value, addr.getPointer(), beforeInst); + llvm::Instruction *beforeInst, + CodeGenFunction &CGF) { + auto store = new llvm::StoreInst(value, addr.emitRawPointer(CGF), beforeInst); store->setAlignment(addr.getAlignment().getAsAlign()); } static llvm::LoadInst *createLoadInstBefore(Address addr, const Twine &name, - llvm::Instruction *beforeInst) { - return new llvm::LoadInst(addr.getElementType(), addr.getPointer(), name, - false, addr.getAlignment().getAsAlign(), + llvm::Instruction *beforeInst, + CodeGenFunction &CGF) { + return new llvm::LoadInst(addr.getElementType(), addr.emitRawPointer(CGF), + name, false, addr.getAlignment().getAsAlign(), beforeInst); } @@ -357,8 +330,8 @@ static void ResolveAllBranchFixups(CodeGenFunction &CGF, // entry which we're currently popping. if (Fixup.OptimisticBranchBlock == nullptr) { createStoreInstBefore(CGF.Builder.getInt32(Fixup.DestinationIndex), - CGF.getNormalCleanupDestSlot(), - Fixup.InitialBranch); + CGF.getNormalCleanupDestSlot(), Fixup.InitialBranch, + CGF); Fixup.InitialBranch->setSuccessor(0, CleanupEntry); } @@ -385,7 +358,7 @@ static llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF, if (llvm::BranchInst *Br = dyn_cast(Term)) { assert(Br->isUnconditional()); auto Load = createLoadInstBefore(CGF.getNormalCleanupDestSlot(), - "cleanup.dest", Term); + "cleanup.dest", Term, CGF); llvm::SwitchInst *Switch = llvm::SwitchInst::Create(Load, Br->getSuccessor(0), 4, Block); Br->eraseFromParent(); @@ -513,8 +486,8 @@ void CodeGenFunction::PopCleanupBlocks( I += Header.getSize(); if (Header.isConditional()) { - Address ActiveFlag = - reinterpret_cast
(LifetimeExtendedCleanupStack[I]); + RawAddress ActiveFlag = + reinterpret_cast(LifetimeExtendedCleanupStack[I]); initFullExprCleanupWithFlag(ActiveFlag); I += sizeof(ActiveFlag); } @@ -888,7 +861,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { if (NormalCleanupDestSlot->hasOneUse()) { NormalCleanupDestSlot->user_back()->eraseFromParent(); NormalCleanupDestSlot->eraseFromParent(); - NormalCleanupDest = Address::invalid(); + NormalCleanupDest = RawAddress::invalid(); } llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0); @@ -912,9 +885,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { // pass the abnormal exit flag to Fn (SEH cleanup) cleanupFlags.setHasExitSwitch(); - llvm::LoadInst *Load = - createLoadInstBefore(getNormalCleanupDestSlot(), "cleanup.dest", - nullptr); + llvm::LoadInst *Load = createLoadInstBefore( + getNormalCleanupDestSlot(), "cleanup.dest", nullptr, *this); llvm::SwitchInst *Switch = llvm::SwitchInst::Create(Load, Default, SwitchCapacity); @@ -961,8 +933,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { if (!Fixup.Destination) continue; if (!Fixup.OptimisticBranchBlock) { createStoreInstBefore(Builder.getInt32(Fixup.DestinationIndex), - getNormalCleanupDestSlot(), - Fixup.InitialBranch); + getNormalCleanupDestSlot(), Fixup.InitialBranch, + *this); Fixup.InitialBranch->setSuccessor(0, NormalEntry); } Fixup.OptimisticBranchBlock = NormalExit; @@ -1135,7 +1107,7 @@ void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) { // Store the index at the start. llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex()); - createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI); + createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI, *this); // Adjust BI to point to the first cleanup block. { @@ -1269,9 +1241,9 @@ static void SetupCleanupBlockActivation(CodeGenFunction &CGF, // If we're in a conditional block, ignore the dominating IP and // use the outermost conditional branch. if (CGF.isInConditionalBranch()) { - CGF.setBeforeOutermostConditional(value, var); + CGF.setBeforeOutermostConditional(value, var, CGF); } else { - createStoreInstBefore(value, var, dominatingIP); + createStoreInstBefore(value, var, dominatingIP, CGF); } } @@ -1321,7 +1293,7 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C, Scope.setActive(false); } -Address CodeGenFunction::getNormalCleanupDestSlot() { +RawAddress CodeGenFunction::getNormalCleanupDestSlot() { if (!NormalCleanupDest.isValid()) NormalCleanupDest = CreateDefaultAlignTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot"); diff --git a/clang/lib/CodeGen/CGCleanup.h b/clang/lib/CodeGen/CGCleanup.h index 7a7344c07160db388ba8d743a37c245069c9af9c..03e4a29d7b3dbfa5b3953725e9fc1fe0fe55bb44 100644 --- a/clang/lib/CodeGen/CGCleanup.h +++ b/clang/lib/CodeGen/CGCleanup.h @@ -333,7 +333,7 @@ public: Address getActiveFlag() const { return ActiveFlag; } - void setActiveFlag(Address Var) { + void setActiveFlag(RawAddress Var) { assert(Var.getAlignment().isOne()); ActiveFlag = Var; } diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index b7142ec08af986d16656fdb7e10aed35b98912d1..93ca711f716fce5bec80f56f81e0f3749de5d3f8 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -867,8 +867,8 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { EmitStmt(S.getPromiseDeclStmt()); Address PromiseAddr = GetAddrOfLocalVar(S.getPromiseDecl()); - auto *PromiseAddrVoidPtr = - new llvm::BitCastInst(PromiseAddr.getPointer(), VoidPtrTy, "", CoroId); + auto *PromiseAddrVoidPtr = new llvm::BitCastInst( + PromiseAddr.emitRawPointer(*this), VoidPtrTy, "", CoroId); // Update CoroId to refer to the promise. We could not do it earlier because // promise local variable was not emitted yet. CoroId->setArgOperand(1, PromiseAddrVoidPtr); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 07ecaa81c47d84999e7f0a37a2fd3ad5e6d6f8f8..2a385d85aa2bc3af4ac53e68f1bcce757a32d2e6 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1452,6 +1452,8 @@ static unsigned getDwarfCC(CallingConv CC) { return llvm::dwarf::DW_CC_LLVM_M68kRTD; case CC_PreserveNone: return llvm::dwarf::DW_CC_LLVM_PreserveNone; + case CC_RISCVVectorCall: + return llvm::dwarf::DW_CC_LLVM_RISCVVectorCall; } return 0; } @@ -3239,7 +3241,7 @@ llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) { // }; int64_t Count = -1; // Count == -1 is an unbounded array. if (const auto *CAT = dyn_cast(Ty)) - Count = CAT->getSize().getZExtValue(); + Count = CAT->getZExtSize(); else if (const auto *VAT = dyn_cast(Ty)) { if (Expr *Size = VAT->getSizeExpr()) { Expr::EvalResult Result; @@ -3463,6 +3465,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/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 2ef5ed04af30b6e99b59e2570e0c27da25500777..267f2e40a7bbaa198ed551bcc67702a38d783f11 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1461,7 +1461,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { bool EmitDebugInfo = DI && CGM.getCodeGenOpts().hasReducedDebugInfo(); Address address = Address::invalid(); - Address AllocaAddr = Address::invalid(); + RawAddress AllocaAddr = RawAddress::invalid(); Address OpenMPLocalAddr = Address::invalid(); if (CGM.getLangOpts().OpenMPIRBuilder) OpenMPLocalAddr = OMPBuilderCBHelpers::getAddressOfLocalVariable(*this, &D); @@ -1524,7 +1524,10 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // return slot, so that we can elide the copy when returning this // variable (C++0x [class.copy]p34). address = ReturnValue; - AllocaAddr = ReturnValue; + AllocaAddr = + RawAddress(ReturnValue.emitRawPointer(*this), + ReturnValue.getElementType(), ReturnValue.getAlignment()); + ; if (const RecordType *RecordTy = Ty->getAs()) { const auto *RD = RecordTy->getDecl(); @@ -1535,7 +1538,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // to this variable. Set it to zero to indicate that NRVO was not // applied. llvm::Value *Zero = Builder.getFalse(); - Address NRVOFlag = + RawAddress NRVOFlag = CreateTempAlloca(Zero->getType(), CharUnits::One(), "nrvo"); EnsureInsertPoint(); Builder.CreateStore(Zero, NRVOFlag); @@ -1678,7 +1681,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { } if (D.hasAttr() && HaveInsertPoint()) - EmitVarAnnotations(&D, address.getPointer()); + EmitVarAnnotations(&D, address.emitRawPointer(*this)); // Make sure we call @llvm.lifetime.end. if (emission.useLifetimeMarkers()) @@ -1851,12 +1854,13 @@ void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type, llvm::Value *BaseSizeInChars = llvm::ConstantInt::get(IntPtrTy, EltSize.getQuantity()); Address Begin = Loc.withElementType(Int8Ty); - llvm::Value *End = Builder.CreateInBoundsGEP( - Begin.getElementType(), Begin.getPointer(), SizeVal, "vla.end"); + llvm::Value *End = Builder.CreateInBoundsGEP(Begin.getElementType(), + Begin.emitRawPointer(*this), + SizeVal, "vla.end"); llvm::BasicBlock *OriginBB = Builder.GetInsertBlock(); EmitBlock(LoopBB); llvm::PHINode *Cur = Builder.CreatePHI(Begin.getType(), 2, "vla.cur"); - Cur->addIncoming(Begin.getPointer(), OriginBB); + Cur->addIncoming(Begin.emitRawPointer(*this), OriginBB); CharUnits CurAlign = Loc.getAlignment().alignmentOfArrayElement(EltSize); auto *I = Builder.CreateMemCpy(Address(Cur, Int8Ty, CurAlign), @@ -2283,7 +2287,7 @@ void CodeGenFunction::emitDestroy(Address addr, QualType type, checkZeroLength = false; } - llvm::Value *begin = addr.getPointer(); + llvm::Value *begin = addr.emitRawPointer(*this); llvm::Value *end = Builder.CreateInBoundsGEP(addr.getElementType(), begin, length); emitArrayDestroy(begin, end, type, elementAlign, destroyer, @@ -2543,7 +2547,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, } Address DeclPtr = Address::invalid(); - Address AllocaPtr = Address::invalid(); + RawAddress AllocaPtr = Address::invalid(); bool DoStore = false; bool IsScalar = hasScalarEvaluationKind(Ty); bool UseIndirectDebugAddress = false; @@ -2555,8 +2559,8 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, // Indirect argument is in alloca address space, which may be different // from the default address space. auto AllocaAS = CGM.getASTAllocaAddressSpace(); - auto *V = DeclPtr.getPointer(); - AllocaPtr = DeclPtr; + auto *V = DeclPtr.emitRawPointer(*this); + AllocaPtr = RawAddress(V, DeclPtr.getElementType(), DeclPtr.getAlignment()); // For truly ABI indirect arguments -- those that are not `byval` -- store // the address of the argument on the stack to preserve debug information. @@ -2695,7 +2699,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, } if (D.hasAttr()) - EmitVarAnnotations(&D, DeclPtr.getPointer()); + EmitVarAnnotations(&D, DeclPtr.emitRawPointer(*this)); // We can only check return value nullability if all arguments to the // function satisfy their nullability preconditions. This makes it necessary diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 5a9d06da12de571ab376e8740b06fd63ac66cc9f..34f289334a7df90584d9b7f80bf57a99060a7af0 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -397,7 +397,7 @@ namespace { void CodeGenFunction::EmitAnyExprToExn(const Expr *e, Address addr) { // Make sure the exception object is cleaned up if there's an // exception during initialization. - pushFullExprCleanup(EHCleanup, addr.getPointer()); + pushFullExprCleanup(EHCleanup, addr.emitRawPointer(*this)); EHScopeStack::stable_iterator cleanup = EHStack.stable_begin(); // __cxa_allocate_exception returns a void*; we need to cast this @@ -416,8 +416,8 @@ void CodeGenFunction::EmitAnyExprToExn(const Expr *e, Address addr) { /*IsInit*/ true); // Deactivate the cleanup block. - DeactivateCleanupBlock(cleanup, - cast(typedAddr.getPointer())); + DeactivateCleanupBlock( + cleanup, cast(typedAddr.emitRawPointer(*this))); } Address CodeGenFunction::getExceptionSlot() { @@ -1834,7 +1834,8 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, llvm::Value *ParentFP) { llvm::CallInst *RecoverCall = nullptr; CGBuilderTy Builder(*this, AllocaInsertPt); - if (auto *ParentAlloca = dyn_cast(ParentVar.getPointer())) { + if (auto *ParentAlloca = + dyn_cast_or_null(ParentVar.getBasePointer())) { // Mark the variable escaped if nobody else referenced it and compute the // localescape index. auto InsertPair = ParentCGF.EscapedLocals.insert( @@ -1851,8 +1852,8 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, // If the parent didn't have an alloca, we're doing some nested outlining. // Just clone the existing localrecover call, but tweak the FP argument to // use our FP value. All other arguments are constants. - auto *ParentRecover = - cast(ParentVar.getPointer()->stripPointerCasts()); + auto *ParentRecover = cast( + ParentVar.emitRawPointer(*this)->stripPointerCasts()); assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::localrecover && "expected alloca or localrecover in parent LocalDeclMap"); RecoverCall = cast(ParentRecover->clone()); @@ -1925,7 +1926,8 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, if (isa(D) && D->getType() == getContext().VoidPtrTy) { assert(D->getName().starts_with("frame_pointer")); - FramePtrAddrAlloca = cast(I.second.getPointer()); + FramePtrAddrAlloca = + cast(I.second.getBasePointer()); break; } } @@ -1986,7 +1988,8 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, LValue ThisFieldLValue = EmitLValueForLambdaField(LambdaThisCaptureField); if (!LambdaThisCaptureField->getType()->isPointerType()) { - CXXThisValue = ThisFieldLValue.getAddress(*this).getPointer(); + CXXThisValue = + ThisFieldLValue.getAddress(*this).emitRawPointer(*this); } else { CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation()) .getScalarVal(); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 85f5d739cef457a49d143d33c6689efe82b48696..36872c0fedb76ec22cf9be5d36927b0c79fe8b77 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -65,21 +65,21 @@ static llvm::cl::opt ClSanitizeDebugDeoptimization( /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. -Address CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, - CharUnits Align, - const Twine &Name, - llvm::Value *ArraySize) { +RawAddress +CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits Align, + const Twine &Name, + llvm::Value *ArraySize) { auto Alloca = CreateTempAlloca(Ty, Name, ArraySize); Alloca->setAlignment(Align.getAsAlign()); - return Address(Alloca, Ty, Align, KnownNonNull); + return RawAddress(Alloca, Ty, Align, KnownNonNull); } /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. The alloca is casted to default address space if necessary. -Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, - const Twine &Name, - llvm::Value *ArraySize, - Address *AllocaAddr) { +RawAddress CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, + const Twine &Name, + llvm::Value *ArraySize, + RawAddress *AllocaAddr) { auto Alloca = CreateTempAllocaWithoutCast(Ty, Align, Name, ArraySize); if (AllocaAddr) *AllocaAddr = Alloca; @@ -101,7 +101,7 @@ Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, Ty->getPointerTo(DestAddrSpace), /*non-null*/ true); } - return Address(V, Ty, Align, KnownNonNull); + return RawAddress(V, Ty, Align, KnownNonNull); } /// CreateTempAlloca - This creates an alloca and inserts it into the entry @@ -120,28 +120,29 @@ llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, /// default alignment of the corresponding LLVM type, which is *not* /// guaranteed to be related in any way to the expected alignment of /// an AST type that might have been lowered to Ty. -Address CodeGenFunction::CreateDefaultAlignTempAlloca(llvm::Type *Ty, - const Twine &Name) { +RawAddress CodeGenFunction::CreateDefaultAlignTempAlloca(llvm::Type *Ty, + const Twine &Name) { CharUnits Align = CharUnits::fromQuantity(CGM.getDataLayout().getPrefTypeAlign(Ty)); return CreateTempAlloca(Ty, Align, Name); } -Address CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) { +RawAddress CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) { CharUnits Align = getContext().getTypeAlignInChars(Ty); return CreateTempAlloca(ConvertType(Ty), Align, Name); } -Address CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name, - Address *Alloca) { +RawAddress CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name, + RawAddress *Alloca) { // FIXME: Should we prefer the preferred type alignment here? return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name, Alloca); } -Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, - const Twine &Name, Address *Alloca) { - Address Result = CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, - /*ArraySize=*/nullptr, Alloca); +RawAddress CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, + const Twine &Name, + RawAddress *Alloca) { + RawAddress Result = CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, + /*ArraySize=*/nullptr, Alloca); if (Ty->isConstantMatrixType()) { auto *ArrayTy = cast(Result.getElementType()); @@ -154,13 +155,14 @@ Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, return Result; } -Address CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, CharUnits Align, - const Twine &Name) { +RawAddress CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, + CharUnits Align, + const Twine &Name) { return CreateTempAllocaWithoutCast(ConvertTypeForMem(Ty), Align, Name); } -Address CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, - const Twine &Name) { +RawAddress CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, + const Twine &Name) { return CreateMemTempWithoutCast(Ty, getContext().getTypeAlignInChars(Ty), Name); } @@ -359,7 +361,7 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, } else { CleanupFn = CGF.CGM.getAddrAndTypeOfCXXStructor( GlobalDecl(ReferenceTemporaryDtor, Dtor_Complete)); - CleanupArg = cast(ReferenceTemporary.getPointer()); + CleanupArg = cast(ReferenceTemporary.emitRawPointer(CGF)); } CGF.CGM.getCXXABI().registerGlobalDtor( CGF, *cast(M->getExtendingDecl()), CleanupFn, CleanupArg); @@ -384,10 +386,10 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, } } -static Address createReferenceTemporary(CodeGenFunction &CGF, - const MaterializeTemporaryExpr *M, - const Expr *Inner, - Address *Alloca = nullptr) { +static RawAddress createReferenceTemporary(CodeGenFunction &CGF, + const MaterializeTemporaryExpr *M, + const Expr *Inner, + RawAddress *Alloca = nullptr) { auto &TCG = CGF.getTargetHooks(); switch (M->getStorageDuration()) { case SD_FullExpression: @@ -416,7 +418,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF, GV->getValueType()->getPointerTo( CGF.getContext().getTargetAddressSpace(LangAS::Default))); // FIXME: Should we put the new global into a COMDAT? - return Address(C, GV->getValueType(), alignment); + return RawAddress(C, GV->getValueType(), alignment); } return CGF.CreateMemTemp(Ty, "ref.tmp", Alloca); } @@ -448,7 +450,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { auto ownership = M->getType().getObjCLifetime(); if (ownership != Qualifiers::OCL_None && ownership != Qualifiers::OCL_ExplicitNone) { - Address Object = createReferenceTemporary(*this, M, E); + RawAddress Object = createReferenceTemporary(*this, M, E); if (auto *Var = dyn_cast(Object.getPointer())) { llvm::Type *Ty = ConvertTypeForMem(E->getType()); Object = Object.withElementType(Ty); @@ -502,8 +504,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { } // Create and initialize the reference temporary. - Address Alloca = Address::invalid(); - Address Object = createReferenceTemporary(*this, M, E, &Alloca); + RawAddress Alloca = Address::invalid(); + RawAddress Object = createReferenceTemporary(*this, M, E, &Alloca); if (auto *Var = dyn_cast( Object.getPointer()->stripPointerCasts())) { llvm::Type *TemporaryType = ConvertTypeForMem(E->getType()); @@ -1111,12 +1113,12 @@ llvm::Value *CodeGenFunction::EmitCountedByFieldExpr( } else if (const MemberExpr *ME = dyn_cast(StructBase)) { LValue LV = EmitMemberExpr(ME); Address Addr = LV.getAddress(*this); - Res = Addr.getPointer(); + Res = Addr.emitRawPointer(*this); } else if (StructBase->getType()->isPointerType()) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; Address Addr = EmitPointerWithAlignment(StructBase, &BaseInfo, &TBAAInfo); - Res = Addr.getPointer(); + Res = Addr.emitRawPointer(*this); } else { return nullptr; } @@ -1282,8 +1284,7 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, if (InnerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) { if (BaseInfo) BaseInfo->mergeForCast(TargetTypeBaseInfo); - Addr = Address(Addr.getPointer(), Addr.getElementType(), Align, - IsKnownNonNull); + Addr.setAlignment(Align); } } @@ -1300,8 +1301,8 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, CGF.ConvertTypeForMem(E->getType()->getPointeeType()); Addr = Addr.withElementType(ElemTy); if (CE->getCastKind() == CK_AddressSpaceConversion) - Addr = CGF.Builder.CreateAddrSpaceCast(Addr, - CGF.ConvertType(E->getType())); + Addr = CGF.Builder.CreateAddrSpaceCast( + Addr, CGF.ConvertType(E->getType()), ElemTy); return Addr; } break; @@ -1364,10 +1365,9 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, // TODO: conditional operators, comma. // Otherwise, use the alignment of the type. - CharUnits Align = - CGF.CGM.getNaturalPointeeTypeAlignment(E->getType(), BaseInfo, TBAAInfo); - llvm::Type *ElemTy = CGF.ConvertTypeForMem(E->getType()->getPointeeType()); - return Address(CGF.EmitScalarExpr(E), ElemTy, Align, IsKnownNonNull); + return CGF.makeNaturalAddressForPointer( + CGF.EmitScalarExpr(E), E->getType()->getPointeeType(), CharUnits(), + /*ForPointeeType=*/true, BaseInfo, TBAAInfo, IsKnownNonNull); } /// EmitPointerWithAlignment - Given an expression of pointer type, try to @@ -1468,8 +1468,7 @@ LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) { if (IsBaseCXXThis || isa(ME->getBase())) SkippedChecks.set(SanitizerKind::Null, true); } - EmitTypeCheck(TCK, E->getExprLoc(), LV.getPointer(*this), E->getType(), - LV.getAlignment(), SkippedChecks); + EmitTypeCheck(TCK, E->getExprLoc(), LV, E->getType(), SkippedChecks); } return LV; } @@ -1581,11 +1580,11 @@ LValue CodeGenFunction::EmitLValueHelper(const Expr *E, // Defend against branches out of gnu statement expressions surrounded by // cleanups. Address Addr = LV.getAddress(*this); - llvm::Value *V = Addr.getPointer(); + llvm::Value *V = Addr.getBasePointer(); Scope.ForceCleanup({&V}); - return LValue::MakeAddr(Addr.withPointer(V, Addr.isKnownNonNull()), - LV.getType(), getContext(), LV.getBaseInfo(), - LV.getTBAAInfo()); + Addr.replaceBasePointer(V); + return LValue::MakeAddr(Addr, LV.getType(), getContext(), + LV.getBaseInfo(), LV.getTBAAInfo()); } // FIXME: Is it possible to create an ExprWithCleanups that produces a // bitfield lvalue or some other non-simple lvalue? @@ -1929,7 +1928,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, bool isNontemporal) { - if (auto *GV = dyn_cast(Addr.getPointer())) + if (auto *GV = dyn_cast(Addr.getBasePointer())) if (GV->isThreadLocal()) Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV), NotKnownNonNull); @@ -2039,8 +2038,9 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) { // Convert the pointer of \p Addr to a pointer to a vector (the value type of // MatrixType), if it points to a array (the memory type of MatrixType). -static Address MaybeConvertMatrixAddress(Address Addr, CodeGenFunction &CGF, - bool IsVector = true) { +static RawAddress MaybeConvertMatrixAddress(RawAddress Addr, + CodeGenFunction &CGF, + bool IsVector = true) { auto *ArrayTy = dyn_cast(Addr.getElementType()); if (ArrayTy && IsVector) { auto *VectorTy = llvm::FixedVectorType::get(ArrayTy->getElementType(), @@ -2077,7 +2077,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, bool isInit, bool isNontemporal) { - if (auto *GV = dyn_cast(Addr.getPointer())) + if (auto *GV = dyn_cast(Addr.getBasePointer())) if (GV->isThreadLocal()) Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV), NotKnownNonNull); @@ -2432,14 +2432,12 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, assert(Dst.getBaseIvarExp() && "BaseIvarExp is NULL"); llvm::Type *ResultType = IntPtrTy; Address dst = EmitPointerWithAlignment(Dst.getBaseIvarExp()); - llvm::Value *RHS = dst.getPointer(); + llvm::Value *RHS = dst.emitRawPointer(*this); RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast"); - llvm::Value *LHS = - Builder.CreatePtrToInt(LvalueDst.getPointer(), ResultType, - "sub.ptr.lhs.cast"); + llvm::Value *LHS = Builder.CreatePtrToInt(LvalueDst.emitRawPointer(*this), + ResultType, "sub.ptr.lhs.cast"); llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset"); - CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, - BytesBetween); + CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, BytesBetween); } else if (Dst.isGlobalObjCRef()) { CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst, Dst.isThreadLocalRef()); @@ -2770,12 +2768,9 @@ CodeGenFunction::EmitLoadOfReference(LValue RefLVal, llvm::LoadInst *Load = Builder.CreateLoad(RefLVal.getAddress(*this), RefLVal.isVolatile()); CGM.DecorateInstructionWithTBAA(Load, RefLVal.getTBAAInfo()); - - QualType PointeeType = RefLVal.getType()->getPointeeType(); - CharUnits Align = CGM.getNaturalTypeAlignment( - PointeeType, PointeeBaseInfo, PointeeTBAAInfo, - /* forPointeeType= */ true); - return Address(Load, ConvertTypeForMem(PointeeType), Align); + return makeNaturalAddressForPointer(Load, RefLVal.getType()->getPointeeType(), + CharUnits(), /*ForPointeeType=*/true, + PointeeBaseInfo, PointeeTBAAInfo); } LValue CodeGenFunction::EmitLoadOfReferenceLValue(LValue RefLVal) { @@ -2792,10 +2787,9 @@ Address CodeGenFunction::EmitLoadOfPointer(Address Ptr, LValueBaseInfo *BaseInfo, TBAAAccessInfo *TBAAInfo) { llvm::Value *Addr = Builder.CreateLoad(Ptr); - return Address(Addr, ConvertTypeForMem(PtrTy->getPointeeType()), - CGM.getNaturalTypeAlignment(PtrTy->getPointeeType(), BaseInfo, - TBAAInfo, - /*forPointeeType=*/true)); + return makeNaturalAddressForPointer(Addr, PtrTy->getPointeeType(), + CharUnits(), /*ForPointeeType=*/true, + BaseInfo, TBAAInfo); } LValue CodeGenFunction::EmitLoadOfPointerLValue(Address PtrAddr, @@ -2991,7 +2985,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { /* BaseInfo= */ nullptr, /* TBAAInfo= */ nullptr, /* forPointeeType= */ true); - Addr = Address(Val, ConvertTypeForMem(E->getType()), Alignment); + Addr = makeNaturalAddressForPointer(Val, T, Alignment); } return MakeAddrLValue(Addr, T, AlignmentSource::Decl); } @@ -3023,11 +3017,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD), CapturedStmtInfo->getContextValue()); Address LValueAddress = CapLVal.getAddress(*this); - CapLVal = MakeAddrLValue( - Address(LValueAddress.getPointer(), LValueAddress.getElementType(), - getContext().getDeclAlign(VD)), - CapLVal.getType(), LValueBaseInfo(AlignmentSource::Decl), - CapLVal.getTBAAInfo()); + CapLVal = MakeAddrLValue(Address(LValueAddress.emitRawPointer(*this), + LValueAddress.getElementType(), + getContext().getDeclAlign(VD)), + CapLVal.getType(), + LValueBaseInfo(AlignmentSource::Decl), + CapLVal.getTBAAInfo()); // Mark lvalue as nontemporal if the variable is marked as nontemporal // in simd context. if (getLangOpts().OpenMP && @@ -3083,7 +3078,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { // Handle threadlocal function locals. if (VD->getTLSKind() != VarDecl::TLS_None) addr = addr.withPointer( - Builder.CreateThreadLocalAddress(addr.getPointer()), NotKnownNonNull); + Builder.CreateThreadLocalAddress(addr.getBasePointer()), + NotKnownNonNull); // Check for OpenMP threadprivate variables. if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd && @@ -3351,7 +3347,7 @@ llvm::Value *CodeGenFunction::EmitCheckValue(llvm::Value *V) { // Pointers are passed directly, everything else is passed by address. if (!V->getType()->isPointerTy()) { - Address Ptr = CreateDefaultAlignTempAlloca(V->getType()); + RawAddress Ptr = CreateDefaultAlignTempAlloca(V->getType()); Builder.CreateStore(V, Ptr); V = Ptr.getPointer(); } @@ -3663,12 +3659,29 @@ void CodeGenFunction::EmitCfiSlowPathCheck( // symbol in LTO mode. void CodeGenFunction::EmitCfiCheckStub() { llvm::Module *M = &CGM.getModule(); - auto &Ctx = M->getContext(); + ASTContext &C = getContext(); + QualType QInt64Ty = C.getIntTypeForBitwidth(64, false); + + FunctionArgList FnArgs; + ImplicitParamDecl ArgCallsiteTypeId(C, QInt64Ty, ImplicitParamKind::Other); + ImplicitParamDecl ArgAddr(C, C.VoidPtrTy, ImplicitParamKind::Other); + ImplicitParamDecl ArgCFICheckFailData(C, C.VoidPtrTy, + ImplicitParamKind::Other); + FnArgs.push_back(&ArgCallsiteTypeId); + FnArgs.push_back(&ArgAddr); + FnArgs.push_back(&ArgCFICheckFailData); + const CGFunctionInfo &FI = + CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, FnArgs); + llvm::Function *F = llvm::Function::Create( - llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy}, false), + llvm::FunctionType::get(VoidTy, {Int64Ty, VoidPtrTy, VoidPtrTy}, false), llvm::GlobalValue::WeakAnyLinkage, "__cfi_check", M); + CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false); + CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F); F->setAlignment(llvm::Align(4096)); CGM.setDSOLocal(F); + + llvm::LLVMContext &Ctx = M->getContext(); llvm::BasicBlock *BB = llvm::BasicBlock::Create(Ctx, "entry", F); // CrossDSOCFI pass is not executed if there is no executable code. SmallVector Args{F->getArg(2), F->getArg(1)}; @@ -3907,6 +3920,21 @@ static llvm::Value *emitArraySubscriptGEP(CodeGenFunction &CGF, } } +static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, + ArrayRef indices, + llvm::Type *elementType, bool inbounds, + bool signedIndices, SourceLocation loc, + CharUnits align, + const llvm::Twine &name = "arrayidx") { + if (inbounds) { + return CGF.EmitCheckedInBoundsGEP(addr, indices, elementType, signedIndices, + CodeGenFunction::NotSubtraction, loc, + align, name); + } else { + return CGF.Builder.CreateGEP(addr, indices, elementType, align, name); + } +} + static CharUnits getArrayElementAlign(CharUnits arrayAlign, llvm::Value *idx, CharUnits eltSize) { @@ -3954,7 +3982,7 @@ static Address wrapWithBPFPreserveStaticOffset(CodeGenFunction &CGF, llvm::Function *Fn = CGF.CGM.getIntrinsic(llvm::Intrinsic::preserve_static_offset); - llvm::CallInst *Call = CGF.Builder.CreateCall(Fn, {Addr.getPointer()}); + llvm::CallInst *Call = CGF.Builder.CreateCall(Fn, {Addr.emitRawPointer(CGF)}); return Address(Call, Addr.getElementType(), Addr.getAlignment()); } @@ -4017,7 +4045,7 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, // We can use that to compute the best alignment of the element. CharUnits eltSize = CGF.getContext().getTypeSizeInChars(eltType); CharUnits eltAlign = - getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); + getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); if (hasBPFPreserveStaticOffset(Base)) addr = wrapWithBPFPreserveStaticOffset(CGF, addr); @@ -4026,19 +4054,19 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, auto LastIndex = dyn_cast(indices.back()); if (!LastIndex || (!CGF.IsInPreservedAIRegion && !IsPreserveAIArrayBase(CGF, Base))) { - eltPtr = emitArraySubscriptGEP( - CGF, addr.getElementType(), addr.getPointer(), indices, inbounds, - signedIndices, loc, name); + addr = emitArraySubscriptGEP(CGF, addr, indices, + CGF.ConvertTypeForMem(eltType), inbounds, + signedIndices, loc, eltAlign, name); + return addr; } else { // Remember the original array subscript for bpf target unsigned idx = LastIndex->getZExtValue(); llvm::DIType *DbgInfo = nullptr; if (arrayType) DbgInfo = CGF.getDebugInfo()->getOrCreateStandaloneType(*arrayType, loc); - eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex(addr.getElementType(), - addr.getPointer(), - indices.size() - 1, - idx, DbgInfo); + eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex( + addr.getElementType(), addr.emitRawPointer(CGF), indices.size() - 1, + idx, DbgInfo); } return Address(eltPtr, CGF.ConvertTypeForMem(eltType), eltAlign); @@ -4207,8 +4235,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, CharUnits EltAlign = getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize); llvm::Value *EltPtr = - emitArraySubscriptGEP(*this, Int8Ty, Addr.getPointer(), ScaledIdx, - false, SignedIndices, E->getExprLoc()); + emitArraySubscriptGEP(*this, Int8Ty, Addr.emitRawPointer(*this), + ScaledIdx, false, SignedIndices, E->getExprLoc()); Addr = Address(EltPtr, OrigBaseElemTy, EltAlign); } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) { // If this is A[i] where A is an array, the frontend will have decayed the @@ -4254,7 +4282,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, llvm::Type *CountTy = ConvertType(CountFD->getType()); llvm::Value *Res = Builder.CreateInBoundsGEP( - Int8Ty, Addr.getPointer(), + Int8Ty, Addr.emitRawPointer(*this), Builder.getInt32(OffsetDiff.getQuantity()), ".counted_by.gep"); Res = Builder.CreateAlignedLoad(CountTy, Res, getIntAlign(), ".counted_by.load"); @@ -4500,9 +4528,9 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, BaseInfo = ArrayLV.getBaseInfo(); TBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, ResultExprTy); } else { - Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, - TBAAInfo, BaseTy, ResultExprTy, - IsLowerBound); + Address Base = + emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, TBAAInfo, BaseTy, + ResultExprTy, IsLowerBound); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy, !getLangOpts().isSignedOverflowDefined(), /*signedIndices=*/false, E->getExprLoc()); @@ -4589,7 +4617,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { SkippedChecks.set(SanitizerKind::Alignment, true); if (IsBaseCXXThis || isa(BaseExpr)) SkippedChecks.set(SanitizerKind::Null, true); - EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy, + EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr, PtrTy, /*Alignment=*/CharUnits::Zero(), SkippedChecks); BaseLV = MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo); } else @@ -4638,8 +4666,8 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field, LambdaLV = EmitLoadOfReferenceLValue(AddrOfExplicitObject, D->getType(), AlignmentSource::Decl); else - LambdaLV = MakeNaturalAlignAddrLValue(AddrOfExplicitObject.getPointer(), - D->getType().getNonReferenceType()); + LambdaLV = MakeAddrLValue(AddrOfExplicitObject, + D->getType().getNonReferenceType()); } else { QualType LambdaTagType = getContext().getTagDeclType(Field->getParent()); LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType); @@ -4829,7 +4857,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, // information provided by invariant.group. This is because accessing // fields may leak the real address of dynamic object, which could result // in miscompilation when leaked pointer would be compared. - auto *stripped = Builder.CreateStripInvariantGroup(addr.getPointer()); + auto *stripped = + Builder.CreateStripInvariantGroup(addr.emitRawPointer(*this)); addr = Address(stripped, addr.getElementType(), addr.getAlignment()); } } @@ -4848,10 +4877,11 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, // Remember the original union field index llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateStandaloneType(base.getType(), rec->getLocation()); - addr = Address( - Builder.CreatePreserveUnionAccessIndex( - addr.getPointer(), getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo), - addr.getElementType(), addr.getAlignment()); + addr = + Address(Builder.CreatePreserveUnionAccessIndex( + addr.emitRawPointer(*this), + getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo), + addr.getElementType(), addr.getAlignment()); } if (FieldType->isReferenceType()) @@ -5088,11 +5118,9 @@ LValue CodeGenFunction::EmitConditionalOperatorLValue( if (Info.LHS && Info.RHS) { Address lhsAddr = Info.LHS->getAddress(*this); Address rhsAddr = Info.RHS->getAddress(*this); - llvm::PHINode *phi = Builder.CreatePHI(lhsAddr.getType(), 2, "cond-lvalue"); - phi->addIncoming(lhsAddr.getPointer(), Info.lhsBlock); - phi->addIncoming(rhsAddr.getPointer(), Info.rhsBlock); - Address result(phi, lhsAddr.getElementType(), - std::min(lhsAddr.getAlignment(), rhsAddr.getAlignment())); + Address result = mergeAddressesInConditionalExpr( + lhsAddr, rhsAddr, Info.lhsBlock, Info.rhsBlock, + Builder.GetInsertBlock(), expr->getType()); AlignmentSource alignSource = std::max(Info.LHS->getBaseInfo().getAlignmentSource(), Info.RHS->getBaseInfo().getAlignmentSource()); @@ -5179,7 +5207,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { LValue LV = EmitLValue(E->getSubExpr()); Address V = LV.getAddress(*this); const auto *DCE = cast(E); - return MakeNaturalAlignAddrLValue(EmitDynamicCast(V, DCE), E->getType()); + return MakeNaturalAlignRawAddrLValue(EmitDynamicCast(V, DCE), E->getType()); } case CK_ConstructorConversion: @@ -5244,8 +5272,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { // C++11 [expr.static.cast]p2: Behavior is undefined if a downcast is // performed and the object is not of the derived type. if (sanitizePerformTypeCheck()) - EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(), - Derived.getPointer(), E->getType()); + EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(), Derived, + E->getType()); if (SanOpts.has(SanitizerKind::CFIDerivedCast)) EmitVTablePtrCheckForCast(E->getType(), Derived, @@ -5601,7 +5629,7 @@ LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) { LValue CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) { - return MakeNaturalAlignAddrLValue(EmitCXXTypeidExpr(E), E->getType()); + return MakeNaturalAlignRawAddrLValue(EmitCXXTypeidExpr(E), E->getType()); } Address CodeGenFunction::EmitCXXUuidofExpr(const CXXUuidofExpr *E) { diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 5190b22bcc162254b09ef81bae7f7f3d7deb0502..143855aa84ca3f8f5cdea4cf2ea60a7a1be68bd2 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -294,10 +294,10 @@ void AggExprEmitter::withReturnValueSlot( // Otherwise, EmitCall will emit its own, notice that it's "unused", and end // its lifetime before we have the chance to emit a proper destructor call. bool UseTemp = Dest.isPotentiallyAliased() || Dest.requiresGCollection() || - (RequiresDestruction && !Dest.getAddress().isValid()); + (RequiresDestruction && Dest.isIgnored()); Address RetAddr = Address::invalid(); - Address RetAllocaAddr = Address::invalid(); + RawAddress RetAllocaAddr = RawAddress::invalid(); EHScopeStack::stable_iterator LifetimeEndBlock; llvm::Value *LifetimeSizePtr = nullptr; @@ -329,7 +329,8 @@ void AggExprEmitter::withReturnValueSlot( if (!UseTemp) return; - assert(Dest.isIgnored() || Dest.getPointer() != Src.getAggregatePointer()); + assert(Dest.isIgnored() || Dest.emitRawPointer(CGF) != + Src.getAggregatePointer(E->getType(), CGF)); EmitFinalDestCopy(E->getType(), Src); if (!RequiresDestruction && LifetimeStartInst) { @@ -448,7 +449,8 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0); llvm::Value *IdxStart[] = { Zero, Zero }; llvm::Value *ArrayStart = Builder.CreateInBoundsGEP( - ArrayPtr.getElementType(), ArrayPtr.getPointer(), IdxStart, "arraystart"); + ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxStart, + "arraystart"); CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start); ++Field; @@ -465,7 +467,8 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { // End pointer. llvm::Value *IdxEnd[] = { Zero, Size }; llvm::Value *ArrayEnd = Builder.CreateInBoundsGEP( - ArrayPtr.getElementType(), ArrayPtr.getPointer(), IdxEnd, "arrayend"); + ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxEnd, + "arrayend"); CGF.EmitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength); } else if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) { // Length. @@ -516,9 +519,9 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, // down a level. llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); llvm::Value *indices[] = { zero, zero }; - llvm::Value *begin = Builder.CreateInBoundsGEP( - DestPtr.getElementType(), DestPtr.getPointer(), indices, - "arrayinit.begin"); + llvm::Value *begin = Builder.CreateInBoundsGEP(DestPtr.getElementType(), + DestPtr.emitRawPointer(CGF), + indices, "arrayinit.begin"); CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType); CharUnits elementAlign = @@ -1059,7 +1062,7 @@ void AggExprEmitter::VisitBinCmp(const BinaryOperator *E) { if (RV.isScalar()) return {RV.getScalarVal(), nullptr}; if (RV.isAggregate()) - return {RV.getAggregatePointer(), nullptr}; + return {RV.getAggregatePointer(E->getType(), CGF), nullptr}; assert(RV.isComplex()); return RV.getComplexVal(); }; @@ -1818,7 +1821,7 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr( // else, clean it up for -O0 builds and general tidiness. if (!pushedCleanup && LV.isSimple()) if (llvm::GetElementPtrInst *GEP = - dyn_cast(LV.getPointer(CGF))) + dyn_cast(LV.emitRawPointer(CGF))) if (GEP->use_empty()) GEP->eraseFromParent(); } @@ -1849,9 +1852,9 @@ void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E, // destPtr is an array*. Construct an elementType* by drilling down a level. llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); llvm::Value *indices[] = {zero, zero}; - llvm::Value *begin = Builder.CreateInBoundsGEP( - destPtr.getElementType(), destPtr.getPointer(), indices, - "arrayinit.begin"); + llvm::Value *begin = Builder.CreateInBoundsGEP(destPtr.getElementType(), + destPtr.emitRawPointer(CGF), + indices, "arrayinit.begin"); // Prepare to special-case multidimensional array initialization: we avoid // emitting multiple destructor loops in that case. diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 2adbef6d55122c973a195260ad218354723ff035..5c16a48d3ee6d6ff32c98df47c4f66fb57eda555 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -280,7 +280,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; Address ThisValue = EmitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo); - This = MakeAddrLValue(ThisValue, Base->getType(), BaseInfo, TBAAInfo); + This = MakeAddrLValue(ThisValue, Base->getType()->getPointeeType(), + BaseInfo, TBAAInfo); } else { This = EmitLValue(Base); } @@ -353,10 +354,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( if (IsImplicitObjectCXXThis || isa(IOA)) SkippedChecks.set(SanitizerKind::Null, true); } - EmitTypeCheck(CodeGenFunction::TCK_MemberCall, CallLoc, - This.getPointer(*this), - C.getRecordType(CalleeDecl->getParent()), - /*Alignment=*/CharUnits::Zero(), SkippedChecks); + EmitTypeCheck(CodeGenFunction::TCK_MemberCall, CallLoc, This, + C.getRecordType(CalleeDecl->getParent()), SkippedChecks); // C++ [class.virtual]p12: // Explicit qualification with the scope operator (5.1) suppresses the @@ -455,7 +454,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, else This = EmitLValue(BaseExpr, KnownNonNull).getAddress(*this); - EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.getPointer(), + EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.emitRawPointer(*this), QualType(MPT->getClass(), 0)); // Get the member function pointer. @@ -1073,8 +1072,7 @@ void CodeGenFunction::EmitNewArrayInitializer( // Move past these elements. InitListElements = cast(Init->getType()->getAsArrayTypeUnsafe()) - ->getSize() - .getZExtValue(); + ->getZExtSize(); CurPtr = Builder.CreateConstInBoundsGEP( CurPtr, InitListElements, "string.init.end"); @@ -1110,9 +1108,10 @@ void CodeGenFunction::EmitNewArrayInitializer( // alloca. EndOfInit = CreateTempAlloca(BeginPtr.getType(), getPointerAlign(), "array.init.end"); - CleanupDominator = Builder.CreateStore(BeginPtr.getPointer(), EndOfInit); - pushIrregularPartialArrayCleanup(BeginPtr.getPointer(), EndOfInit, - ElementType, ElementAlign, + CleanupDominator = + Builder.CreateStore(BeginPtr.emitRawPointer(*this), EndOfInit); + pushIrregularPartialArrayCleanup(BeginPtr.emitRawPointer(*this), + EndOfInit, ElementType, ElementAlign, getDestroyer(DtorKind)); Cleanup = EHStack.stable_begin(); } @@ -1124,16 +1123,17 @@ void CodeGenFunction::EmitNewArrayInitializer( // element. TODO: some of these stores can be trivially // observed to be unnecessary. if (EndOfInit.isValid()) { - Builder.CreateStore(CurPtr.getPointer(), EndOfInit); + Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); } // FIXME: If the last initializer is an incomplete initializer list for // an array, and we have an array filler, we can fold together the two // initialization loops. StoreAnyExprIntoOneUnit(*this, IE, IE->getType(), CurPtr, AggValueSlot::DoesNotOverlap); - CurPtr = Address(Builder.CreateInBoundsGEP( - CurPtr.getElementType(), CurPtr.getPointer(), - Builder.getSize(1), "array.exp.next"), + CurPtr = Address(Builder.CreateInBoundsGEP(CurPtr.getElementType(), + CurPtr.emitRawPointer(*this), + Builder.getSize(1), + "array.exp.next"), CurPtr.getElementType(), StartAlign.alignmentAtOffset((++i) * ElementSize)); } @@ -1187,7 +1187,7 @@ void CodeGenFunction::EmitNewArrayInitializer( // FIXME: Share this cleanup with the constructor call emission rather than // having it create a cleanup of its own. if (EndOfInit.isValid()) - Builder.CreateStore(CurPtr.getPointer(), EndOfInit); + Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); // Emit a constructor call loop to initialize the remaining elements. if (InitListElements) @@ -1250,15 +1250,15 @@ void CodeGenFunction::EmitNewArrayInitializer( llvm::BasicBlock *ContBB = createBasicBlock("new.loop.end"); // Find the end of the array, hoisted out of the loop. - llvm::Value *EndPtr = - Builder.CreateInBoundsGEP(BeginPtr.getElementType(), BeginPtr.getPointer(), - NumElements, "array.end"); + llvm::Value *EndPtr = Builder.CreateInBoundsGEP( + BeginPtr.getElementType(), BeginPtr.emitRawPointer(*this), NumElements, + "array.end"); // If the number of elements isn't constant, we have to now check if there is // anything left to initialize. if (!ConstNum) { - llvm::Value *IsEmpty = - Builder.CreateICmpEQ(CurPtr.getPointer(), EndPtr, "array.isempty"); + llvm::Value *IsEmpty = Builder.CreateICmpEQ(CurPtr.emitRawPointer(*this), + EndPtr, "array.isempty"); Builder.CreateCondBr(IsEmpty, ContBB, LoopBB); } @@ -1268,19 +1268,20 @@ void CodeGenFunction::EmitNewArrayInitializer( // Set up the current-element phi. llvm::PHINode *CurPtrPhi = Builder.CreatePHI(CurPtr.getType(), 2, "array.cur"); - CurPtrPhi->addIncoming(CurPtr.getPointer(), EntryBB); + CurPtrPhi->addIncoming(CurPtr.emitRawPointer(*this), EntryBB); CurPtr = Address(CurPtrPhi, CurPtr.getElementType(), ElementAlign); // Store the new Cleanup position for irregular Cleanups. if (EndOfInit.isValid()) - Builder.CreateStore(CurPtr.getPointer(), EndOfInit); + Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); // Enter a partial-destruction Cleanup if necessary. if (!CleanupDominator && needsEHCleanup(DtorKind)) { - pushRegularPartialArrayCleanup(BeginPtr.getPointer(), CurPtr.getPointer(), - ElementType, ElementAlign, - getDestroyer(DtorKind)); + llvm::Value *BeginPtrRaw = BeginPtr.emitRawPointer(*this); + llvm::Value *CurPtrRaw = CurPtr.emitRawPointer(*this); + pushRegularPartialArrayCleanup(BeginPtrRaw, CurPtrRaw, ElementType, + ElementAlign, getDestroyer(DtorKind)); Cleanup = EHStack.stable_begin(); CleanupDominator = Builder.CreateUnreachable(); } @@ -1296,9 +1297,8 @@ void CodeGenFunction::EmitNewArrayInitializer( } // Advance to the next element by adjusting the pointer type as necessary. - llvm::Value *NextPtr = - Builder.CreateConstInBoundsGEP1_32(ElementTy, CurPtr.getPointer(), 1, - "array.next"); + llvm::Value *NextPtr = Builder.CreateConstInBoundsGEP1_32( + ElementTy, CurPtr.emitRawPointer(*this), 1, "array.next"); // Check whether we've gotten to the end of the array and, if so, // exit the loop. @@ -1524,14 +1524,9 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, typedef CallDeleteDuringNew DirectCleanup; - DirectCleanup *Cleanup = CGF.EHStack - .pushCleanupWithExtra(EHCleanup, - E->getNumPlacementArgs(), - E->getOperatorDelete(), - NewPtr.getPointer(), - AllocSize, - E->passAlignment(), - AllocAlign); + DirectCleanup *Cleanup = CGF.EHStack.pushCleanupWithExtra( + EHCleanup, E->getNumPlacementArgs(), E->getOperatorDelete(), + NewPtr.emitRawPointer(CGF), AllocSize, E->passAlignment(), AllocAlign); for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) { auto &Arg = NewArgs[I + NumNonPlacementArgs]; Cleanup->setPlacementArg(I, Arg.getRValue(CGF), Arg.Ty); @@ -1542,7 +1537,7 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, // Otherwise, we need to save all this stuff. DominatingValue::saved_type SavedNewPtr = - DominatingValue::save(CGF, RValue::get(NewPtr.getPointer())); + DominatingValue::save(CGF, RValue::get(NewPtr, CGF)); DominatingValue::saved_type SavedAllocSize = DominatingValue::save(CGF, RValue::get(AllocSize)); @@ -1591,8 +1586,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { isa(IgnoreParen) || isa(IgnoreParen)) { minElements = cast(Init->getType()->getAsArrayTypeUnsafe()) - ->getSize() - .getZExtValue(); + ->getZExtSize(); } else if (ILE || CPLIE) { minElements = ILE ? ILE->getNumInits() : CPLIE->getInitExprs().size(); } @@ -1620,14 +1614,14 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // In these cases, discard the computed alignment and use the // formal alignment of the allocated type. if (BaseInfo.getAlignmentSource() != AlignmentSource::Decl) - allocation = allocation.withAlignment(allocAlign); + allocation.setAlignment(allocAlign); // Set up allocatorArgs for the call to operator delete if it's not // the reserved global operator. if (E->getOperatorDelete() && !E->getOperatorDelete()->isReservedGlobalPlacementOperator()) { allocatorArgs.add(RValue::get(allocSize), getContext().getSizeType()); - allocatorArgs.add(RValue::get(allocation.getPointer()), arg->getType()); + allocatorArgs.add(RValue::get(allocation, *this), arg->getType()); } } else { @@ -1715,8 +1709,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { llvm::BasicBlock *notNullBB = createBasicBlock("new.notnull"); contBB = createBasicBlock("new.cont"); - llvm::Value *isNull = - Builder.CreateIsNull(allocation.getPointer(), "new.isnull"); + llvm::Value *isNull = Builder.CreateIsNull(allocation, "new.isnull"); Builder.CreateCondBr(isNull, contBB, notNullBB); EmitBlock(notNullBB); } @@ -1762,12 +1755,12 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { SkippedChecks.set(SanitizerKind::Null, nullCheck); EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, E->getAllocatedTypeSourceInfo()->getTypeLoc().getBeginLoc(), - result.getPointer(), allocType, result.getAlignment(), - SkippedChecks, numElements); + result, allocType, result.getAlignment(), SkippedChecks, + numElements); EmitNewInitializer(*this, E, allocType, elementTy, result, numElements, allocSizeWithoutCookie); - llvm::Value *resultPtr = result.getPointer(); + llvm::Value *resultPtr = result.emitRawPointer(*this); if (E->isArray()) { // NewPtr is a pointer to the base element type. If we're // allocating an array of arrays, we'll need to cast back to the @@ -1911,7 +1904,8 @@ static void EmitDestroyingObjectDelete(CodeGenFunction &CGF, CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType, Dtor); else - CGF.EmitDeleteCall(DE->getOperatorDelete(), Ptr.getPointer(), ElementType); + CGF.EmitDeleteCall(DE->getOperatorDelete(), Ptr.emitRawPointer(CGF), + ElementType); } /// Emit the code for deleting a single object. @@ -1927,8 +1921,7 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, // dynamic type, the static type shall be a base class of the dynamic type // of the object to be deleted and the static type shall have a virtual // destructor or the behavior is undefined. - CGF.EmitTypeCheck(CodeGenFunction::TCK_MemberCall, - DE->getExprLoc(), Ptr.getPointer(), + CGF.EmitTypeCheck(CodeGenFunction::TCK_MemberCall, DE->getExprLoc(), Ptr, ElementType); const FunctionDecl *OperatorDelete = DE->getOperatorDelete(); @@ -1977,9 +1970,8 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, // Make sure that we call delete even if the dtor throws. // This doesn't have to a conditional cleanup because we're going // to pop it off in a second. - CGF.EHStack.pushCleanup(NormalAndEHCleanup, - Ptr.getPointer(), - OperatorDelete, ElementType); + CGF.EHStack.pushCleanup( + NormalAndEHCleanup, Ptr.emitRawPointer(CGF), OperatorDelete, ElementType); if (Dtor) CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, @@ -2066,7 +2058,7 @@ static void EmitArrayDelete(CodeGenFunction &CGF, CharUnits elementAlign = deletedPtr.getAlignment().alignmentOfArrayElement(elementSize); - llvm::Value *arrayBegin = deletedPtr.getPointer(); + llvm::Value *arrayBegin = deletedPtr.emitRawPointer(CGF); llvm::Value *arrayEnd = CGF.Builder.CreateInBoundsGEP( deletedPtr.getElementType(), arrayBegin, numElements, "delete.end"); @@ -2097,7 +2089,7 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull"); llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end"); - llvm::Value *IsNull = Builder.CreateIsNull(Ptr.getPointer(), "isnull"); + llvm::Value *IsNull = Builder.CreateIsNull(Ptr, "isnull"); Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull); EmitBlock(DeleteNotNull); @@ -2132,10 +2124,8 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { GEP.push_back(Zero); } - Ptr = Address(Builder.CreateInBoundsGEP(Ptr.getElementType(), - Ptr.getPointer(), GEP, "del.first"), - ConvertTypeForMem(DeleteTy), Ptr.getAlignment(), - Ptr.isKnownNonNull()); + Ptr = Builder.CreateInBoundsGEP(Ptr, GEP, ConvertTypeForMem(DeleteTy), + Ptr.getAlignment(), "del.first"); } assert(ConvertTypeForMem(DeleteTy) == Ptr.getElementType()); @@ -2193,7 +2183,7 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, // destruction and the static type of the operand is neither the constructor // or destructor’s class nor one of its bases, the behavior is undefined. CGF.EmitTypeCheck(CodeGenFunction::TCK_DynamicOperation, E->getExprLoc(), - ThisPtr.getPointer(), SrcRecordTy); + ThisPtr, SrcRecordTy); // C++ [expr.typeid]p2: // If the glvalue expression is obtained by applying the unary * operator to @@ -2209,7 +2199,7 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, CGF.createBasicBlock("typeid.bad_typeid"); llvm::BasicBlock *EndBlock = CGF.createBasicBlock("typeid.end"); - llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr.getPointer()); + llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr); CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock); CGF.EmitBlock(BadTypeidBlock); @@ -2295,8 +2285,7 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, // construction or destruction and the static type of the operand is not a // pointer to or object of the constructor or destructor’s own class or one // of its bases, the dynamic_cast results in undefined behavior. - EmitTypeCheck(TCK_DynamicOperation, DCE->getExprLoc(), ThisAddr.getPointer(), - SrcRecordTy); + EmitTypeCheck(TCK_DynamicOperation, DCE->getExprLoc(), ThisAddr, SrcRecordTy); if (DCE->isAlwaysNull()) { if (llvm::Value *T = EmitDynamicCastToNull(*this, DestTy)) { @@ -2331,7 +2320,7 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, CastNull = createBasicBlock("dynamic_cast.null"); CastNotNull = createBasicBlock("dynamic_cast.notnull"); - llvm::Value *IsNull = Builder.CreateIsNull(ThisAddr.getPointer()); + llvm::Value *IsNull = Builder.CreateIsNull(ThisAddr); Builder.CreateCondBr(IsNull, CastNull, CastNotNull); EmitBlock(CastNotNull); } diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 75286dceb13a7b2bcd5c90bbdae95a227ea36078..36d7493d9a6baf86022a3a74052439b7f017868a 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -656,7 +656,7 @@ static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter, } unsigned NumElementsToUpdate = - FillC ? CAT->getSize().getZExtValue() : Updater->getNumInits(); + FillC ? CAT->getZExtSize() : Updater->getNumInits(); for (unsigned I = 0; I != NumElementsToUpdate; ++I, Offset += ElemSize) { Expr *Init = nullptr; if (I < Updater->getNumInits()) @@ -800,8 +800,8 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, // Add a vtable pointer, if we need one and it hasn't already been added. if (Layout.hasOwnVFPtr()) { llvm::Constant *VTableAddressPoint = - CGM.getCXXABI().getVTableAddressPointForConstExpr( - BaseSubobject(CD, Offset), VTableClass); + CGM.getCXXABI().getVTableAddressPoint(BaseSubobject(CD, Offset), + VTableClass); if (!AppendBytes(Offset, VTableAddressPoint)) return false; } @@ -1249,7 +1249,7 @@ public: auto *CAT = CGM.getContext().getAsConstantArrayType(ILE->getType()); assert(CAT && "can't emit array init for non-constant-bound array"); unsigned NumInitElements = ILE->getNumInits(); - unsigned NumElements = CAT->getSize().getZExtValue(); + unsigned NumElements = CAT->getZExtSize(); // Initialising an array requires us to automatically // initialise any elements that have not been initialised explicitly @@ -1374,7 +1374,7 @@ public: // Resize the string to the right size, adding zeros at the end, or // truncating as needed. - Str.resize(CAT->getSize().getZExtValue(), '\0'); + Str.resize(CAT->getZExtSize(), '\0'); return llvm::ConstantDataArray::getString(VMContext, Str, false); } @@ -2382,7 +2382,7 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { llvm::Constant *Element = ConstantEmitter::emitNullForMemory(*this, ElementTy); - unsigned NumElements = CAT->getSize().getZExtValue(); + unsigned NumElements = CAT->getZExtSize(); SmallVector Array(NumElements, Element); return llvm::ConstantArray::get(ATy, Array); } diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 8536570087ad0fe96016f169b6dfbbe031c3035d..83247aa48f8609144a6bd6e400e5491f97ccb8ff 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2250,7 +2250,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { // performed and the object is not of the derived type. if (CGF.sanitizePerformTypeCheck()) CGF.EmitTypeCheck(CodeGenFunction::TCK_DowncastPointer, CE->getExprLoc(), - Derived.getPointer(), DestTy->getPointeeType()); + Derived, DestTy->getPointeeType()); if (CGF.SanOpts.has(SanitizerKind::CFIDerivedCast)) CGF.EmitVTablePtrCheckForCast(DestTy->getPointeeType(), Derived, @@ -2258,13 +2258,14 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { CodeGenFunction::CFITCK_DerivedCast, CE->getBeginLoc()); - return Derived.getPointer(); + return CGF.getAsNaturalPointerTo(Derived, CE->getType()->getPointeeType()); } case CK_UncheckedDerivedToBase: case CK_DerivedToBase: { // The EmitPointerWithAlignment path does this fine; just discard // the alignment. - return CGF.EmitPointerWithAlignment(CE).getPointer(); + return CGF.getAsNaturalPointerTo(CGF.EmitPointerWithAlignment(CE), + CE->getType()->getPointeeType()); } case CK_Dynamic: { @@ -2274,7 +2275,8 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { } case CK_ArrayToPointerDecay: - return CGF.EmitArrayToPointerDecay(E).getPointer(); + return CGF.getAsNaturalPointerTo(CGF.EmitArrayToPointerDecay(E), + CE->getType()->getPointeeType()); case CK_FunctionToPointerDecay: return EmitLValue(E).getPointer(CGF); @@ -5588,3 +5590,16 @@ CodeGenFunction::EmitCheckedInBoundsGEP(llvm::Type *ElemTy, Value *Ptr, return GEPVal; } + +Address CodeGenFunction::EmitCheckedInBoundsGEP( + Address Addr, ArrayRef IdxList, llvm::Type *elementType, + bool SignedIndices, bool IsSubtraction, SourceLocation Loc, CharUnits Align, + const Twine &Name) { + if (!SanOpts.has(SanitizerKind::PointerOverflow)) + return Builder.CreateInBoundsGEP(Addr, IdxList, elementType, Align, Name); + + return RawAddress( + EmitCheckedInBoundsGEP(Addr.getElementType(), Addr.emitRawPointer(*this), + IdxList, SignedIndices, IsSubtraction, Loc, Name), + elementType, Align); +} diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp index 75c1d7fbea840688ebe63d5939a08a09cdfd1243..8fade0fac21e9379df8c06aec1c301fdbaff6e85 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -366,7 +366,7 @@ template struct GenFuncBase { llvm::Value *SizeInBytes = CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts); llvm::Value *DstArrayEnd = CGF.Builder.CreateInBoundsGEP( - CGF.Int8Ty, DstAddr.getPointer(), SizeInBytes); + CGF.Int8Ty, DstAddr.emitRawPointer(CGF), SizeInBytes); llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock(); // Create the header block and insert the phi instructions. @@ -376,7 +376,7 @@ template struct GenFuncBase { for (unsigned I = 0; I < N; ++I) { PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur"); - PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB); + PHIs[I]->addIncoming(StartAddrs[I].emitRawPointer(CGF), PreheaderBB); } // Create the exit and loop body blocks. @@ -410,7 +410,7 @@ template struct GenFuncBase { // Instrs to update the destination and source addresses. // Update phi instructions. NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize); - PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB); + PHIs[I]->addIncoming(NewAddrs[I].emitRawPointer(CGF), LoopBB); } // Insert an unconditional branch to the header block. @@ -488,7 +488,7 @@ template struct GenFuncBase { for (unsigned I = 0; I < N; ++I) { Alignments[I] = Addrs[I].getAlignment(); - Ptrs[I] = Addrs[I].getPointer(); + Ptrs[I] = Addrs[I].emitRawPointer(CallerCGF); } if (llvm::Function *F = diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index f3a948cf13f9c9098f8497a28aa1ee9102f59939..c7f497a7c8451be6918c726ebdb3423a600170db 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -94,8 +94,8 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) { // and cast value to correct type Address Temporary = CreateMemTemp(SubExpr->getType()); EmitAnyExprToMem(SubExpr, Temporary, Qualifiers(), /*isInit*/ true); - llvm::Value *BitCast = - Builder.CreateBitCast(Temporary.getPointer(), ConvertType(ArgQT)); + llvm::Value *BitCast = Builder.CreateBitCast( + Temporary.emitRawPointer(*this), ConvertType(ArgQT)); Args.add(RValue::get(BitCast), ArgQT); // Create char array to store type encoding @@ -204,11 +204,11 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E, ObjCMethodDecl::param_const_iterator PI = MethodWithObjects->param_begin(); const ParmVarDecl *argDecl = *PI++; QualType ArgQT = argDecl->getType().getUnqualifiedType(); - Args.add(RValue::get(Objects.getPointer()), ArgQT); + Args.add(RValue::get(Objects, *this), ArgQT); if (DLE) { argDecl = *PI++; ArgQT = argDecl->getType().getUnqualifiedType(); - Args.add(RValue::get(Keys.getPointer()), ArgQT); + Args.add(RValue::get(Keys, *this), ArgQT); } argDecl = *PI; ArgQT = argDecl->getType().getUnqualifiedType(); @@ -827,7 +827,7 @@ static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar, // sizeof (Type of Ivar), isAtomic, false); CallArgList args; - llvm::Value *dest = CGF.ReturnValue.getPointer(); + llvm::Value *dest = CGF.ReturnValue.emitRawPointer(CGF); args.add(RValue::get(dest), Context.VoidPtrTy); args.add(RValue::get(src), Context.VoidPtrTy); @@ -1147,8 +1147,8 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, callCStructCopyConstructor(Dst, Src); } else { ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(), ivar, - AtomicHelperFn); + emitCPPObjectAtomicGetterCall(*this, ReturnValue.emitRawPointer(*this), + ivar, AtomicHelperFn); } return; } @@ -1163,7 +1163,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, } else { ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(), + emitCPPObjectAtomicGetterCall(*this, ReturnValue.emitRawPointer(*this), ivar, AtomicHelperFn); } return; @@ -1287,7 +1287,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, case TEK_Scalar: { llvm::Value *value; if (propType->isReferenceType()) { - value = LV.getAddress(*this).getPointer(); + value = LV.getAddress(*this).emitRawPointer(*this); } else { // We want to load and autoreleaseReturnValue ARC __weak ivars. if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) { @@ -1821,16 +1821,14 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ CallArgList Args; // The first argument is a temporary of the enumeration-state type. - Args.add(RValue::get(StatePtr.getPointer()), - getContext().getPointerType(StateTy)); + Args.add(RValue::get(StatePtr, *this), getContext().getPointerType(StateTy)); // The second argument is a temporary array with space for NumItems // pointers. We'll actually be loading elements from the array // pointer written into the control state; this buffer is so that // collections that *aren't* backed by arrays can still queue up // batches of elements. - Args.add(RValue::get(ItemsPtr.getPointer()), - getContext().getPointerType(ItemsTy)); + Args.add(RValue::get(ItemsPtr, *this), getContext().getPointerType(ItemsTy)); // The third argument is the capacity of that temporary array. llvm::Type *NSUIntegerTy = ConvertType(getContext().getNSUIntegerType()); @@ -2198,7 +2196,7 @@ static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF, Address addr, if (!fn) fn = getARCIntrinsic(IntID, CGF.CGM); - return CGF.EmitNounwindRuntimeCall(fn, addr.getPointer()); + return CGF.EmitNounwindRuntimeCall(fn, addr.emitRawPointer(CGF)); } /// Perform an operation having the following signature: @@ -2216,9 +2214,8 @@ static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF, Address addr, llvm::Type *origType = value->getType(); llvm::Value *args[] = { - CGF.Builder.CreateBitCast(addr.getPointer(), CGF.Int8PtrPtrTy), - CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy) - }; + CGF.Builder.CreateBitCast(addr.emitRawPointer(CGF), CGF.Int8PtrPtrTy), + CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy)}; llvm::CallInst *result = CGF.EmitNounwindRuntimeCall(fn, args); if (ignored) return nullptr; @@ -2237,9 +2234,8 @@ static void emitARCCopyOperation(CodeGenFunction &CGF, Address dst, Address src, fn = getARCIntrinsic(IntID, CGF.CGM); llvm::Value *args[] = { - CGF.Builder.CreateBitCast(dst.getPointer(), CGF.Int8PtrPtrTy), - CGF.Builder.CreateBitCast(src.getPointer(), CGF.Int8PtrPtrTy) - }; + CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), CGF.Int8PtrPtrTy), + CGF.Builder.CreateBitCast(src.emitRawPointer(CGF), CGF.Int8PtrPtrTy)}; CGF.EmitNounwindRuntimeCall(fn, args); } @@ -2490,9 +2486,8 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(Address addr, fn = getARCIntrinsic(llvm::Intrinsic::objc_storeStrong, CGM); llvm::Value *args[] = { - Builder.CreateBitCast(addr.getPointer(), Int8PtrPtrTy), - Builder.CreateBitCast(value, Int8PtrTy) - }; + Builder.CreateBitCast(addr.emitRawPointer(*this), Int8PtrPtrTy), + Builder.CreateBitCast(value, Int8PtrTy)}; EmitNounwindRuntimeCall(fn, args); if (ignored) return nullptr; @@ -2643,7 +2638,7 @@ void CodeGenFunction::EmitARCDestroyWeak(Address addr) { if (!fn) fn = getARCIntrinsic(llvm::Intrinsic::objc_destroyWeak, CGM); - EmitNounwindRuntimeCall(fn, addr.getPointer()); + EmitNounwindRuntimeCall(fn, addr.emitRawPointer(*this)); } /// void \@objc_moveWeak(i8** %dest, i8** %src) diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index a36b0cdddaf0afd293592aac7fe7124ab8613db2..4e7f777ba1d9160fd872c7a3466fcf2a438f12e2 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -706,7 +706,8 @@ protected: llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; llvm::Value *lookupArgs[] = { - EnforceType(Builder, ObjCSuper.getPointer(), PtrToObjCSuperTy), cmd}; + EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), PtrToObjCSuperTy), + cmd}; return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs); } @@ -761,8 +762,8 @@ class CGObjCGNUstep : public CGObjCGNU { llvm::FunctionCallee LookupFn = SlotLookupFn; // Store the receiver on the stack so that we can reload it later - Address ReceiverPtr = - CGF.CreateTempAlloca(Receiver->getType(), CGF.getPointerAlign()); + RawAddress ReceiverPtr = + CGF.CreateTempAlloca(Receiver->getType(), CGF.getPointerAlign()); Builder.CreateStore(Receiver, ReceiverPtr); llvm::Value *self; @@ -778,9 +779,9 @@ class CGObjCGNUstep : public CGObjCGNU { LookupFn2->addParamAttr(0, llvm::Attribute::NoCapture); llvm::Value *args[] = { - EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy), - EnforceType(Builder, cmd, SelectorTy), - EnforceType(Builder, self, IdTy) }; + EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy), + EnforceType(Builder, cmd, SelectorTy), + EnforceType(Builder, self, IdTy)}; llvm::CallBase *slot = CGF.EmitRuntimeCallOrInvoke(LookupFn, args); slot->setOnlyReadsMemory(); slot->setMetadata(msgSendMDKind, node); @@ -800,7 +801,7 @@ class CGObjCGNUstep : public CGObjCGNU { llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; - llvm::Value *lookupArgs[] = {ObjCSuper.getPointer(), cmd}; + llvm::Value *lookupArgs[] = {ObjCSuper.emitRawPointer(CGF), cmd}; llvm::CallInst *slot = CGF.EmitNounwindRuntimeCall(SlotLookupSuperFn, lookupArgs); @@ -1221,10 +1222,10 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { llvm::Value *cmd, MessageSendInfo &MSI) override { // Don't access the slot unless we're trying to cache the result. CGBuilderTy &Builder = CGF.Builder; - llvm::Value *lookupArgs[] = {CGObjCGNU::EnforceType(Builder, - ObjCSuper.getPointer(), - PtrToObjCSuperTy), - cmd}; + llvm::Value *lookupArgs[] = { + CGObjCGNU::EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), + PtrToObjCSuperTy), + cmd}; return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs); } @@ -2186,7 +2187,8 @@ protected: llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; llvm::Value *lookupArgs[] = { - EnforceType(Builder, ObjCSuper.getPointer(), PtrToObjCSuperTy), cmd, + EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), PtrToObjCSuperTy), + cmd, }; if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) @@ -4201,15 +4203,15 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF, Address AddrWeakObj) { CGBuilderTy &B = CGF.Builder; - return B.CreateCall(WeakReadFn, - EnforceType(B, AddrWeakObj.getPointer(), PtrToIdTy)); + return B.CreateCall( + WeakReadFn, EnforceType(B, AddrWeakObj.emitRawPointer(CGF), PtrToIdTy)); } void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF, llvm::Value *src, Address dst) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); B.CreateCall(WeakAssignFn, {src, dstVal}); } @@ -4218,7 +4220,7 @@ void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF, bool threadlocal) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); // FIXME. Add threadloca assign API assert(!threadlocal && "EmitObjCGlobalAssign - Threal Local API NYI"); B.CreateCall(GlobalAssignFn, {src, dstVal}); @@ -4229,7 +4231,7 @@ void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF, llvm::Value *ivarOffset) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), IdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), IdTy); B.CreateCall(IvarAssignFn, {src, dstVal, ivarOffset}); } @@ -4237,7 +4239,7 @@ void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF, llvm::Value *src, Address dst) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); B.CreateCall(StrongCastAssignFn, {src, dstVal}); } @@ -4246,8 +4248,8 @@ void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF, Address SrcPtr, llvm::Value *Size) { CGBuilderTy &B = CGF.Builder; - llvm::Value *DestPtrVal = EnforceType(B, DestPtr.getPointer(), PtrTy); - llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.getPointer(), PtrTy); + llvm::Value *DestPtrVal = EnforceType(B, DestPtr.emitRawPointer(CGF), PtrTy); + llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.emitRawPointer(CGF), PtrTy); B.CreateCall(MemMoveFn, {DestPtrVal, SrcPtrVal, Size}); } diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index e815e097e1fb48e7e3037d8983174ed471259245..8a599c10e1caf17328d7f3e1d70f3b7d499aacbc 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -1310,7 +1310,7 @@ private: /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel); - Address EmitSelectorAddr(Selector Sel); + ConstantAddress EmitSelectorAddr(Selector Sel); public: CGObjCMac(CodeGen::CodeGenModule &cgm); @@ -1538,7 +1538,7 @@ private: /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel); - Address EmitSelectorAddr(Selector Sel); + ConstantAddress EmitSelectorAddr(Selector Sel); /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C /// interface. The return value has type EHTypePtrTy. @@ -2064,9 +2064,8 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, const ObjCMethodDecl *Method) { // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. - Address ObjCSuper = - CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(), - "objc_super"); + RawAddress ObjCSuper = CGF.CreateTempAlloca( + ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super"); llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); CGF.Builder.CreateStore(ReceiverAsObject, @@ -2501,12 +2500,12 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { auto *CArray = cast(Array); - uint64_t ElCount = CArray->getSize().getZExtValue(); + uint64_t ElCount = CArray->getZExtSize(); assert(CArray && "only array with known element size is supported"); FQT = CArray->getElementType(); while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { auto *CArray = cast(Array); - ElCount *= CArray->getSize().getZExtValue(); + ElCount *= CArray->getZExtSize(); FQT = CArray->getElementType(); } if (FQT->isRecordType() && ElCount) { @@ -4259,7 +4258,7 @@ namespace { CGF.EmitBlock(FinallyCallExit); CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(), - ExceptionData.getPointer()); + ExceptionData.emitRawPointer(CGF)); CGF.EmitBlock(FinallyNoCallExit); @@ -4425,7 +4424,9 @@ void FragileHazards::emitHazardsInNewBlocks() { } static void addIfPresent(llvm::DenseSet &S, Address V) { - if (V.isValid()) S.insert(V.getPointer()); + if (V.isValid()) + if (llvm::Value *Ptr = V.getBasePointer()) + S.insert(Ptr); } void FragileHazards::collectLocals() { @@ -4628,13 +4629,13 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // - Call objc_exception_try_enter to push ExceptionData on top of // the EH stack. CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), - ExceptionData.getPointer()); + ExceptionData.emitRawPointer(CGF)); // - Call setjmp on the exception data buffer. llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0); llvm::Value *GEPIndexes[] = { Zero, Zero, Zero }; llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP( - ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes, + ObjCTypes.ExceptionDataTy, ExceptionData.emitRawPointer(CGF), GEPIndexes, "setjmp_buffer"); llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall( ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result"); @@ -4673,9 +4674,9 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, } else { // Retrieve the exception object. We may emit multiple blocks but // nothing can cross this so the value is already in SSA form. - llvm::CallInst *Caught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer(), "caught"); + llvm::CallInst *Caught = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF), + "caught"); // Push the exception to rethrow onto the EH value stack for the // benefit of any @throws in the handlers. @@ -4698,7 +4699,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Enter a new exception try block (in case a @catch block // throws an exception). CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), - ExceptionData.getPointer()); + ExceptionData.emitRawPointer(CGF)); llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(), @@ -4829,9 +4830,9 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Extract the new exception and save it to the // propagating-exception slot. assert(PropagatingExnVar.isValid()); - llvm::CallInst *NewCaught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer(), "caught"); + llvm::CallInst *NewCaught = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF), + "caught"); CGF.Builder.CreateStore(NewCaught, PropagatingExnVar); // Don't pop the catch handler; the throw already did. @@ -4861,9 +4862,8 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Otherwise, just look in the buffer for the exception to throw. } else { - llvm::CallInst *Caught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer()); + llvm::CallInst *Caught = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF)); PropagatingExn = Caught; } @@ -4906,7 +4906,7 @@ llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, Address AddrWeakObj) { llvm::Type* DestTy = AddrWeakObj.getElementType(); llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast( - AddrWeakObj.getPointer(), ObjCTypes.PtrObjectPtrTy); + AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread"); @@ -4928,8 +4928,8 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = { src, dstVal }; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args, "weakassign"); @@ -4950,8 +4950,8 @@ void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; if (!threadlocal) CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), @@ -4977,8 +4977,8 @@ void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal, ivarOffset}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); } @@ -4997,8 +4997,8 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args, "strongassign"); @@ -5007,7 +5007,8 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, llvm::Value *size) { - llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size }; + llvm::Value *args[] = {DestPtr.emitRawPointer(CGF), + SrcPtr.emitRawPointer(CGF), size}; CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); } @@ -5243,7 +5244,7 @@ llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) { return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel)); } -Address CGObjCMac::EmitSelectorAddr(Selector Sel) { +ConstantAddress CGObjCMac::EmitSelectorAddr(Selector Sel) { CharUnits Align = CGM.getPointerAlign(); llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; @@ -5254,7 +5255,7 @@ Address CGObjCMac::EmitSelectorAddr(Selector Sel) { Entry->setExternallyInitialized(true); } - return Address(Entry, ObjCTypes.SelectorPtrTy, Align); + return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align); } llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) { @@ -5326,7 +5327,7 @@ void IvarLayoutBuilder::visitField(const FieldDecl *field, } // Unlike incomplete arrays, constant arrays can be nested. while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) { - numElts *= arrayType->getSize().getZExtValue(); + numElts *= arrayType->getZExtSize(); fieldType = arrayType->getElementType(); } @@ -7323,7 +7324,7 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, ObjCTypes.MessageRefTy, CGF.getPointerAlign()); // Update the message ref argument. - args[1].setRValue(RValue::get(mref.getPointer())); + args[1].setRValue(RValue::get(mref, CGF)); // Load the function to call from the message ref table. Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0); @@ -7552,9 +7553,8 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, // ... // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. - Address ObjCSuper = - CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(), - "objc_super"); + RawAddress ObjCSuper = CGF.CreateTempAlloca( + ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super"); llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); @@ -7594,7 +7594,7 @@ llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF, return LI; } -Address CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { +ConstantAddress CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; CharUnits Align = CGM.getPointerAlign(); if (!Entry) { @@ -7610,7 +7610,7 @@ Address CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { CGM.addCompilerUsedGlobal(Entry); } - return Address(Entry, ObjCTypes.SelectorPtrTy, Align); + return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align); } /// EmitObjCIvarAssign - Code gen for assigning to a __strong object. @@ -7629,8 +7629,8 @@ void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal, ivarOffset}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); } @@ -7650,8 +7650,8 @@ void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args, "weakassign"); @@ -7660,7 +7660,8 @@ void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, llvm::Value *Size) { - llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size }; + llvm::Value *args[] = {DestPtr.emitRawPointer(CGF), + SrcPtr.emitRawPointer(CGF), Size}; CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); } @@ -7672,7 +7673,7 @@ llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( Address AddrWeakObj) { llvm::Type *DestTy = AddrWeakObj.getElementType(); llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast( - AddrWeakObj.getPointer(), ObjCTypes.PtrObjectPtrTy); + AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread"); @@ -7694,8 +7695,8 @@ void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args, "weakassign"); @@ -7716,8 +7717,8 @@ void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; if (!threadlocal) CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp index 424564f9759995267ff2061cfbc6371ecbc7c2df..01d0f35da19643cf1d0b5b21439f6fbbe4ade22e 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -67,7 +67,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, V = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, V, Offset, "add.ptr"); if (!Ivar->isBitField()) { - LValue LV = CGF.MakeNaturalAlignAddrLValue(V, IvarTy); + LValue LV = CGF.MakeNaturalAlignRawAddrLValue(V, IvarTy); return LV; } @@ -233,7 +233,7 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, llvm::Instruction *CPICandidate = Handler.Block->getFirstNonPHI(); if (auto *CPI = dyn_cast_or_null(CPICandidate)) { CGF.CurrentFuncletPad = CPI; - CPI->setOperand(2, CGF.getExceptionSlot().getPointer()); + CPI->setOperand(2, CGF.getExceptionSlot().emitRawPointer(CGF)); CGF.EHStack.pushCleanup(NormalCleanup, CPI); } } @@ -405,7 +405,7 @@ bool CGObjCRuntime::canMessageReceiverBeNull(CodeGenFunction &CGF, auto self = curMethod->getSelfDecl(); if (self->getType().isConstQualified()) { if (auto LI = dyn_cast(receiver->stripPointerCasts())) { - llvm::Value *selfAddr = CGF.GetAddrOfLocalVar(self).getPointer(); + llvm::Value *selfAddr = CGF.GetAddrOfLocalVar(self).emitRawPointer(CGF); if (selfAddr == LI->getPointerOperand()) { return false; } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index e8a68dbcc68709c7afd7249032674409dd711e9f..bc363313dec6f8ba350eb4f8c29ea9f0df6effde 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -622,7 +622,7 @@ static void emitInitWithReductionInitializer(CodeGenFunction &CGF, auto *GV = new llvm::GlobalVariable( CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, Init, Name); - LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); + LValue LV = CGF.MakeNaturalAlignRawAddrLValue(GV, Ty); RValue InitRVal; switch (CGF.getEvaluationKind(Ty)) { case TEK_Scalar: @@ -668,8 +668,8 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, llvm::Value *SrcBegin = nullptr; if (DRD) - SrcBegin = SrcAddr.getPointer(); - llvm::Value *DestBegin = DestAddr.getPointer(); + SrcBegin = SrcAddr.emitRawPointer(CGF); + llvm::Value *DestBegin = DestAddr.emitRawPointer(CGF); // Cast from pointer to array type to pointer to single element. llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestAddr.getElementType(), DestBegin, NumElements); @@ -912,7 +912,7 @@ static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, Address OriginalBaseAddress, llvm::Value *Addr) { - Address Tmp = Address::invalid(); + RawAddress Tmp = RawAddress::invalid(); Address TopTmp = Address::invalid(); Address MostTopTmp = Address::invalid(); BaseTy = BaseTy.getNonReferenceType(); @@ -971,10 +971,10 @@ Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address SharedAddr = SharedAddresses[N].first.getAddress(CGF); llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( SharedAddr.getElementType(), BaseLValue.getPointer(CGF), - SharedAddr.getPointer()); + SharedAddr.emitRawPointer(CGF)); llvm::Value *PrivatePointer = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - PrivateAddr.getPointer(), SharedAddr.getType()); + PrivateAddr.emitRawPointer(CGF), SharedAddr.getType()); llvm::Value *Ptr = CGF.Builder.CreateGEP( SharedAddr.getElementType(), PrivatePointer, Adjustment); return castToBase(CGF, OrigVD->getType(), @@ -1557,7 +1557,7 @@ static llvm::TargetRegionEntryInfo getEntryInfoFromPresumedLoc( return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack, ParentName); } -Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { +ConstantAddress CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { auto AddrOfGlobal = [&VD, this]() { return CGM.GetAddrOfGlobal(VD); }; auto LinkageForVariable = [&VD, this]() { @@ -1579,8 +1579,8 @@ Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { LinkageForVariable); if (!addr) - return Address::invalid(); - return Address(addr, LlvmPtrTy, CGM.getContext().getDeclAlign(VD)); + return ConstantAddress::invalid(); + return ConstantAddress(addr, LlvmPtrTy, CGM.getContext().getDeclAlign(VD)); } llvm::Constant * @@ -1604,7 +1604,7 @@ Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, llvm::Type *VarTy = VDAddr.getElementType(); llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.Int8PtrTy), + CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.Int8PtrTy), CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), getOrCreateThreadPrivateCache(VD)}; return Address( @@ -1627,7 +1627,8 @@ void CGOpenMPRuntime::emitThreadPrivateVarInit( // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) // to register constructor/destructor for variable. llvm::Value *Args[] = { - OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), + OMPLoc, + CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.VoidPtrTy), Ctor, CopyCtor, Dtor}; CGF.EmitRuntimeCall( OMPBuilder.getOrCreateRuntimeFunction( @@ -1900,13 +1901,13 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, // OutlinedFn(>id, &zero_bound, CapturedStruct); Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); - Address ZeroAddrBound = + RawAddress ZeroAddrBound = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, /*Name=*/".bound.zero.addr"); CGF.Builder.CreateStore(CGF.Builder.getInt32(/*C*/ 0), ZeroAddrBound); llvm::SmallVector OutlinedFnArgs; // ThreadId for serialized parallels is 0. - OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); + OutlinedFnArgs.push_back(ThreadIDAddr.emitRawPointer(CGF)); OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); @@ -2272,7 +2273,7 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, emitUpdateLocation(CGF, Loc), // ident_t * getThreadID(CGF, Loc), // i32 BufSize, // size_t - CL.getPointer(), // void * + CL.emitRawPointer(CGF), // void * CpyFn, // void (*) (void *, void *) DidItVal // i32 did_it }; @@ -2591,10 +2592,10 @@ static void emitForStaticInitCall( ThreadId, CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, M2)), // Schedule type - Values.IL.getPointer(), // &isLastIter - Values.LB.getPointer(), // &LB - Values.UB.getPointer(), // &UB - Values.ST.getPointer(), // &Stride + Values.IL.emitRawPointer(CGF), // &isLastIter + Values.LB.emitRawPointer(CGF), // &LB + Values.UB.emitRawPointer(CGF), // &UB + Values.ST.emitRawPointer(CGF), // &Stride CGF.Builder.getIntN(Values.IVSize, 1), // Incr Chunk // Chunk }; @@ -2697,12 +2698,11 @@ llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, // kmp_int[32|64] *p_stride); llvm::Value *Args[] = { - emitUpdateLocation(CGF, Loc), - getThreadID(CGF, Loc), - IL.getPointer(), // &isLastIter - LB.getPointer(), // &Lower - UB.getPointer(), // &Upper - ST.getPointer() // &Stride + emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), + IL.emitRawPointer(CGF), // &isLastIter + LB.emitRawPointer(CGF), // &Lower + UB.emitRawPointer(CGF), // &Upper + ST.emitRawPointer(CGF) // &Stride }; llvm::Value *Call = CGF.EmitRuntimeCall( OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args); @@ -3047,7 +3047,7 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, CGF.Builder .CreatePointerBitCastOrAddrSpaceCast(TDBase.getAddress(CGF), CGF.VoidPtrTy, CGF.Int8Ty) - .getPointer()}; + .emitRawPointer(CGF)}; SmallVector CallArgs(std::begin(CommonArgs), std::end(CommonArgs)); if (isOpenMPTaskLoopDirective(Kind)) { @@ -3574,7 +3574,8 @@ getPointerAndSize(CodeGenFunction &CGF, const Expr *E) { CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); Address UpAddrAddress = UpAddrLVal.getAddress(CGF); llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( - UpAddrAddress.getElementType(), UpAddrAddress.getPointer(), /*Idx0=*/1); + UpAddrAddress.getElementType(), UpAddrAddress.emitRawPointer(CGF), + /*Idx0=*/1); llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy); llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy); SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); @@ -3888,8 +3889,9 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *Size; std::tie(Addr, Size) = getPointerAndSize(CGF, E); llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); - LValue Base = CGF.MakeAddrLValue( - CGF.Builder.CreateGEP(AffinitiesArray, Idx), KmpTaskAffinityInfoTy); + LValue Base = + CGF.MakeAddrLValue(CGF.Builder.CreateGEP(CGF, AffinitiesArray, Idx), + KmpTaskAffinityInfoTy); // affs[i].base_addr = &; LValue BaseAddrLVal = CGF.EmitLValueForField( Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); @@ -3910,7 +3912,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *LocRef = emitUpdateLocation(CGF, Loc); llvm::Value *GTid = getThreadID(CGF, Loc); llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - AffinitiesArray.getPointer(), CGM.VoidPtrTy); + AffinitiesArray.emitRawPointer(CGF), CGM.VoidPtrTy); // FIXME: Emit the function and ignore its result for now unless the // runtime function is properly implemented. (void)CGF.EmitRuntimeCall( @@ -3921,8 +3923,8 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( NewTask, KmpTaskTWithPrivatesPtrTy); - LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, - KmpTaskTWithPrivatesQTy); + LValue Base = CGF.MakeNaturalAlignRawAddrLValue(NewTaskNewTaskTTy, + KmpTaskTWithPrivatesQTy); LValue TDBase = CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); // Fill the data in the resulting kmp_task_t record. @@ -4047,7 +4049,7 @@ CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, CGF.ConvertTypeForMem(KmpDependInfoPtrTy)), KmpDependInfoPtrTy->castAs()); Address DepObjAddr = CGF.Builder.CreateGEP( - Base.getAddress(CGF), + CGF, Base.getAddress(CGF), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); LValue NumDepsBase = CGF.MakeAddrLValue( DepObjAddr, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); @@ -4097,7 +4099,7 @@ static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue &PosLVal = *Pos.get(); llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); Base = CGF.MakeAddrLValue( - CGF.Builder.CreateGEP(DependenciesArray, Idx), KmpDependInfoTy); + CGF.Builder.CreateGEP(CGF, DependenciesArray, Idx), KmpDependInfoTy); } // deps[i].base_addr = &; LValue BaseAddrLVal = CGF.EmitLValueForField( @@ -4195,7 +4197,7 @@ void CGOpenMPRuntime::emitDepobjElements(CodeGenFunction &CGF, ElSize, CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); - Address DepAddr = CGF.Builder.CreateGEP(DependenciesArray, Pos); + Address DepAddr = CGF.Builder.CreateGEP(CGF, DependenciesArray, Pos); CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); // Increase pos. @@ -4430,7 +4432,7 @@ void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy), CGF.ConvertTypeForMem(KmpDependInfoTy)); llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( - Addr.getElementType(), Addr.getPointer(), + Addr.getElementType(), Addr.emitRawPointer(CGF), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, CGF.VoidPtrTy); @@ -4460,8 +4462,8 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, Address Begin = Base.getAddress(CGF); // Cast from pointer to array type to pointer to single element. - llvm::Value *End = CGF.Builder.CreateGEP( - Begin.getElementType(), Begin.getPointer(), NumDeps); + llvm::Value *End = CGF.Builder.CreateGEP(Begin.getElementType(), + Begin.emitRawPointer(CGF), NumDeps); // The basic structure here is a while-do loop. llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); @@ -4469,7 +4471,7 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, CGF.EmitBlock(BodyBB); llvm::PHINode *ElementPHI = CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); - ElementPHI->addIncoming(Begin.getPointer(), EntryBB); + ElementPHI->addIncoming(Begin.emitRawPointer(CGF), EntryBB); Begin = Begin.withPointer(ElementPHI, KnownNonNull); Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); @@ -4483,12 +4485,12 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, FlagsLVal); // Shift the address forward by one element. - Address ElementNext = - CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); - ElementPHI->addIncoming(ElementNext.getPointer(), - CGF.Builder.GetInsertBlock()); + llvm::Value *ElementNext = + CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext") + .emitRawPointer(CGF); + ElementPHI->addIncoming(ElementNext, CGF.Builder.GetInsertBlock()); llvm::Value *IsEmpty = - CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); + CGF.Builder.CreateICmpEQ(ElementNext, End, "omp.isempty"); CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); // Done. CGF.EmitBlock(DoneBB, /*IsFinished=*/true); @@ -4531,7 +4533,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, DepTaskArgs[1] = ThreadID; DepTaskArgs[2] = NewTask; DepTaskArgs[3] = NumOfElements; - DepTaskArgs[4] = DependenciesArray.getPointer(); + DepTaskArgs[4] = DependenciesArray.emitRawPointer(CGF); DepTaskArgs[5] = CGF.Builder.getInt32(0); DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); } @@ -4563,7 +4565,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, DepWaitTaskArgs[0] = UpLoc; DepWaitTaskArgs[1] = ThreadID; DepWaitTaskArgs[2] = NumOfElements; - DepWaitTaskArgs[3] = DependenciesArray.getPointer(); + DepWaitTaskArgs[3] = DependenciesArray.emitRawPointer(CGF); DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); DepWaitTaskArgs[6] = @@ -4725,8 +4727,8 @@ static void EmitOMPAggregateReduction( const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); - llvm::Value *RHSBegin = RHSAddr.getPointer(); - llvm::Value *LHSBegin = LHSAddr.getPointer(); + llvm::Value *RHSBegin = RHSAddr.emitRawPointer(CGF); + llvm::Value *LHSBegin = LHSAddr.emitRawPointer(CGF); // Cast from pointer to array type to pointer to single element. llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSAddr.getElementType(), LHSBegin, NumElements); @@ -4990,7 +4992,7 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, QualType ReductionArrayTy = C.getConstantArrayType( C.VoidPtrTy, ArraySize, nullptr, ArraySizeModifier::Normal, /*IndexTypeQuals=*/0); - Address ReductionList = + RawAddress ReductionList = CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); const auto *IPriv = Privates.begin(); unsigned Idx = 0; @@ -5462,7 +5464,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( C.getConstantArrayType(RDType, ArraySize, nullptr, ArraySizeModifier::Normal, /*IndexTypeQuals=*/0); // kmp_task_red_input_t .rd_input.[Size]; - Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); + RawAddress TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs, Data.ReductionCopies, Data.ReductionOps); for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { @@ -5473,7 +5475,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( TaskRedInput.getElementType(), TaskRedInput.getPointer(), Idxs, /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, ".rd_input.gep."); - LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); + LValue ElemLVal = CGF.MakeNaturalAlignRawAddrLValue(GEP, RDType); // ElemLVal.reduce_shar = &Shareds[Cnt]; LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); RCG.emitSharedOrigLValue(CGF, Cnt); @@ -5629,7 +5631,7 @@ void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, DepWaitTaskArgs[0] = UpLoc; DepWaitTaskArgs[1] = ThreadID; DepWaitTaskArgs[2] = NumOfElements; - DepWaitTaskArgs[3] = DependenciesArray.getPointer(); + DepWaitTaskArgs[3] = DependenciesArray.emitRawPointer(CGF); DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); DepWaitTaskArgs[6] = @@ -5852,7 +5854,7 @@ void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF, AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy, AllocatorTraitsLVal.getBaseInfo(), AllocatorTraitsLVal.getTBAAInfo()); - llvm::Value *Traits = Addr.getPointer(); + llvm::Value *Traits = Addr.emitRawPointer(CGF); llvm::Value *AllocatorVal = CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( @@ -6796,7 +6798,7 @@ private: OASE->getBase()->IgnoreParenImpCasts()) .getCanonicalType(); if (const auto *ATy = dyn_cast(BaseQTy.getTypePtr())) - return ATy->getSize().getSExtValue() != 1; + return ATy->getSExtSize() != 1; // If we don't have a constant dimension length, we have to consider // the current section as having any size, so it is not necessarily // unitary. If it happen to be unity size, that's user fault. @@ -7312,17 +7314,19 @@ private: CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) .getAddress(CGF); } - Size = CGF.Builder.CreatePtrDiff( - CGF.Int8Ty, ComponentLB.getPointer(), LB.getPointer()); + llvm::Value *ComponentLBPtr = ComponentLB.emitRawPointer(CGF); + llvm::Value *LBPtr = LB.emitRawPointer(CGF); + Size = CGF.Builder.CreatePtrDiff(CGF.Int8Ty, ComponentLBPtr, + LBPtr); break; } } assert(Size && "Failed to determine structure size"); CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.getPointer()); + CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.getPointer()); + CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.Types.push_back(Flags); @@ -7332,13 +7336,14 @@ private: LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); } CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.getPointer()); + CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.getPointer()); + CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); + llvm::Value *LBPtr = LB.emitRawPointer(CGF); Size = CGF.Builder.CreatePtrDiff( - CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).getPointer(), - LB.getPointer()); + CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).emitRawPointer(CGF), + LBPtr); CombinedInfo.Sizes.push_back( CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.Types.push_back(Flags); @@ -7356,20 +7361,21 @@ private: (Next == CE && MapType != OMPC_MAP_unknown)) { if (!IsMappingWholeStruct) { CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.getPointer()); + CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.getPointer()); + CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1); } else { StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - StructBaseCombinedInfo.BasePointers.push_back(BP.getPointer()); + StructBaseCombinedInfo.BasePointers.push_back( + BP.emitRawPointer(CGF)); StructBaseCombinedInfo.DevicePtrDecls.push_back(nullptr); StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - StructBaseCombinedInfo.Pointers.push_back(LB.getPointer()); + StructBaseCombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); StructBaseCombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); StructBaseCombinedInfo.NonContigInfo.Dims.push_back( @@ -7546,8 +7552,8 @@ private: // it. if (DimSizes.size() < Components.size() - 1) { if (CAT) - DimSizes.push_back(llvm::ConstantInt::get( - CGF.Int64Ty, CAT->getSize().getZExtValue())); + DimSizes.push_back( + llvm::ConstantInt::get(CGF.Int64Ty, CAT->getZExtSize())); else if (VAT) DimSizes.push_back(CGF.Builder.CreateIntCast( CGF.EmitScalarExpr(VAT->getSizeExpr()), CGF.Int64Ty, @@ -8211,11 +8217,11 @@ public: } CombinedInfo.Exprs.push_back(VD); // Base is the base of the struct - CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer()); + CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); // Pointer is the address of the lowest element - llvm::Value *LB = LBAddr.getPointer(); + llvm::Value *LB = LBAddr.emitRawPointer(CGF); const CXXMethodDecl *MD = CGF.CurFuncDecl ? dyn_cast(CGF.CurFuncDecl) : nullptr; const CXXRecordDecl *RD = MD ? MD->getParent() : nullptr; @@ -8229,7 +8235,7 @@ public: // if the this[:1] expression had appeared in a map clause with a map-type // of tofrom. // Emit this[:1] - CombinedInfo.Pointers.push_back(PartialStruct.Base.getPointer()); + CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF)); QualType Ty = MD->getFunctionObjectParameterType(); llvm::Value *Size = CGF.Builder.CreateIntCast(CGF.getTypeSize(Ty), CGF.Int64Ty, @@ -8238,7 +8244,7 @@ public: } else { CombinedInfo.Pointers.push_back(LB); // Size is (addr of {highest+1} element) - (addr of lowest element) - llvm::Value *HB = HBAddr.getPointer(); + llvm::Value *HB = HBAddr.emitRawPointer(CGF); llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32( HBAddr.getElementType(), HB, /*Idx0=*/1); llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); @@ -8747,7 +8753,7 @@ public: Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( CV, ElementType, CGF.getContext().getDeclAlign(VD), AlignmentSource::Decl)); - CombinedInfo.Pointers.push_back(PtrAddr.getPointer()); + CombinedInfo.Pointers.push_back(PtrAddr.emitRawPointer(CGF)); } else { CombinedInfo.Pointers.push_back(CV); } @@ -9558,10 +9564,11 @@ static void emitTargetCallKernelLaunch( bool HasNoWait = D.hasClausesOfKind(); unsigned NumTargetItems = InputInfo.NumberOfTargetItems; - llvm::Value *BasePointersArray = InputInfo.BasePointersArray.getPointer(); - llvm::Value *PointersArray = InputInfo.PointersArray.getPointer(); - llvm::Value *SizesArray = InputInfo.SizesArray.getPointer(); - llvm::Value *MappersArray = InputInfo.MappersArray.getPointer(); + llvm::Value *BasePointersArray = + InputInfo.BasePointersArray.emitRawPointer(CGF); + llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF); + llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF); + llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF); auto &&EmitTargetCallFallbackCB = [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS, @@ -10309,15 +10316,16 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall( // Source location for the ident struct llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); - llvm::Value *OffloadingArgs[] = {RTLoc, - DeviceID, - PointerNum, - InputInfo.BasePointersArray.getPointer(), - InputInfo.PointersArray.getPointer(), - InputInfo.SizesArray.getPointer(), - MapTypesArray, - MapNamesArray, - InputInfo.MappersArray.getPointer()}; + llvm::Value *OffloadingArgs[] = { + RTLoc, + DeviceID, + PointerNum, + InputInfo.BasePointersArray.emitRawPointer(CGF), + InputInfo.PointersArray.emitRawPointer(CGF), + InputInfo.SizesArray.emitRawPointer(CGF), + MapTypesArray, + MapNamesArray, + InputInfo.MappersArray.emitRawPointer(CGF)}; // Select the right runtime function call for each standalone // directive. @@ -11128,7 +11136,7 @@ void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, getThreadID(CGF, D.getBeginLoc()), llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), + CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).emitRawPointer(CGF), CGM.VoidPtrTy)}; llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( @@ -11162,7 +11170,8 @@ static void EmitDoacrossOrdered(CodeGenFunction &CGF, CodeGenModule &CGM, /*Volatile=*/false, Int64Ty); } llvm::Value *Args[] = { - ULoc, ThreadID, CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; + ULoc, ThreadID, + CGF.Builder.CreateConstArrayGEP(CntAddr, 0).emitRawPointer(CGF)}; llvm::FunctionCallee RTLFn; llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder(); OMPDoacrossKind ODK; @@ -11332,7 +11341,7 @@ Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, Args[0] = CGF.CGM.getOpenMPRuntime().getThreadID( CGF, SourceLocation::getFromRawEncoding(LocEncoding)); Args[1] = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - Addr.getPointer(), CGF.VoidPtrTy); + Addr.emitRawPointer(CGF), CGF.VoidPtrTy); llvm::Value *AllocVal = getAllocatorVal(CGF, AllocExpr); Args[2] = AllocVal; CGF.EmitRuntimeCall(RTLFn, Args); @@ -11690,15 +11699,17 @@ void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LLIVTy, getName({UniqueDeclName, "iv"})); cast(LastIV)->setAlignment( IVLVal.getAlignment().getAsAlign()); - LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); + LValue LastIVLVal = + CGF.MakeNaturalAlignRawAddrLValue(LastIV, IVLVal.getType()); // Last value of the lastprivate conditional. // decltype(priv_a) last_a; llvm::GlobalVariable *Last = OMPBuilder.getOrCreateInternalVariable( CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); - Last->setAlignment(LVal.getAlignment().getAsAlign()); - LValue LastLVal = CGF.MakeAddrLValue( - Address(Last, Last->getValueType(), LVal.getAlignment()), LVal.getType()); + cast(Last)->setAlignment( + LVal.getAlignment().getAsAlign()); + LValue LastLVal = + CGF.MakeRawAddrLValue(Last, LVal.getType(), LVal.getAlignment()); // Global loop counter. Required to handle inner parallel-for regions. // iv @@ -11871,9 +11882,8 @@ void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( // The variable was not updated in the region - exit. if (!GV) return; - LValue LPLVal = CGF.MakeAddrLValue( - Address(GV, GV->getValueType(), PrivLVal.getAlignment()), - PrivLVal.getType().getNonReferenceType()); + LValue LPLVal = CGF.MakeRawAddrLValue( + GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); CGF.EmitStoreOfScalar(Res, PrivLVal); } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index c3206427b143e12b616bf5b1501ab6c6871870d0..522ae3d35d22d76e269b03ca0d26ef9ecc0b7bd2 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -1068,13 +1068,12 @@ public: /// \param Loc Location of the reference to threadprivate var. /// \return Address of the threadprivate variable for the current thread. virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, - const VarDecl *VD, - Address VDAddr, + const VarDecl *VD, Address VDAddr, SourceLocation Loc); /// Returns the address of the variable marked as declare target with link /// clause OR as declare target with to clause and unified memory. - virtual Address getAddrOfDeclareTargetVar(const VarDecl *VD); + virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD); /// Emit a code for initialization of threadprivate variable. It emits /// a call to runtime library which adds initial value to the newly created diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp index 299ee1460b3db0ef895c681246a8cc7f8bd42fb2..5baac8f0e3e268bf2789014edae018ec0436f557 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp @@ -1096,7 +1096,8 @@ void CGOpenMPRuntimeGPU::emitGenericVarsProlog(CodeGenFunction &CGF, llvm::PointerType *VarPtrTy = CGF.ConvertTypeForMem(VarTy)->getPointerTo(); llvm::Value *CastedVoidPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( VoidPtr, VarPtrTy, VD->getName() + "_on_stack"); - LValue VarAddr = CGF.MakeNaturalAlignAddrLValue(CastedVoidPtr, VarTy); + LValue VarAddr = + CGF.MakeNaturalAlignPointeeRawAddrLValue(CastedVoidPtr, VarTy); Rec.second.PrivateAddr = VarAddr.getAddress(CGF); Rec.second.GlobalizedVal = VoidPtr; @@ -1206,8 +1207,8 @@ void CGOpenMPRuntimeGPU::emitTeamsCall(CodeGenFunction &CGF, bool IsBareKernel = D.getSingleClause(); - Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, - /*Name=*/".zero.addr"); + RawAddress ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, + /*Name=*/".zero.addr"); CGF.Builder.CreateStore(CGF.Builder.getInt32(/*C*/ 0), ZeroAddr); llvm::SmallVector OutlinedFnArgs; // We don't emit any thread id function call in bare kernel, but because the @@ -1215,7 +1216,7 @@ void CGOpenMPRuntimeGPU::emitTeamsCall(CodeGenFunction &CGF, if (IsBareKernel) OutlinedFnArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); else - OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).getPointer()); + OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).emitRawPointer(CGF)); OutlinedFnArgs.push_back(ZeroAddr.getPointer()); OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); @@ -1289,7 +1290,7 @@ void CGOpenMPRuntimeGPU::emitParallelCall(CodeGenFunction &CGF, llvm::ConstantInt::get(CGF.Int32Ty, -1), FnPtr, ID, - Bld.CreateBitOrPointerCast(CapturedVarsAddrs.getPointer(), + Bld.CreateBitOrPointerCast(CapturedVarsAddrs.emitRawPointer(CGF), CGF.VoidPtrPtrTy), llvm::ConstantInt::get(CGM.SizeTy, CapturedVars.size())}; CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( @@ -1503,17 +1504,18 @@ static void shuffleAndStore(CodeGenFunction &CGF, Address SrcAddr, CGF.EmitBlock(PreCondBB); llvm::PHINode *PhiSrc = Bld.CreatePHI(Ptr.getType(), /*NumReservedValues=*/2); - PhiSrc->addIncoming(Ptr.getPointer(), CurrentBB); + PhiSrc->addIncoming(Ptr.emitRawPointer(CGF), CurrentBB); llvm::PHINode *PhiDest = Bld.CreatePHI(ElemPtr.getType(), /*NumReservedValues=*/2); - PhiDest->addIncoming(ElemPtr.getPointer(), CurrentBB); + PhiDest->addIncoming(ElemPtr.emitRawPointer(CGF), CurrentBB); Ptr = Address(PhiSrc, Ptr.getElementType(), Ptr.getAlignment()); ElemPtr = Address(PhiDest, ElemPtr.getElementType(), ElemPtr.getAlignment()); + llvm::Value *PtrEndRaw = PtrEnd.emitRawPointer(CGF); + llvm::Value *PtrRaw = Ptr.emitRawPointer(CGF); llvm::Value *PtrDiff = Bld.CreatePtrDiff( - CGF.Int8Ty, PtrEnd.getPointer(), - Bld.CreatePointerBitCastOrAddrSpaceCast(Ptr.getPointer(), - CGF.VoidPtrTy)); + CGF.Int8Ty, PtrEndRaw, + Bld.CreatePointerBitCastOrAddrSpaceCast(PtrRaw, CGF.VoidPtrTy)); Bld.CreateCondBr(Bld.CreateICmpSGT(PtrDiff, Bld.getInt64(IntSize - 1)), ThenBB, ExitBB); CGF.EmitBlock(ThenBB); @@ -1528,8 +1530,8 @@ static void shuffleAndStore(CodeGenFunction &CGF, Address SrcAddr, TBAAAccessInfo()); Address LocalPtr = Bld.CreateConstGEP(Ptr, 1); Address LocalElemPtr = Bld.CreateConstGEP(ElemPtr, 1); - PhiSrc->addIncoming(LocalPtr.getPointer(), ThenBB); - PhiDest->addIncoming(LocalElemPtr.getPointer(), ThenBB); + PhiSrc->addIncoming(LocalPtr.emitRawPointer(CGF), ThenBB); + PhiDest->addIncoming(LocalElemPtr.emitRawPointer(CGF), ThenBB); CGF.EmitBranch(PreCondBB); CGF.EmitBlock(ExitBB); } else { @@ -1676,10 +1678,10 @@ static void emitReductionListCopy( // scope and that of functions it invokes (i.e., reduce_function). // RemoteReduceData[i] = (void*)&RemoteElem if (UpdateDestListPtr) { - CGF.EmitStoreOfScalar(Bld.CreatePointerBitCastOrAddrSpaceCast( - DestElementAddr.getPointer(), CGF.VoidPtrTy), - DestElementPtrAddr, /*Volatile=*/false, - C.VoidPtrTy); + CGF.EmitStoreOfScalar( + Bld.CreatePointerBitCastOrAddrSpaceCast( + DestElementAddr.emitRawPointer(CGF), CGF.VoidPtrTy), + DestElementPtrAddr, /*Volatile=*/false, C.VoidPtrTy); } ++Idx; @@ -1830,7 +1832,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, // elemptr = ((CopyType*)(elemptrptr)) + I Address ElemPtr(ElemPtrPtr, CopyType, Align); if (NumIters > 1) - ElemPtr = Bld.CreateGEP(ElemPtr, Cnt); + ElemPtr = Bld.CreateGEP(CGF, ElemPtr, Cnt); // Get pointer to location in transfer medium. // MediumPtr = &medium[warp_id] @@ -1894,7 +1896,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, TargetElemPtrPtr, /*Volatile=*/false, C.VoidPtrTy, Loc); Address TargetElemPtr(TargetElemPtrVal, CopyType, Align); if (NumIters > 1) - TargetElemPtr = Bld.CreateGEP(TargetElemPtr, Cnt); + TargetElemPtr = Bld.CreateGEP(CGF, TargetElemPtr, Cnt); // *TargetElemPtr = SrcMediumVal; llvm::Value *SrcMediumValue = @@ -2105,9 +2107,9 @@ static llvm::Function *emitShuffleAndReduceFunction( CGF.EmitBlock(ThenBB); // reduce_function(LocalReduceList, RemoteReduceList) llvm::Value *LocalReduceListPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( - LocalReduceList.getPointer(), CGF.VoidPtrTy); + LocalReduceList.emitRawPointer(CGF), CGF.VoidPtrTy); llvm::Value *RemoteReduceListPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( - RemoteReduceList.getPointer(), CGF.VoidPtrTy); + RemoteReduceList.emitRawPointer(CGF), CGF.VoidPtrTy); CGM.getOpenMPRuntime().emitOutlinedFunctionCall( CGF, Loc, ReduceFn, {LocalReduceListPtr, RemoteReduceListPtr}); Bld.CreateBr(MergeBB); @@ -2218,9 +2220,9 @@ static llvm::Value *emitListToGlobalCopyFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - GlobLVal.setAddress(Address(GlobAddr.getPointer(), + GlobLVal.setAddress(Address(GlobAddr.emitRawPointer(CGF), CGF.ConvertTypeForMem(Private->getType()), GlobAddr.getAlignment())); switch (CGF.getEvaluationKind(Private->getType())) { @@ -2304,7 +2306,7 @@ static llvm::Value *emitListToGlobalReduceFunction( // 1. Build a list of reduction variables. // void *RedList[] = {[0], ..., [-1]}; - Address ReductionList = + RawAddress ReductionList = CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); auto IPriv = Privates.begin(); llvm::Value *Idxs[] = {CGF.EmitLoadOfScalar(CGF.GetAddrOfLocalVar(&IdxArg), @@ -2319,10 +2321,10 @@ static llvm::Value *emitListToGlobalReduceFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - CGF.EmitStoreOfScalar(GlobAddr.getPointer(), Elem, /*Volatile=*/false, - C.VoidPtrTy); + CGF.EmitStoreOfScalar(GlobAddr.emitRawPointer(CGF), Elem, + /*Volatile=*/false, C.VoidPtrTy); if ((*IPriv)->getType()->isVariablyModifiedType()) { // Store array size. ++Idx; @@ -2425,9 +2427,9 @@ static llvm::Value *emitGlobalToListCopyFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - GlobLVal.setAddress(Address(GlobAddr.getPointer(), + GlobLVal.setAddress(Address(GlobAddr.emitRawPointer(CGF), CGF.ConvertTypeForMem(Private->getType()), GlobAddr.getAlignment())); switch (CGF.getEvaluationKind(Private->getType())) { @@ -2526,10 +2528,10 @@ static llvm::Value *emitGlobalToListReduceFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - CGF.EmitStoreOfScalar(GlobAddr.getPointer(), Elem, /*Volatile=*/false, - C.VoidPtrTy); + CGF.EmitStoreOfScalar(GlobAddr.emitRawPointer(CGF), Elem, + /*Volatile=*/false, C.VoidPtrTy); if ((*IPriv)->getType()->isVariablyModifiedType()) { // Store array size. ++Idx; @@ -2545,7 +2547,7 @@ static llvm::Value *emitGlobalToListReduceFunction( } // Call reduce_function(ReduceList, GlobalReduceList) - llvm::Value *GlobalReduceList = ReductionList.getPointer(); + llvm::Value *GlobalReduceList = ReductionList.emitRawPointer(CGF); Address AddrReduceListArg = CGF.GetAddrOfLocalVar(&ReduceListArg); llvm::Value *ReducedPtr = CGF.EmitLoadOfScalar( AddrReduceListArg, /*Volatile=*/false, C.VoidPtrTy, Loc); @@ -2876,7 +2878,7 @@ void CGOpenMPRuntimeGPU::emitReduction( } llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - ReductionList.getPointer(), CGF.VoidPtrTy); + ReductionList.emitRawPointer(CGF), CGF.VoidPtrTy); llvm::Function *ReductionFn = emitReductionFunction( CGF.CurFn->getName(), Loc, CGF.ConvertTypeForMem(ReductionArrayTy), Privates, LHSExprs, RHSExprs, ReductionOps); @@ -3106,15 +3108,15 @@ llvm::Function *CGOpenMPRuntimeGPU::createParallelDataSharingWrapper( // Get the array of arguments. SmallVector Args; - Args.emplace_back(CGF.GetAddrOfLocalVar(&WrapperArg).getPointer()); - Args.emplace_back(ZeroAddr.getPointer()); + Args.emplace_back(CGF.GetAddrOfLocalVar(&WrapperArg).emitRawPointer(CGF)); + Args.emplace_back(ZeroAddr.emitRawPointer(CGF)); CGBuilderTy &Bld = CGF.Builder; auto CI = CS.capture_begin(); // Use global memory for data sharing. // Handle passing of global args to workers. - Address GlobalArgs = + RawAddress GlobalArgs = CGF.CreateDefaultAlignTempAlloca(CGF.VoidPtrPtrTy, "global_args"); llvm::Value *GlobalArgsPtr = GlobalArgs.getPointer(); llvm::Value *DataSharingArgs[] = {GlobalArgsPtr}; @@ -3400,7 +3402,7 @@ void CGOpenMPRuntimeGPU::adjustTargetSpecificDataForLambdas( VDAddr = CGF.EmitLoadOfReferenceLValue(VDAddr, VD->getType().getCanonicalType()) .getAddress(CGF); - CGF.EmitStoreOfScalar(VDAddr.getPointer(), VarLVal); + CGF.EmitStoreOfScalar(VDAddr.emitRawPointer(CGF), VarLVal); } } } diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index cb5a004e4f4a6cf802758169cb211728b6d0e42e..576fe2f7a2d46f41aa6c60b4139a28753fd3314f 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -2294,7 +2294,7 @@ std::pair CodeGenFunction::EmitAsmInputLValue( Address Addr = InputValue.getAddress(*this); ConstraintStr += '*'; - return {Addr.getPointer(), Addr.getElementType()}; + return {InputValue.getPointer(*this), Addr.getElementType()}; } std::pair @@ -2701,7 +2701,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { ArgTypes.push_back(DestAddr.getType()); ArgElemTypes.push_back(DestAddr.getElementType()); - Args.push_back(DestAddr.getPointer()); + Args.push_back(DestAddr.emitRawPointer(*this)); Constraints += "=*"; Constraints += OutputConstraint; ReadOnly = ReadNone = false; @@ -3076,8 +3076,8 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) { CapturedStmtInfo->setContextValue(Builder.CreateLoad(DeclPtr)); // Initialize variable-length arrays. - LValue Base = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getContextValue(), - Ctx.getTagDeclType(RD)); + LValue Base = MakeNaturalAlignRawAddrLValue( + CapturedStmtInfo->getContextValue(), Ctx.getTagDeclType(RD)); for (auto *FD : RD->fields()) { if (FD->hasCapturedVLAType()) { auto *ExprArg = diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index f37ac549d10a827ea0ad5b71fc656d0240d6c03a..e6d504bcdeca5b4e86d7f04974e8dd4713c2d0c0 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -350,7 +350,8 @@ void CodeGenFunction::GenerateOpenMPCapturedVars( LValue DstLV = MakeAddrLValue(DstAddr, Ctx.getUIntPtrType()); llvm::Value *SrcAddrVal = EmitScalarConversion( - DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()), + DstAddr.emitRawPointer(*this), + Ctx.getPointerType(Ctx.getUIntPtrType()), Ctx.getPointerType(CurField->getType()), CurCap->getLocation()); LValue SrcLV = MakeNaturalAlignAddrLValue(SrcAddrVal, CurField->getType()); @@ -364,7 +365,8 @@ void CodeGenFunction::GenerateOpenMPCapturedVars( CapturedVars.push_back(CV); } else { assert(CurCap->capturesVariable() && "Expected capture by reference."); - CapturedVars.push_back(EmitLValue(*I).getAddress(*this).getPointer()); + CapturedVars.push_back( + EmitLValue(*I).getAddress(*this).emitRawPointer(*this)); } } } @@ -375,8 +377,9 @@ static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, ASTContext &Ctx = CGF.getContext(); llvm::Value *CastedPtr = CGF.EmitScalarConversion( - AddrLV.getAddress(CGF).getPointer(), Ctx.getUIntPtrType(), + AddrLV.getAddress(CGF).emitRawPointer(CGF), Ctx.getUIntPtrType(), Ctx.getPointerType(DstType), Loc); + // FIXME: should the pointee type (DstType) be passed? Address TmpAddr = CGF.MakeNaturalAlignAddrLValue(CastedPtr, DstType).getAddress(CGF); return TmpAddr; @@ -702,8 +705,8 @@ void CodeGenFunction::EmitOMPAggregateAssign( llvm::Value *NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr); SrcAddr = SrcAddr.withElementType(DestAddr.getElementType()); - llvm::Value *SrcBegin = SrcAddr.getPointer(); - llvm::Value *DestBegin = DestAddr.getPointer(); + llvm::Value *SrcBegin = SrcAddr.emitRawPointer(*this); + llvm::Value *DestBegin = DestAddr.emitRawPointer(*this); // Cast from pointer to array type to pointer to single element. llvm::Value *DestEnd = Builder.CreateInBoundsGEP(DestAddr.getElementType(), DestBegin, NumElements); @@ -1007,10 +1010,10 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) { CopyBegin = createBasicBlock("copyin.not.master"); CopyEnd = createBasicBlock("copyin.not.master.end"); // TODO: Avoid ptrtoint conversion. - auto *MasterAddrInt = - Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy); - auto *PrivateAddrInt = - Builder.CreatePtrToInt(PrivateAddr.getPointer(), CGM.IntPtrTy); + auto *MasterAddrInt = Builder.CreatePtrToInt( + MasterAddr.emitRawPointer(*this), CGM.IntPtrTy); + auto *PrivateAddrInt = Builder.CreatePtrToInt( + PrivateAddr.emitRawPointer(*this), CGM.IntPtrTy); Builder.CreateCondBr( Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin, CopyEnd); @@ -1666,7 +1669,7 @@ Address CodeGenFunction::OMPBuilderCBHelpers::getAddrOfThreadPrivate( llvm::Type *VarTy = VDAddr.getElementType(); llvm::Value *Data = - CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.Int8PtrTy); + CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.Int8PtrTy); llvm::ConstantInt *Size = CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)); std::string Suffix = getNameWithSeparators({"cache", ""}); llvm::Twine CacheName = Twine(CGM.getMangledName(VD)).concat(Suffix); @@ -2045,7 +2048,7 @@ void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) { ->getParam(0) ->getType() .getNonReferenceType(); - Address CountAddr = CreateMemTemp(LogicalTy, ".count.addr"); + RawAddress CountAddr = CreateMemTemp(LogicalTy, ".count.addr"); emitCapturedStmtCall(*this, DistanceClosure, {CountAddr.getPointer()}); llvm::Value *DistVal = Builder.CreateLoad(CountAddr, ".count"); @@ -2061,7 +2064,7 @@ void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) { LValue LCVal = EmitLValue(LoopVarRef); Address LoopVarAddress = LCVal.getAddress(*this); emitCapturedStmtCall(*this, LoopVarClosure, - {LoopVarAddress.getPointer(), IndVar}); + {LoopVarAddress.emitRawPointer(*this), IndVar}); RunCleanupsScope BodyScope(*this); EmitStmt(BodyStmt); @@ -4795,7 +4798,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( ParamTypes.push_back(PrivatesPtr->getType()); for (const Expr *E : Data.PrivateVars) { const auto *VD = cast(cast(E)->getDecl()); - Address PrivatePtr = CGF.CreateMemTemp( + RawAddress PrivatePtr = CGF.CreateMemTemp( CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); CallArgs.push_back(PrivatePtr.getPointer()); @@ -4803,7 +4806,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( } for (const Expr *E : Data.FirstprivateVars) { const auto *VD = cast(cast(E)->getDecl()); - Address PrivatePtr = + RawAddress PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".firstpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -4813,7 +4816,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( } for (const Expr *E : Data.LastprivateVars) { const auto *VD = cast(cast(E)->getDecl()); - Address PrivatePtr = + RawAddress PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".lastpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -4826,7 +4829,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( Ty = CGF.getContext().getPointerType(Ty); if (isAllocatableDecl(VD)) Ty = CGF.getContext().getPointerType(Ty); - Address PrivatePtr = CGF.CreateMemTemp( + RawAddress PrivatePtr = CGF.CreateMemTemp( CGF.getContext().getPointerType(Ty), ".local.ptr.addr"); auto Result = UntiedLocalVars.insert( std::make_pair(VD, std::make_pair(PrivatePtr, Address::invalid()))); @@ -4859,7 +4862,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( if (auto *DI = CGF.getDebugInfo()) if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo()) (void)DI->EmitDeclareOfAutoVariable( - Pair.first, Pair.second.getPointer(), CGF.Builder, + Pair.first, Pair.second.getBasePointer(), CGF.Builder, /*UsePointerValue*/ true); } // Adjust mapping for internal locals by mapping actual memory instead of @@ -4912,14 +4915,14 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( RedCG, Cnt); Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); - Replacement = - Address(CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, - CGF.getContext().getPointerType( - Data.ReductionCopies[Cnt]->getType()), - Data.ReductionCopies[Cnt]->getExprLoc()), - CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), - Replacement.getAlignment()); + Replacement = Address( + CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF), + CGF.getContext().VoidPtrTy, + CGF.getContext().getPointerType( + Data.ReductionCopies[Cnt]->getType()), + Data.ReductionCopies[Cnt]->getExprLoc()), + CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), + Replacement.getAlignment()); Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement); } @@ -4970,7 +4973,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); Replacement = Address( CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, + Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy, CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()), InRedPrivs[Cnt]->getExprLoc()), CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()), @@ -5089,7 +5092,7 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective( // If there is no user-defined mapper, the mapper array will be nullptr. In // this case, we don't need to privatize it. if (!isa_and_nonnull( - InputInfo.MappersArray.getPointer())) { + InputInfo.MappersArray.emitRawPointer(*this))) { MVD = createImplicitFirstprivateForType( getContext(), Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc()); TargetScope.addPrivate(MVD, InputInfo.MappersArray); @@ -5115,7 +5118,7 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective( ParamTypes.push_back(PrivatesPtr->getType()); for (const Expr *E : Data.FirstprivateVars) { const auto *VD = cast(cast(E)->getDecl()); - Address PrivatePtr = + RawAddress PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".firstpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -5194,14 +5197,14 @@ void CodeGenFunction::processInReduction(const OMPExecutableDirective &S, RedCG, Cnt); Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); - Replacement = - Address(CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, - CGF.getContext().getPointerType( - Data.ReductionCopies[Cnt]->getType()), - Data.ReductionCopies[Cnt]->getExprLoc()), - CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), - Replacement.getAlignment()); + Replacement = Address( + CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF), + CGF.getContext().VoidPtrTy, + CGF.getContext().getPointerType( + Data.ReductionCopies[Cnt]->getType()), + Data.ReductionCopies[Cnt]->getExprLoc()), + CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), + Replacement.getAlignment()); Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement); } @@ -5247,7 +5250,7 @@ void CodeGenFunction::processInReduction(const OMPExecutableDirective &S, CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); Replacement = Address( CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, + Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy, CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()), InRedPrivs[Cnt]->getExprLoc()), CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()), @@ -5394,7 +5397,7 @@ void CodeGenFunction::EmitOMPDepobjDirective(const OMPDepobjDirective &S) { Dependencies.DepExprs.append(DC->varlist_begin(), DC->varlist_end()); Address DepAddr = CGM.getOpenMPRuntime().emitDepobjDependClause( *this, Dependencies, DC->getBeginLoc()); - EmitStoreOfScalar(DepAddr.getPointer(), DOLVal); + EmitStoreOfScalar(DepAddr.emitRawPointer(*this), DOLVal); return; } if (const auto *DC = S.getSingleClause()) { @@ -6471,21 +6474,21 @@ static void emitOMPAtomicCompareExpr( D->getType()->hasSignedIntegerRepresentation()); llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{ - XAddr.getPointer(), XAddr.getElementType(), + XAddr.emitRawPointer(CGF), XAddr.getElementType(), X->getType()->hasSignedIntegerRepresentation(), X->getType().isVolatileQualified()}; llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal; if (V) { LValue LV = CGF.EmitLValue(V); Address Addr = LV.getAddress(CGF); - VOpVal = {Addr.getPointer(), Addr.getElementType(), + VOpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(), V->getType()->hasSignedIntegerRepresentation(), V->getType().isVolatileQualified()}; } if (R) { LValue LV = CGF.EmitLValue(R); Address Addr = LV.getAddress(CGF); - ROpVal = {Addr.getPointer(), Addr.getElementType(), + ROpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(), R->getType()->hasSignedIntegerRepresentation(), R->getType().isVolatileQualified()}; } @@ -7029,7 +7032,7 @@ void CodeGenFunction::EmitOMPInteropDirective(const OMPInteropDirective &S) { std::tie(NumDependences, DependenciesArray) = CGM.getOpenMPRuntime().emitDependClause(*this, Data.Dependences, S.getBeginLoc()); - DependenceList = DependenciesArray.getPointer(); + DependenceList = DependenciesArray.emitRawPointer(*this); } Data.HasNowaitClause = S.hasClausesOfKind(); diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 8dee3f74b44b4e66edfc8b2ffd1c41514671496b..862369ae009f4808c73cc0b32cd11101261fd4ba 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -201,14 +201,13 @@ CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn, // Find the first store of "this", which will be to the alloca associated // with "this". - Address ThisPtr = - Address(&*AI, ConvertTypeForMem(MD->getFunctionObjectParameterType()), - CGM.getClassPointerAlignment(MD->getParent())); + Address ThisPtr = makeNaturalAddressForPointer( + &*AI, MD->getFunctionObjectParameterType(), + CGM.getClassPointerAlignment(MD->getParent())); llvm::BasicBlock *EntryBB = &Fn->front(); llvm::BasicBlock::iterator ThisStore = llvm::find_if(*EntryBB, [&](llvm::Instruction &I) { - return isa(I) && - I.getOperand(0) == ThisPtr.getPointer(); + return isa(I) && I.getOperand(0) == &*AI; }); assert(ThisStore != EntryBB->end() && "Store of this should be in entry block?"); diff --git a/clang/lib/CodeGen/CGValue.h b/clang/lib/CodeGen/CGValue.h index 1e6f67250583d66fda9c2552d61ce1e9ea629695..cc9ad10ae5969df3c30eac0f9db5234349af9ae6 100644 --- a/clang/lib/CodeGen/CGValue.h +++ b/clang/lib/CodeGen/CGValue.h @@ -14,12 +14,13 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_CGVALUE_H #define LLVM_CLANG_LIB_CODEGEN_CGVALUE_H +#include "Address.h" +#include "CodeGenTBAA.h" +#include "EHScopeStack.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Type.h" -#include "llvm/IR/Value.h" #include "llvm/IR/Type.h" -#include "Address.h" -#include "CodeGenTBAA.h" +#include "llvm/IR/Value.h" namespace llvm { class Constant; @@ -28,57 +29,64 @@ namespace llvm { namespace clang { namespace CodeGen { - class AggValueSlot; - class CodeGenFunction; - struct CGBitFieldInfo; +class AggValueSlot; +class CGBuilderTy; +class CodeGenFunction; +struct CGBitFieldInfo; /// RValue - This trivial value class is used to represent the result of an /// expression that is evaluated. It can be one of three things: either a /// simple LLVM SSA value, a pair of SSA values for complex numbers, or the /// address of an aggregate value in memory. class RValue { - enum Flavor { Scalar, Complex, Aggregate }; + friend struct DominatingValue; - // The shift to make to an aggregate's alignment to make it look - // like a pointer. - enum { AggAlignShift = 4 }; + enum FlavorEnum { Scalar, Complex, Aggregate }; - // Stores first value and flavor. - llvm::PointerIntPair V1; - // Stores second value and volatility. - llvm::PointerIntPair V2; - // Stores element type for aggregate values. - llvm::Type *ElementType; + union { + // Stores first and second value. + struct { + llvm::Value *first; + llvm::Value *second; + } Vals; + + // Stores aggregate address. + Address AggregateAddr; + }; + + unsigned IsVolatile : 1; + unsigned Flavor : 2; public: - bool isScalar() const { return V1.getInt() == Scalar; } - bool isComplex() const { return V1.getInt() == Complex; } - bool isAggregate() const { return V1.getInt() == Aggregate; } + RValue() : Vals{nullptr, nullptr}, Flavor(Scalar) {} + + bool isScalar() const { return Flavor == Scalar; } + bool isComplex() const { return Flavor == Complex; } + bool isAggregate() const { return Flavor == Aggregate; } - bool isVolatileQualified() const { return V2.getInt(); } + bool isVolatileQualified() const { return IsVolatile; } /// getScalarVal() - Return the Value* of this scalar value. llvm::Value *getScalarVal() const { assert(isScalar() && "Not a scalar!"); - return V1.getPointer(); + return Vals.first; } /// getComplexVal - Return the real/imag components of this complex value. /// std::pair getComplexVal() const { - return std::make_pair(V1.getPointer(), V2.getPointer()); + return std::make_pair(Vals.first, Vals.second); } /// getAggregateAddr() - Return the Value* of the address of the aggregate. Address getAggregateAddress() const { assert(isAggregate() && "Not an aggregate!"); - auto align = reinterpret_cast(V2.getPointer()) >> AggAlignShift; - return Address( - V1.getPointer(), ElementType, CharUnits::fromQuantity(align)); + return AggregateAddr; } - llvm::Value *getAggregatePointer() const { - assert(isAggregate() && "Not an aggregate!"); - return V1.getPointer(); + + llvm::Value *getAggregatePointer(QualType PointeeType, + CodeGenFunction &CGF) const { + return getAggregateAddress().getBasePointer(); } static RValue getIgnored() { @@ -88,17 +96,19 @@ public: static RValue get(llvm::Value *V) { RValue ER; - ER.V1.setPointer(V); - ER.V1.setInt(Scalar); - ER.V2.setInt(false); + ER.Vals.first = V; + ER.Flavor = Scalar; + ER.IsVolatile = false; return ER; } + static RValue get(Address Addr, CodeGenFunction &CGF) { + return RValue::get(Addr.emitRawPointer(CGF)); + } static RValue getComplex(llvm::Value *V1, llvm::Value *V2) { RValue ER; - ER.V1.setPointer(V1); - ER.V2.setPointer(V2); - ER.V1.setInt(Complex); - ER.V2.setInt(false); + ER.Vals = {V1, V2}; + ER.Flavor = Complex; + ER.IsVolatile = false; return ER; } static RValue getComplex(const std::pair &C) { @@ -107,15 +117,15 @@ public: // FIXME: Aggregate rvalues need to retain information about whether they are // volatile or not. Remove default to find all places that probably get this // wrong. + + /// Convert an Address to an RValue. If the Address is not + /// signed, create an RValue using the unsigned address. Otherwise, resign the + /// address using the provided type. static RValue getAggregate(Address addr, bool isVolatile = false) { RValue ER; - ER.V1.setPointer(addr.getPointer()); - ER.V1.setInt(Aggregate); - ER.ElementType = addr.getElementType(); - - auto align = static_cast(addr.getAlignment().getQuantity()); - ER.V2.setPointer(reinterpret_cast(align << AggAlignShift)); - ER.V2.setInt(isVolatile); + ER.AggregateAddr = addr; + ER.Flavor = Aggregate; + ER.IsVolatile = isVolatile; return ER; } }; @@ -178,8 +188,10 @@ class LValue { MatrixElt // This is a matrix element, use getVector* } LVType; - llvm::Value *V; - llvm::Type *ElementType; + union { + Address Addr = Address::invalid(); + llvm::Value *V; + }; union { // Index into a vector subscript: V[i] @@ -197,10 +209,6 @@ class LValue { // 'const' is unused here Qualifiers Quals; - // The alignment to use when accessing this lvalue. (For vector elements, - // this is the alignment of the whole vector.) - unsigned Alignment; - // objective-c's ivar bool Ivar:1; @@ -234,23 +242,19 @@ class LValue { Expr *BaseIvarExp; private: - void Initialize(QualType Type, Qualifiers Quals, CharUnits Alignment, + void Initialize(QualType Type, Qualifiers Quals, Address Addr, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { - assert((!Alignment.isZero() || Type->isIncompleteType()) && - "initializing l-value with zero alignment!"); - if (isGlobalReg()) - assert(ElementType == nullptr && "Global reg does not store elem type"); - else - assert(ElementType != nullptr && "Must have elem type"); - this->Type = Type; this->Quals = Quals; const unsigned MaxAlign = 1U << 31; - this->Alignment = Alignment.getQuantity() <= MaxAlign - ? Alignment.getQuantity() - : MaxAlign; - assert(this->Alignment == Alignment.getQuantity() && - "Alignment exceeds allowed max!"); + CharUnits Alignment = Addr.getAlignment(); + assert((isGlobalReg() || !Alignment.isZero() || Type->isIncompleteType()) && + "initializing l-value with zero alignment!"); + if (Alignment.getQuantity() > MaxAlign) { + assert(false && "Alignment exceeds allowed max!"); + Alignment = CharUnits::fromQuantity(MaxAlign); + } + this->Addr = Addr; this->BaseInfo = BaseInfo; this->TBAAInfo = TBAAInfo; @@ -259,9 +263,20 @@ private: this->ImpreciseLifetime = false; this->Nontemporal = false; this->ThreadLocalRef = false; + this->IsKnownNonNull = false; this->BaseIvarExp = nullptr; } + void initializeSimpleLValue(Address Addr, QualType Type, + LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, + ASTContext &Context) { + Qualifiers QS = Type.getQualifiers(); + QS.setObjCGCAttr(Context.getObjCGCAttrKind(Type)); + LVType = Simple; + Initialize(Type, QS, Addr, BaseInfo, TBAAInfo); + assert(Addr.getBasePointer()->getType()->isPointerTy()); + } + public: bool isSimple() const { return LVType == Simple; } bool isVectorElt() const { return LVType == VectorElt; } @@ -328,8 +343,8 @@ public: LangAS getAddressSpace() const { return Quals.getAddressSpace(); } - CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); } - void setAlignment(CharUnits A) { Alignment = A.getQuantity(); } + CharUnits getAlignment() const { return Addr.getAlignment(); } + void setAlignment(CharUnits A) { Addr.setAlignment(A); } LValueBaseInfo getBaseInfo() const { return BaseInfo; } void setBaseInfo(LValueBaseInfo Info) { BaseInfo = Info; } @@ -345,28 +360,32 @@ public: // simple lvalue llvm::Value *getPointer(CodeGenFunction &CGF) const { assert(isSimple()); - return V; + return Addr.getBasePointer(); } - Address getAddress(CodeGenFunction &CGF) const { - return Address(getPointer(CGF), ElementType, getAlignment(), - isKnownNonNull()); - } - void setAddress(Address address) { + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { assert(isSimple()); - V = address.getPointer(); - ElementType = address.getElementType(); - Alignment = address.getAlignment().getQuantity(); - IsKnownNonNull = address.isKnownNonNull(); + return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; } + Address getAddress(CodeGenFunction &CGF) const { + // FIXME: remove parameter. + return Addr; + } + + void setAddress(Address address) { Addr = address; } + // vector elt lvalue Address getVectorAddress() const { - return Address(getVectorPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isVectorElt()); + return Addr; + } + llvm::Value *getRawVectorPointer(CodeGenFunction &CGF) const { + assert(isVectorElt()); + return Addr.emitRawPointer(CGF); } llvm::Value *getVectorPointer() const { assert(isVectorElt()); - return V; + return Addr.getBasePointer(); } llvm::Value *getVectorIdx() const { assert(isVectorElt()); @@ -374,12 +393,12 @@ public: } Address getMatrixAddress() const { - return Address(getMatrixPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isMatrixElt()); + return Addr; } llvm::Value *getMatrixPointer() const { assert(isMatrixElt()); - return V; + return Addr.getBasePointer(); } llvm::Value *getMatrixIdx() const { assert(isMatrixElt()); @@ -388,12 +407,12 @@ public: // extended vector elements. Address getExtVectorAddress() const { - return Address(getExtVectorPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isExtVectorElt()); + return Addr; } - llvm::Value *getExtVectorPointer() const { + llvm::Value *getRawExtVectorPointer(CodeGenFunction &CGF) const { assert(isExtVectorElt()); - return V; + return Addr.emitRawPointer(CGF); } llvm::Constant *getExtVectorElts() const { assert(isExtVectorElt()); @@ -402,10 +421,14 @@ public: // bitfield lvalue Address getBitFieldAddress() const { - return Address(getBitFieldPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isBitField()); + return Addr; + } + llvm::Value *getRawBitFieldPointer(CodeGenFunction &CGF) const { + assert(isBitField()); + return Addr.emitRawPointer(CGF); } - llvm::Value *getBitFieldPointer() const { assert(isBitField()); return V; } + const CGBitFieldInfo &getBitFieldInfo() const { assert(isBitField()); return *BitFieldInfo; @@ -414,18 +437,13 @@ public: // global register lvalue llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; } - static LValue MakeAddr(Address address, QualType type, ASTContext &Context, + static LValue MakeAddr(Address Addr, QualType type, ASTContext &Context, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { - Qualifiers qs = type.getQualifiers(); - qs.setObjCGCAttr(Context.getObjCGCAttrKind(type)); - LValue R; R.LVType = Simple; - assert(address.getPointer()->getType()->isPointerTy()); - R.V = address.getPointer(); - R.ElementType = address.getElementType(); - R.IsKnownNonNull = address.isKnownNonNull(); - R.Initialize(type, qs, address.getAlignment(), BaseInfo, TBAAInfo); + R.initializeSimpleLValue(Addr, type, BaseInfo, TBAAInfo, Context); + R.Addr = Addr; + assert(Addr.getType()->isPointerTy()); return R; } @@ -434,26 +452,18 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = VectorElt; - R.V = vecAddress.getPointer(); - R.ElementType = vecAddress.getElementType(); R.VectorIdx = Idx; - R.IsKnownNonNull = vecAddress.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - BaseInfo, TBAAInfo); + R.Initialize(type, type.getQualifiers(), vecAddress, BaseInfo, TBAAInfo); return R; } - static LValue MakeExtVectorElt(Address vecAddress, llvm::Constant *Elts, + static LValue MakeExtVectorElt(Address Addr, llvm::Constant *Elts, QualType type, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = ExtVectorElt; - R.V = vecAddress.getPointer(); - R.ElementType = vecAddress.getElementType(); R.VectorElts = Elts; - R.IsKnownNonNull = vecAddress.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - BaseInfo, TBAAInfo); + R.Initialize(type, type.getQualifiers(), Addr, BaseInfo, TBAAInfo); return R; } @@ -468,12 +478,8 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = BitField; - R.V = Addr.getPointer(); - R.ElementType = Addr.getElementType(); R.BitFieldInfo = &Info; - R.IsKnownNonNull = Addr.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), BaseInfo, - TBAAInfo); + R.Initialize(type, type.getQualifiers(), Addr, BaseInfo, TBAAInfo); return R; } @@ -481,11 +487,9 @@ public: QualType type) { LValue R; R.LVType = GlobalReg; - R.V = V; - R.ElementType = nullptr; - R.IsKnownNonNull = true; - R.Initialize(type, type.getQualifiers(), alignment, + R.Initialize(type, type.getQualifiers(), Address::invalid(), LValueBaseInfo(AlignmentSource::Decl), TBAAAccessInfo()); + R.V = V; return R; } @@ -494,12 +498,8 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = MatrixElt; - R.V = matAddress.getPointer(); - R.ElementType = matAddress.getElementType(); R.VectorIdx = Idx; - R.IsKnownNonNull = matAddress.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), matAddress.getAlignment(), - BaseInfo, TBAAInfo); + R.Initialize(type, type.getQualifiers(), matAddress, BaseInfo, TBAAInfo); return R; } @@ -643,17 +643,17 @@ public: return NeedsGCBarriers_t(ObjCGCFlag); } - llvm::Value *getPointer() const { - return Addr.getPointer(); + llvm::Value *getPointer(QualType PointeeTy, CodeGenFunction &CGF) const; + + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { + return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; } Address getAddress() const { return Addr; } - bool isIgnored() const { - return !Addr.isValid(); - } + bool isIgnored() const { return !Addr.isValid(); } CharUnits getAlignment() const { return Addr.getAlignment(); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index fad26c43da3d348b7ea2970bba1377d24c29d107..44103884940fd9e4cd1e69dc5dcbdae300d5fb79 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -193,26 +193,35 @@ CodeGenFunction::CGFPOptionsRAII::~CGFPOptionsRAII() { CGF.Builder.setDefaultConstrainedRounding(OldRounding); } -LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { +static LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, + bool ForPointeeType, + CodeGenFunction &CGF) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; - CharUnits Alignment = CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo); - Address Addr(V, ConvertTypeForMem(T), Alignment); - return LValue::MakeAddr(Addr, T, getContext(), BaseInfo, TBAAInfo); + CharUnits Alignment = + CGF.CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, ForPointeeType); + Address Addr = Address(V, CGF.ConvertTypeForMem(T), Alignment); + return CGF.MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo); +} + +LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, *this); } -/// Given a value of type T* that may not be to a complete object, -/// construct an l-value with the natural pointee alignment of T. LValue CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) { - LValueBaseInfo BaseInfo; - TBAAAccessInfo TBAAInfo; - CharUnits Align = CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, - /* forPointeeType= */ true); - Address Addr(V, ConvertTypeForMem(T), Align); - return MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo); + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, *this); +} + +LValue CodeGenFunction::MakeNaturalAlignRawAddrLValue(llvm::Value *V, + QualType T) { + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, *this); } +LValue CodeGenFunction::MakeNaturalAlignPointeeRawAddrLValue(llvm::Value *V, + QualType T) { + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, *this); +} llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) { return CGM.getTypes().ConvertTypeForMem(T); @@ -525,7 +534,8 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { ReturnBlock.getBlock()->eraseFromParent(); } if (ReturnValue.isValid()) { - auto *RetAlloca = dyn_cast(ReturnValue.getPointer()); + auto *RetAlloca = + dyn_cast(ReturnValue.emitRawPointer(*this)); if (RetAlloca && RetAlloca->use_empty()) { RetAlloca->eraseFromParent(); ReturnValue = Address::invalid(); @@ -1122,13 +1132,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, auto AI = CurFn->arg_begin(); if (CurFnInfo->getReturnInfo().isSRetAfterThis()) ++AI; - ReturnValue = - Address(&*AI, ConvertType(RetTy), - CurFnInfo->getReturnInfo().getIndirectAlign(), KnownNonNull); + ReturnValue = makeNaturalAddressForPointer( + &*AI, RetTy, CurFnInfo->getReturnInfo().getIndirectAlign(), false, + nullptr, nullptr, KnownNonNull); if (!CurFnInfo->getReturnInfo().getIndirectByVal()) { - ReturnValuePointer = CreateDefaultAlignTempAlloca( - ReturnValue.getPointer()->getType(), "result.ptr"); - Builder.CreateStore(ReturnValue.getPointer(), ReturnValuePointer); + ReturnValuePointer = + CreateDefaultAlignTempAlloca(ReturnValue.getType(), "result.ptr"); + Builder.CreateStore(ReturnValue.emitRawPointer(*this), + ReturnValuePointer); } } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::InAlloca && !hasScalarEvaluationKind(CurFnInfo->getReturnType())) { @@ -1189,8 +1200,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, // or contains the address of the enclosing object). LValue ThisFieldLValue = EmitLValueForLambdaField(LambdaThisCaptureField); if (!LambdaThisCaptureField->getType()->isPointerType()) { - // If the enclosing object was captured by value, just use its address. - CXXThisValue = ThisFieldLValue.getAddress(*this).getPointer(); + // If the enclosing object was captured by value, just use its + // address. Sign this pointer. + CXXThisValue = ThisFieldLValue.getPointer(*this); } else { // Load the lvalue pointed to by the field, since '*this' was captured // by reference. @@ -2012,8 +2024,9 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType, = llvm::ConstantInt::get(CGF.IntPtrTy, baseSize.getQuantity()); Address begin = dest.withElementType(CGF.Int8Ty); - llvm::Value *end = Builder.CreateInBoundsGEP( - begin.getElementType(), begin.getPointer(), sizeInChars, "vla.end"); + llvm::Value *end = Builder.CreateInBoundsGEP(begin.getElementType(), + begin.emitRawPointer(CGF), + sizeInChars, "vla.end"); llvm::BasicBlock *originBB = CGF.Builder.GetInsertBlock(); llvm::BasicBlock *loopBB = CGF.createBasicBlock("vla-init.loop"); @@ -2024,7 +2037,7 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType, CGF.EmitBlock(loopBB); llvm::PHINode *cur = Builder.CreatePHI(begin.getType(), 2, "vla.cur"); - cur->addIncoming(begin.getPointer(), originBB); + cur->addIncoming(begin.emitRawPointer(CGF), originBB); CharUnits curAlign = dest.getAlignment().alignmentOfArrayElement(baseSize); @@ -2189,8 +2202,8 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType, dyn_cast(addr.getElementType()); while (llvmArrayType) { assert(isa(arrayType)); - assert(cast(arrayType)->getSize().getZExtValue() - == llvmArrayType->getNumElements()); + assert(cast(arrayType)->getZExtSize() == + llvmArrayType->getNumElements()); gepIndices.push_back(zero); countFromCLAs *= llvmArrayType->getNumElements(); @@ -2208,8 +2221,7 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType, // as some other type (probably a packed struct). Compute the array // size, and just emit the 'begin' expression as a bitcast. while (arrayType) { - countFromCLAs *= - cast(arrayType)->getSize().getZExtValue(); + countFromCLAs *= cast(arrayType)->getZExtSize(); eltType = arrayType->getElementType(); arrayType = getContext().getAsArrayType(eltType); } @@ -2218,10 +2230,10 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType, addr = addr.withElementType(baseType); } else { // Create the actual GEP. - addr = Address(Builder.CreateInBoundsGEP( - addr.getElementType(), addr.getPointer(), gepIndices, "array.begin"), - ConvertTypeForMem(eltType), - addr.getAlignment()); + addr = Address(Builder.CreateInBoundsGEP(addr.getElementType(), + addr.emitRawPointer(*this), + gepIndices, "array.begin"), + ConvertTypeForMem(eltType), addr.getAlignment()); } baseType = eltType; @@ -2562,7 +2574,7 @@ void CodeGenFunction::EmitVarAnnotations(const VarDecl *D, llvm::Value *V) { Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D, Address Addr) { assert(D->hasAttr() && "no annotate attribute"); - llvm::Value *V = Addr.getPointer(); + llvm::Value *V = Addr.emitRawPointer(*this); llvm::Type *VTy = V->getType(); auto *PTy = dyn_cast(VTy); unsigned AS = PTy ? PTy->getAddressSpace() : 0; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index e8f8aa601ed017b559d2b87548110423e5c78107..8dd6da5f85f11dcfd95d984f62153bd8247f9e30 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -151,6 +151,9 @@ struct DominatingLLVMValue { /// Answer whether the given value needs extra work to be saved. static bool needsSaving(llvm::Value *value) { + if (!value) + return false; + // If it's not an instruction, we don't need to save. if (!isa(value)) return false; @@ -177,21 +180,28 @@ template <> struct DominatingValue
{ typedef Address type; struct saved_type { - DominatingLLVMValue::saved_type SavedValue; + DominatingLLVMValue::saved_type BasePtr; llvm::Type *ElementType; CharUnits Alignment; + DominatingLLVMValue::saved_type Offset; + llvm::PointerType *EffectiveType; }; static bool needsSaving(type value) { - return DominatingLLVMValue::needsSaving(value.getPointer()); + if (DominatingLLVMValue::needsSaving(value.getBasePointer()) || + DominatingLLVMValue::needsSaving(value.getOffset())) + return true; + return false; } static saved_type save(CodeGenFunction &CGF, type value) { - return { DominatingLLVMValue::save(CGF, value.getPointer()), - value.getElementType(), value.getAlignment() }; + return {DominatingLLVMValue::save(CGF, value.getBasePointer()), + value.getElementType(), value.getAlignment(), + DominatingLLVMValue::save(CGF, value.getOffset()), value.getType()}; } static type restore(CodeGenFunction &CGF, saved_type value) { - return Address(DominatingLLVMValue::restore(CGF, value.SavedValue), - value.ElementType, value.Alignment); + return Address(DominatingLLVMValue::restore(CGF, value.BasePtr), + value.ElementType, value.Alignment, + DominatingLLVMValue::restore(CGF, value.Offset)); } }; @@ -201,14 +211,26 @@ template <> struct DominatingValue { class saved_type { enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral, AggregateAddress, ComplexAddress }; - - llvm::Value *Value; - llvm::Type *ElementType; + union { + struct { + DominatingLLVMValue::saved_type first, second; + } Vals; + DominatingValue
::saved_type AggregateAddr; + }; LLVM_PREFERRED_TYPE(Kind) unsigned K : 3; - unsigned Align : 29; - saved_type(llvm::Value *v, llvm::Type *e, Kind k, unsigned a = 0) - : Value(v), ElementType(e), K(k), Align(a) {} + unsigned IsVolatile : 1; + + saved_type(DominatingLLVMValue::saved_type Val1, unsigned K) + : Vals{Val1, DominatingLLVMValue::saved_type()}, K(K) {} + + saved_type(DominatingLLVMValue::saved_type Val1, + DominatingLLVMValue::saved_type Val2) + : Vals{Val1, Val2}, K(ComplexAddress) {} + + saved_type(DominatingValue
::saved_type AggregateAddr, + bool IsVolatile, unsigned K) + : AggregateAddr(AggregateAddr), K(K) {} public: static bool needsSaving(RValue value); @@ -659,7 +681,7 @@ public: llvm::Value *Size; public: - CallLifetimeEnd(Address addr, llvm::Value *size) + CallLifetimeEnd(RawAddress addr, llvm::Value *size) : Addr(addr.getPointer()), Size(size) {} void Emit(CodeGenFunction &CGF, Flags flags) override { @@ -684,7 +706,7 @@ public: }; /// i32s containing the indexes of the cleanup destinations. - Address NormalCleanupDest = Address::invalid(); + RawAddress NormalCleanupDest = RawAddress::invalid(); unsigned NextCleanupDestIndex = 1; @@ -819,10 +841,10 @@ public: template void pushCleanupAfterFullExpr(CleanupKind Kind, As... A) { if (!isInConditionalBranch()) - return pushCleanupAfterFullExprWithActiveFlag(Kind, Address::invalid(), - A...); + return pushCleanupAfterFullExprWithActiveFlag( + Kind, RawAddress::invalid(), A...); - Address ActiveFlag = createCleanupActiveFlag(); + RawAddress ActiveFlag = createCleanupActiveFlag(); assert(!DominatingValue
::needsSaving(ActiveFlag) && "cleanup active flag should never need saving"); @@ -835,7 +857,7 @@ public: template void pushCleanupAfterFullExprWithActiveFlag(CleanupKind Kind, - Address ActiveFlag, As... A) { + RawAddress ActiveFlag, As... A) { LifetimeExtendedCleanupHeader Header = {sizeof(T), Kind, ActiveFlag.isValid()}; @@ -850,7 +872,7 @@ public: new (Buffer) LifetimeExtendedCleanupHeader(Header); new (Buffer + sizeof(Header)) T(A...); if (Header.IsConditional) - new (Buffer + sizeof(Header) + sizeof(T)) Address(ActiveFlag); + new (Buffer + sizeof(Header) + sizeof(T)) RawAddress(ActiveFlag); } /// Set up the last cleanup that was pushed as a conditional @@ -859,8 +881,8 @@ public: initFullExprCleanupWithFlag(createCleanupActiveFlag()); } - void initFullExprCleanupWithFlag(Address ActiveFlag); - Address createCleanupActiveFlag(); + void initFullExprCleanupWithFlag(RawAddress ActiveFlag); + RawAddress createCleanupActiveFlag(); /// PushDestructorCleanup - Push a cleanup to call the /// complete-object destructor of an object of the given type at the @@ -1048,7 +1070,7 @@ public: QualType VarTy = LocalVD->getType(); if (VarTy->isReferenceType()) { Address Temp = CGF.CreateMemTemp(VarTy); - CGF.Builder.CreateStore(TempAddr.getPointer(), Temp); + CGF.Builder.CreateStore(TempAddr.emitRawPointer(CGF), Temp); TempAddr = Temp; } SavedTempAddresses.try_emplace(LocalVD, TempAddr); @@ -1243,10 +1265,12 @@ public: /// one branch or the other of a conditional expression. bool isInConditionalBranch() const { return OutermostConditional != nullptr; } - void setBeforeOutermostConditional(llvm::Value *value, Address addr) { + void setBeforeOutermostConditional(llvm::Value *value, Address addr, + CodeGenFunction &CGF) { assert(isInConditionalBranch()); llvm::BasicBlock *block = OutermostConditional->getStartingBlock(); - auto store = new llvm::StoreInst(value, addr.getPointer(), &block->back()); + auto store = + new llvm::StoreInst(value, addr.emitRawPointer(CGF), &block->back()); store->setAlignment(addr.getAlignment().getAsAlign()); } @@ -1601,7 +1625,7 @@ public: /// If \p StepV is null, the default increment is 1. void maybeUpdateMCDCTestVectorBitmap(const Expr *E) { if (isMCDCCoverageEnabled() && isBinaryLogicalOp(E)) { - PGO.emitMCDCTestVectorBitmapUpdate(Builder, E, MCDCCondBitmapAddr); + PGO.emitMCDCTestVectorBitmapUpdate(Builder, E, MCDCCondBitmapAddr, *this); PGO.setCurrentStmt(E); } } @@ -1609,7 +1633,7 @@ public: /// Update the MCDC temp value with the condition's evaluated result. void maybeUpdateMCDCCondBitmap(const Expr *E, llvm::Value *Val) { if (isMCDCCoverageEnabled()) { - PGO.emitMCDCCondBitmapUpdate(Builder, E, MCDCCondBitmapAddr, Val); + PGO.emitMCDCCondBitmapUpdate(Builder, E, MCDCCondBitmapAddr, Val, *this); PGO.setCurrentStmt(E); } } @@ -1704,7 +1728,7 @@ public: : CGF(CGF), OldCXXThisValue(CGF.CXXThisValue), OldCXXThisAlignment(CGF.CXXThisAlignment), SourceLocScope(E, CGF.CurSourceLocExprScope) { - CGF.CXXThisValue = CGF.CXXDefaultInitExprThis.getPointer(); + CGF.CXXThisValue = CGF.CXXDefaultInitExprThis.getBasePointer(); CGF.CXXThisAlignment = CGF.CXXDefaultInitExprThis.getAlignment(); } ~CXXDefaultInitExprScope() { @@ -2090,7 +2114,7 @@ public: llvm::Value *getExceptionFromSlot(); llvm::Value *getSelectorFromSlot(); - Address getNormalCleanupDestSlot(); + RawAddress getNormalCleanupDestSlot(); llvm::BasicBlock *getUnreachableBlock() { if (!UnreachableBlock) { @@ -2579,10 +2603,40 @@ public: // Helpers //===--------------------------------------------------------------------===// + Address mergeAddressesInConditionalExpr(Address LHS, Address RHS, + llvm::BasicBlock *LHSBlock, + llvm::BasicBlock *RHSBlock, + llvm::BasicBlock *MergeBlock, + QualType MergedType) { + Builder.SetInsertPoint(MergeBlock); + llvm::PHINode *PtrPhi = Builder.CreatePHI(LHS.getType(), 2, "cond"); + PtrPhi->addIncoming(LHS.getBasePointer(), LHSBlock); + PtrPhi->addIncoming(RHS.getBasePointer(), RHSBlock); + LHS.replaceBasePointer(PtrPhi); + LHS.setAlignment(std::min(LHS.getAlignment(), RHS.getAlignment())); + return LHS; + } + + /// Construct an address with the natural alignment of T. If a pointer to T + /// is expected to be signed, the pointer passed to this function must have + /// been signed, and the returned Address will have the pointer authentication + /// information needed to authenticate the signed pointer. + Address makeNaturalAddressForPointer( + llvm::Value *Ptr, QualType T, CharUnits Alignment = CharUnits::Zero(), + bool ForPointeeType = false, LValueBaseInfo *BaseInfo = nullptr, + TBAAAccessInfo *TBAAInfo = nullptr, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) { + if (Alignment.isZero()) + Alignment = + CGM.getNaturalTypeAlignment(T, BaseInfo, TBAAInfo, ForPointeeType); + return Address(Ptr, ConvertTypeForMem(T), Alignment, nullptr, + IsKnownNonNull); + } + LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source = AlignmentSource::Type) { - return LValue::MakeAddr(Addr, T, getContext(), LValueBaseInfo(Source), - CGM.getTBAAAccessInfo(T)); + return MakeAddrLValue(Addr, T, LValueBaseInfo(Source), + CGM.getTBAAAccessInfo(T)); } LValue MakeAddrLValue(Address Addr, QualType T, LValueBaseInfo BaseInfo, @@ -2592,6 +2646,14 @@ public: LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source = AlignmentSource::Type) { + return MakeAddrLValue(makeNaturalAddressForPointer(V, T, Alignment), T, + LValueBaseInfo(Source), CGM.getTBAAAccessInfo(T)); + } + + /// Same as MakeAddrLValue above except that the pointer is known to be + /// unsigned. + LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, + AlignmentSource Source = AlignmentSource::Type) { Address Addr(V, ConvertTypeForMem(T), Alignment); return LValue::MakeAddr(Addr, T, getContext(), LValueBaseInfo(Source), CGM.getTBAAAccessInfo(T)); @@ -2604,9 +2666,18 @@ public: TBAAAccessInfo()); } + /// Given a value of type T* that may not be to a complete object, construct + /// an l-value with the natural pointee alignment of T. LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T); + LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T); + /// Same as MakeNaturalAlignPointeeAddrLValue except that the pointer is known + /// to be unsigned. + LValue MakeNaturalAlignPointeeRawAddrLValue(llvm::Value *V, QualType T); + + LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T); + Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo = nullptr, TBAAAccessInfo *PointeeTBAAInfo = nullptr); @@ -2655,13 +2726,13 @@ public: /// more efficient if the caller knows that the address will not be exposed. llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty, const Twine &Name = "tmp", llvm::Value *ArraySize = nullptr); - Address CreateTempAlloca(llvm::Type *Ty, CharUnits align, - const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr, - Address *Alloca = nullptr); - Address CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits align, - const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr); + RawAddress CreateTempAlloca(llvm::Type *Ty, CharUnits align, + const Twine &Name = "tmp", + llvm::Value *ArraySize = nullptr, + RawAddress *Alloca = nullptr); + RawAddress CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits align, + const Twine &Name = "tmp", + llvm::Value *ArraySize = nullptr); /// CreateDefaultAlignedTempAlloca - This creates an alloca with the /// default ABI alignment of the given LLVM type. @@ -2673,8 +2744,8 @@ public: /// not hand this address off to arbitrary IRGen routines, and especially /// do not pass it as an argument to a function that might expect a /// properly ABI-aligned value. - Address CreateDefaultAlignTempAlloca(llvm::Type *Ty, - const Twine &Name = "tmp"); + RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, + const Twine &Name = "tmp"); /// CreateIRTemp - Create a temporary IR object of the given type, with /// appropriate alignment. This routine should only be used when an temporary @@ -2684,32 +2755,31 @@ public: /// /// That is, this is exactly equivalent to CreateMemTemp, but calling /// ConvertType instead of ConvertTypeForMem. - Address CreateIRTemp(QualType T, const Twine &Name = "tmp"); + RawAddress CreateIRTemp(QualType T, const Twine &Name = "tmp"); /// CreateMemTemp - Create a temporary memory object of the given type, with /// appropriate alignmen and cast it to the default address space. Returns /// the original alloca instruction by \p Alloca if it is not nullptr. - Address CreateMemTemp(QualType T, const Twine &Name = "tmp", - Address *Alloca = nullptr); - Address CreateMemTemp(QualType T, CharUnits Align, const Twine &Name = "tmp", - Address *Alloca = nullptr); + RawAddress CreateMemTemp(QualType T, const Twine &Name = "tmp", + RawAddress *Alloca = nullptr); + RawAddress CreateMemTemp(QualType T, CharUnits Align, + const Twine &Name = "tmp", + RawAddress *Alloca = nullptr); /// CreateMemTemp - Create a temporary memory object of the given type, with /// appropriate alignmen without casting it to the default address space. - Address CreateMemTempWithoutCast(QualType T, const Twine &Name = "tmp"); - Address CreateMemTempWithoutCast(QualType T, CharUnits Align, - const Twine &Name = "tmp"); + RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name = "tmp"); + RawAddress CreateMemTempWithoutCast(QualType T, CharUnits Align, + const Twine &Name = "tmp"); /// CreateAggTemp - Create a temporary memory object for the given /// aggregate type. AggValueSlot CreateAggTemp(QualType T, const Twine &Name = "tmp", - Address *Alloca = nullptr) { - return AggValueSlot::forAddr(CreateMemTemp(T, Name, Alloca), - T.getQualifiers(), - AggValueSlot::IsNotDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap); + RawAddress *Alloca = nullptr) { + return AggValueSlot::forAddr( + CreateMemTemp(T, Name, Alloca), T.getQualifiers(), + AggValueSlot::IsNotDestructed, AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap); } /// EvaluateExprAsBool - Perform the usual unary conversions on the specified @@ -3083,6 +3153,25 @@ public: /// calls to EmitTypeCheck can be skipped. bool sanitizePerformTypeCheck() const; + void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, LValue LV, + QualType Type, SanitizerSet SkippedChecks = SanitizerSet(), + llvm::Value *ArraySize = nullptr) { + if (!sanitizePerformTypeCheck()) + return; + EmitTypeCheck(TCK, Loc, LV.emitRawPointer(*this), Type, LV.getAlignment(), + SkippedChecks, ArraySize); + } + + void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, Address Addr, + QualType Type, CharUnits Alignment = CharUnits::Zero(), + SanitizerSet SkippedChecks = SanitizerSet(), + llvm::Value *ArraySize = nullptr) { + if (!sanitizePerformTypeCheck()) + return; + EmitTypeCheck(TCK, Loc, Addr.emitRawPointer(*this), Type, Alignment, + SkippedChecks, ArraySize); + } + /// Emit a check that \p V is the address of storage of the /// appropriate size and alignment for an object of type \p Type /// (or if ArraySize is provided, for an array of that bound). @@ -3183,17 +3272,17 @@ public: /// Address with original alloca instruction. Invalid if the variable was /// emitted as a global constant. - Address AllocaAddr; + RawAddress AllocaAddr; struct Invalid {}; AutoVarEmission(Invalid) : Variable(nullptr), Addr(Address::invalid()), - AllocaAddr(Address::invalid()) {} + AllocaAddr(RawAddress::invalid()) {} AutoVarEmission(const VarDecl &variable) : Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr), IsEscapingByRef(false), IsConstantAggregate(false), - SizeForLifetimeMarkers(nullptr), AllocaAddr(Address::invalid()) {} + SizeForLifetimeMarkers(nullptr), AllocaAddr(RawAddress::invalid()) {} bool wasEmittedAsGlobal() const { return !Addr.isValid(); } @@ -3216,7 +3305,7 @@ public: } /// Returns the address for the original alloca instruction. - Address getOriginalAllocatedAddress() const { return AllocaAddr; } + RawAddress getOriginalAllocatedAddress() const { return AllocaAddr; } /// Returns the address of the object within this declaration. /// Note that this does not chase the forwarding pointer for @@ -3246,23 +3335,32 @@ public: llvm::GlobalValue::LinkageTypes Linkage); class ParamValue { - llvm::Value *Value; - llvm::Type *ElementType; - unsigned Alignment; - ParamValue(llvm::Value *V, llvm::Type *T, unsigned A) - : Value(V), ElementType(T), Alignment(A) {} + union { + Address Addr; + llvm::Value *Value; + }; + + bool IsIndirect; + + ParamValue(llvm::Value *V) : Value(V), IsIndirect(false) {} + ParamValue(Address A) : Addr(A), IsIndirect(true) {} + public: static ParamValue forDirect(llvm::Value *value) { - return ParamValue(value, nullptr, 0); + return ParamValue(value); } static ParamValue forIndirect(Address addr) { assert(!addr.getAlignment().isZero()); - return ParamValue(addr.getPointer(), addr.getElementType(), - addr.getAlignment().getQuantity()); + return ParamValue(addr); } - bool isIndirect() const { return Alignment != 0; } - llvm::Value *getAnyValue() const { return Value; } + bool isIndirect() const { return IsIndirect; } + llvm::Value *getAnyValue() const { + if (!isIndirect()) + return Value; + assert(!Addr.hasOffset() && "unexpected offset"); + return Addr.getBasePointer(); + } llvm::Value *getDirectValue() const { assert(!isIndirect()); @@ -3271,8 +3369,7 @@ public: Address getIndirectAddress() const { assert(isIndirect()); - return Address(Value, ElementType, CharUnits::fromQuantity(Alignment), - KnownNonNull); + return Addr; } }; @@ -4182,6 +4279,9 @@ public: const Twine &name = ""); llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name = ""); + llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, + ArrayRef
args, + const Twine &name = ""); llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, ArrayRef args, const Twine &name = ""); @@ -4208,6 +4308,12 @@ public: CXXDtorType Type, const CXXRecordDecl *RD); + llvm::Value *getAsNaturalPointerTo(Address Addr, QualType PointeeType) { + return Addr.getBasePointer(); + } + + bool isPointerKnownNonNull(const Expr *E); + // Return the copy constructor name with the prefix "__copy_constructor_" // removed. static std::string getNonTrivialCopyConstructorStr(QualType QT, @@ -4780,6 +4886,11 @@ public: SourceLocation Loc, const Twine &Name = ""); + Address EmitCheckedInBoundsGEP(Address Addr, ArrayRef IdxList, + llvm::Type *elementType, bool SignedIndices, + bool IsSubtraction, SourceLocation Loc, + CharUnits Align, const Twine &Name = ""); + /// Specifies which type of sanitizer check to apply when handling a /// particular builtin. enum BuiltinCheckKind { @@ -4842,6 +4953,10 @@ public: void EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc, AbstractCallee AC, unsigned ParmNum); + void EmitNonNullArgCheck(Address Addr, QualType ArgType, + SourceLocation ArgLoc, AbstractCallee AC, + unsigned ParmNum); + /// EmitCallArg - Emit a single call argument. void EmitCallArg(CallArgList &args, const Expr *E, QualType ArgType); @@ -5050,7 +5165,7 @@ DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) { CGF.CreateTempAlloca(value->getType(), align, "cond-cleanup.save"); CGF.Builder.CreateStore(value, alloca); - return saved_type(alloca.getPointer(), true); + return saved_type(alloca.emitRawPointer(CGF), true); } inline llvm::Value *DominatingLLVMValue::restore(CodeGenFunction &CGF, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index cb153066b28dd10eaaa3c6f2dafb35ebf4d77fdf..00b3bfcaa0bc2565862d659b122b1caf18ff0599 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3711,7 +3711,9 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // Forward declarations are emitted lazily on first use. if (!FD->doesThisDeclarationHaveABody()) { - if (!FD->doesDeclarationForceExternallyVisibleDefinition()) + if (!FD->doesDeclarationForceExternallyVisibleDefinition() && + (!FD->isMultiVersion() || + !FD->getASTContext().getTargetInfo().getTriple().isAArch64())) return; StringRef MangledName = getMangledName(GD); @@ -3993,10 +3995,11 @@ void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD, auto *Spec = FD->getAttr(); for (unsigned I = 0; I < Spec->cpus_size(); ++I) EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr); - } else if (FD->isTargetClonesMultiVersion()) { - auto *Clone = FD->getAttr(); - for (unsigned I = 0; I < Clone->featuresStrs_size(); ++I) - if (Clone->isFirstOfVersion(I)) + } else if (auto *TC = FD->getAttr()) { + for (unsigned I = 0; I < TC->featuresStrs_size(); ++I) + // AArch64 favors the default target version over the clone if any. + if ((!TC->isDefaultVersion(I) || !getTarget().getTriple().isAArch64()) && + TC->isFirstOfVersion(I)) EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr); // Ensure that the resolver function is also emitted. GetOrCreateMultiVersionResolver(GD); @@ -4092,6 +4095,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,96 +4119,79 @@ void CodeGenModule::emitMultiVersionFunctions() { const auto *FD = cast(GD.getDecl()); assert(FD && "Expected a FunctionDecl"); - bool EmitResolver = !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; - 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; - TVA->getFeatures(Feats); - Options.emplace_back(cast(Func), - /*Architecture*/ "", Feats); - } - }); - } else if (FD->isTargetClonesMultiVersion()) { - const auto *TC = FD->getAttr(); - for (unsigned VersionIndex = 0; VersionIndex < TC->featuresStrs_size(); - ++VersionIndex) { - if (!TC->isFirstOfVersion(VersionIndex)) - 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"); + 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); + }; - StringRef Architecture; - llvm::SmallVector Feature; + bool HasDefaultDecl = !FD->isTargetVersionMultiVersion(); + bool ShouldEmitResolver = + !getContext().getTargetInfo().getTriple().isAArch64(); + SmallVector Options; - if (getTarget().getTriple().isAArch64()) { - if (Version != "default") { - llvm::SmallVector VerFeats; - Version.split(VerFeats, "+"); - for (auto &CurFeat : VerFeats) - Feature.push_back(CurFeat.trim()); - } - } else { - if (Version.starts_with("arch=")) - Architecture = Version.drop_front(sizeof("arch=") - 1); - else if (Version != "default") - Feature.push_back(Version); - } + getContext().forEachMultiversionedFunctionVersion( + FD, [&](const FunctionDecl *CurFD) { + llvm::SmallVector Feats; + + if (const auto *TA = CurFD->getAttr()) { + TA->getAddedFeatures(Feats); + llvm::Function *Func = createFunction(CurFD); + 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); + llvm::Function *Func = createFunction(CurFD); + Options.emplace_back(Func, /*Architecture*/ "", Feats); + } else if (const auto *TC = CurFD->getAttr()) { + ShouldEmitResolver |= CurFD->doesThisDeclarationHaveABody(); + for (unsigned I = 0; I < TC->featuresStrs_size(); ++I) { + if (!TC->isFirstOfVersion(I)) + continue; + + llvm::Function *Func = createFunction(CurFD, I); + StringRef Architecture; + Feats.clear(); + if (getTarget().getTriple().isAArch64()) + TC->getFeatures(Feats, I); + else { + StringRef Version = TC->getFeatureStr(I); + if (Version.starts_with("arch=")) + Architecture = Version.drop_front(sizeof("arch=") - 1); + else if (Version != "default") + Feats.push_back(Version); + } + Options.emplace_back(Func, Architecture, Feats); + } + } else + llvm_unreachable("unexpected MultiVersionKind"); + }); - Options.emplace_back(cast(Func), Architecture, Feature); - } - } else { - assert(0 && "Expected a target or target_clones multiversion function"); + if (!ShouldEmitResolver) continue; - } - if (!EmitResolver) - 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)) { @@ -4369,7 +4372,7 @@ void CodeGenModule::AddDeferredMultiVersionResolverToEmit(GlobalDecl GD) { const auto *FD = cast(GD.getDecl()); assert(FD && "Not a FunctionDecl?"); - if (FD->isTargetVersionMultiVersion()) { + if (FD->isTargetVersionMultiVersion() || FD->isTargetClonesMultiVersion()) { std::string MangledName = getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true); if (!DeferredResolversToEmit.insert(MangledName).second) @@ -4480,7 +4483,10 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( if (FD->isMultiVersion()) { UpdateMultiVersionNames(GD, FD, MangledName); - if (!IsForDefinition) + if (FD->getASTContext().getTargetInfo().getTriple().isAArch64() && + !FD->isUsed()) + AddDeferredMultiVersionResolverToEmit(GD); + else if (!IsForDefinition) return GetOrCreateMultiVersionResolver(GD); } } @@ -6275,7 +6281,7 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) { // Resize the string to the right size, which is indicated by its type. const ConstantArrayType *CAT = Context.getAsConstantArrayType(E->getType()); assert(CAT && "String literal not of constant array type!"); - Str.resize(CAT->getSize().getZExtValue()); + Str.resize(CAT->getZExtSize()); return llvm::ConstantDataArray::getString(VMContext, Str, false); } @@ -7261,7 +7267,7 @@ void CodeGenFunction::EmitDeclMetadata() { for (auto &I : LocalDeclMap) { const Decl *D = I.first; - llvm::Value *Addr = I.second.getPointer(); + llvm::Value *Addr = I.second.emitRawPointer(*this); if (auto *Alloca = dyn_cast(Addr)) { llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D); Alloca->setMetadata( diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 2619edfeb7dc76c3e482b3c2da13dfdca1afc74d..76704c4d7be4a49de647c9f64aac615724215bb7 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -1239,7 +1239,8 @@ void CodeGenPGO::emitMCDCParameters(CGBuilderTy &Builder) { void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr) { + Address MCDCCondBitmapAddr, + CodeGenFunction &CGF) { if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState) return; @@ -1262,7 +1263,7 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, Builder.getInt64(FunctionHash), Builder.getInt32(RegionMCDCState->BitmapBytes), Builder.getInt32(MCDCTestVectorBitmapOffset), - MCDCCondBitmapAddr.getPointer()}; + MCDCCondBitmapAddr.emitRawPointer(CGF)}; Builder.CreateCall( CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_tvbitmap_update), Args); } @@ -1283,7 +1284,8 @@ void CodeGenPGO::emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, Address MCDCCondBitmapAddr, - llvm::Value *Val) { + llvm::Value *Val, + CodeGenFunction &CGF) { if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState) return; @@ -1312,7 +1314,7 @@ void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy), Builder.getInt64(FunctionHash), Builder.getInt32(Branch.ID), - MCDCCondBitmapAddr.getPointer(), Val}; + MCDCCondBitmapAddr.emitRawPointer(CGF), Val}; Builder.CreateCall( CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_condbitmap_update), Args); diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h index 036fbf6815a49da500970580c8ed6057bc317847..9d66ffad6f43509e991ca87c3605c94e27ea8833 100644 --- a/clang/lib/CodeGen/CodeGenPGO.h +++ b/clang/lib/CodeGen/CodeGenPGO.h @@ -113,12 +113,14 @@ public: void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S, llvm::Value *StepV); void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr); + Address MCDCCondBitmapAddr, + CodeGenFunction &CGF); void emitMCDCParameters(CGBuilderTy &Builder); void emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, Address MCDCCondBitmapAddr); void emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr, llvm::Value *Val); + Address MCDCCondBitmapAddr, llvm::Value *Val, + CodeGenFunction &CGF); /// Return the region count for the counter at the given index. uint64_t getRegionCount(const Stmt *S) { diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index a6b51bfef87652d1b4101c0925ab92640a1ea0af..afadc29ab1b02761b79071484419d78f5b2f408f 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -601,7 +601,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { EltTy = llvm::Type::getInt8Ty(getLLVMContext()); } - ResultType = llvm::ArrayType::get(EltTy, A->getSize().getZExtValue()); + ResultType = llvm::ArrayType::get(EltTy, A->getZExtSize()); break; } case Type::ExtVector: diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index bdd53a192f828adbe2999a7f54d3d805c4892146..fd71317572f0c9168e2e2d53b45ad7518ff8a358 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -307,10 +307,6 @@ public: CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, const CXXRecordDecl *NearestVBase); - llvm::Constant * - getVTableAddressPointForConstExpr(BaseSubobject Base, - const CXXRecordDecl *VTableClass) override; - llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) override; @@ -646,7 +642,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( // Apply the adjustment and cast back to the original struct type // for consistency. - llvm::Value *This = ThisAddr.getPointer(); + llvm::Value *This = ThisAddr.emitRawPointer(CGF); This = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), This, Adj); ThisPtrForCall = This; @@ -850,7 +846,7 @@ llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress( CGBuilderTy &Builder = CGF.Builder; // Apply the offset, which we assume is non-null. - return Builder.CreateInBoundsGEP(CGF.Int8Ty, Base.getPointer(), MemPtr, + return Builder.CreateInBoundsGEP(CGF.Int8Ty, Base.emitRawPointer(CGF), MemPtr, "memptr.offset"); } @@ -1245,7 +1241,7 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, CGF.getPointerAlign()); // Apply the offset. - llvm::Value *CompletePtr = Ptr.getPointer(); + llvm::Value *CompletePtr = Ptr.emitRawPointer(CGF); CompletePtr = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, CompletePtr, Offset); @@ -1482,7 +1478,8 @@ llvm::Value *ItaniumCXXABI::emitDynamicCastCall( computeOffsetHint(CGF.getContext(), SrcDecl, DestDecl).getQuantity()); // Emit the call to __dynamic_cast. - llvm::Value *Args[] = {ThisAddr.getPointer(), SrcRTTI, DestRTTI, OffsetHint}; + llvm::Value *Args[] = {ThisAddr.emitRawPointer(CGF), SrcRTTI, DestRTTI, + OffsetHint}; llvm::Value *Value = CGF.EmitNounwindRuntimeCall(getItaniumDynamicCastFn(CGF), Args); @@ -1571,7 +1568,7 @@ llvm::Value *ItaniumCXXABI::emitExactDynamicCast( VPtr, CGM.getTBAAVTablePtrAccessInfo(CGF.VoidPtrPtrTy)); llvm::Value *Success = CGF.Builder.CreateICmpEQ( VPtr, getVTableAddressPoint(BaseSubobject(SrcDecl, *Offset), DestDecl)); - llvm::Value *Result = ThisAddr.getPointer(); + llvm::Value *Result = ThisAddr.emitRawPointer(CGF); if (!Offset->isZero()) Result = CGF.Builder.CreateInBoundsGEP( CGF.CharTy, Result, @@ -1611,7 +1608,7 @@ llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF, PtrDiffLTy, OffsetToTop, CGF.getPointerAlign(), "offset.to.top"); } // Finally, add the offset to the pointer. - return CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ThisAddr.getPointer(), + return CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ThisAddr.emitRawPointer(CGF), OffsetToTop); } @@ -1792,8 +1789,8 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, else Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD); - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, VTT, VTTTy, - nullptr); + CGF.EmitCXXDestructorCall(GD, Callee, CGF.getAsNaturalPointerTo(This, ThisTy), + ThisTy, VTT, VTTTy, nullptr); } void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, @@ -1952,11 +1949,6 @@ llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT( CGF.getPointerAlign()); } -llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr( - BaseSubobject Base, const CXXRecordDecl *VTableClass) { - return getVTableAddressPoint(Base, VTableClass); -} - llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) { assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets"); @@ -2088,8 +2080,8 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( ThisTy = D->getDestroyedType(); } - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, nullptr, - QualType(), nullptr); + CGF.EmitCXXDestructorCall(GD, Callee, This.emitRawPointer(CGF), ThisTy, + nullptr, QualType(), nullptr); return nullptr; } @@ -2162,7 +2154,7 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, int64_t VirtualAdjustment, bool IsReturnAdjustment) { if (!NonVirtualAdjustment && !VirtualAdjustment) - return InitialPtr.getPointer(); + return InitialPtr.emitRawPointer(CGF); Address V = InitialPtr.withElementType(CGF.Int8Ty); @@ -2195,10 +2187,10 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, CGF.getPointerAlign()); } // Adjust our pointer. - ResultPtr = CGF.Builder.CreateInBoundsGEP( - V.getElementType(), V.getPointer(), Offset); + ResultPtr = CGF.Builder.CreateInBoundsGEP(V.getElementType(), + V.emitRawPointer(CGF), Offset); } else { - ResultPtr = V.getPointer(); + ResultPtr = V.emitRawPointer(CGF); } // In a derived-to-base conversion, the non-virtual adjustment is @@ -2284,7 +2276,7 @@ Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.getType(), false); llvm::FunctionCallee F = CGM.CreateRuntimeFunction(FTy, "__asan_poison_cxx_array_cookie"); - CGF.Builder.CreateCall(F, NumElementsPtr.getPointer()); + CGF.Builder.CreateCall(F, NumElementsPtr.emitRawPointer(CGF)); } // Finally, compute a pointer to the actual data buffer by skipping @@ -2315,7 +2307,7 @@ llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, llvm::FunctionType::get(CGF.SizeTy, CGF.UnqualPtrTy, false); llvm::FunctionCallee F = CGM.CreateRuntimeFunction(FTy, "__asan_load_cxx_array_cookie"); - return CGF.Builder.CreateCall(F, numElementsPtr.getPointer()); + return CGF.Builder.CreateCall(F, numElementsPtr.emitRawPointer(CGF)); } CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) { @@ -2627,7 +2619,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, // Call __cxa_guard_release. This cannot throw. CGF.EmitNounwindRuntimeCall(getGuardReleaseFn(CGM, guardPtrTy), - guardAddr.getPointer()); + guardAddr.emitRawPointer(CGF)); } else if (D.isLocalVarDecl()) { // For local variables, store 1 into the first byte of the guard variable // after the object initialization completes so that initialization is @@ -3120,10 +3112,10 @@ LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, LValue LV; if (VD->getType()->isReferenceType()) - LV = CGF.MakeNaturalAlignAddrLValue(CallVal, LValType); + LV = CGF.MakeNaturalAlignRawAddrLValue(CallVal, LValType); else - LV = CGF.MakeAddrLValue(CallVal, LValType, - CGF.getContext().getDeclAlign(VD)); + LV = CGF.MakeRawAddrLValue(CallVal, LValType, + CGF.getContext().getDeclAlign(VD)); // FIXME: need setObjCGCLValueClass? return LV; } @@ -4604,7 +4596,7 @@ static void InitCatchParam(CodeGenFunction &CGF, CGF.Builder.CreateStore(Casted, ExnPtrTmp); // Bind the reference to the temporary. - AdjustedExn = ExnPtrTmp.getPointer(); + AdjustedExn = ExnPtrTmp.emitRawPointer(CGF); } } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 172c4c937b97280d30ca5689ec58b600a852a809..d38a26940a3cb613a29557019f92b60b49cb7a9e 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -327,10 +327,6 @@ public: CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, const CXXRecordDecl *NearestVBase) override; - llvm::Constant * - getVTableAddressPointForConstExpr(BaseSubobject Base, - const CXXRecordDecl *VTableClass) override; - llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) override; @@ -937,7 +933,7 @@ void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF, } CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam); - CPI->setArgOperand(2, var.getObjectAddress(CGF).getPointer()); + CPI->setArgOperand(2, var.getObjectAddress(CGF).emitRawPointer(CGF)); CGF.EHStack.pushCleanup(NormalCleanup, CPI); CGF.EmitAutoVarCleanups(var); } @@ -974,7 +970,7 @@ MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value, llvm::Value *Offset = GetVirtualBaseClassOffset(CGF, Value, SrcDecl, PolymorphicBase); llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP( - Value.getElementType(), Value.getPointer(), Offset); + Value.getElementType(), Value.emitRawPointer(CGF), Offset); CharUnits VBaseAlign = CGF.CGM.getVBaseAlignment(Value.getAlignment(), SrcDecl, PolymorphicBase); return std::make_tuple(Address(Ptr, CGF.Int8Ty, VBaseAlign), Offset, @@ -1011,7 +1007,7 @@ llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF, llvm::Type *StdTypeInfoPtrTy) { std::tie(ThisPtr, std::ignore, std::ignore) = performBaseAdjustment(CGF, ThisPtr, SrcRecordTy); - llvm::CallBase *Typeid = emitRTtypeidCall(CGF, ThisPtr.getPointer()); + llvm::CallBase *Typeid = emitRTtypeidCall(CGF, ThisPtr.emitRawPointer(CGF)); return CGF.Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy); } @@ -1033,7 +1029,7 @@ llvm::Value *MicrosoftCXXABI::emitDynamicCastCall( llvm::Value *Offset; std::tie(This, Offset, std::ignore) = performBaseAdjustment(CGF, This, SrcRecordTy); - llvm::Value *ThisPtr = This.getPointer(); + llvm::Value *ThisPtr = This.emitRawPointer(CGF); Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty); // PVOID __RTDynamicCast( @@ -1065,7 +1061,7 @@ llvm::Value *MicrosoftCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF, llvm::FunctionCallee Function = CGF.CGM.CreateRuntimeFunction( llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false), "__RTCastToVoid"); - llvm::Value *Args[] = {Value.getPointer()}; + llvm::Value *Args[] = {Value.emitRawPointer(CGF)}; return CGF.EmitRuntimeCall(Function, Args); } @@ -1493,7 +1489,7 @@ Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall( llvm::Value *VBaseOffset = GetVirtualBaseClassOffset(CGF, Result, Derived, VBase); llvm::Value *VBasePtr = CGF.Builder.CreateInBoundsGEP( - Result.getElementType(), Result.getPointer(), VBaseOffset); + Result.getElementType(), Result.emitRawPointer(CGF), VBaseOffset); CharUnits VBaseAlign = CGF.CGM.getVBaseAlignment(Result.getAlignment(), Derived, VBase); Result = Address(VBasePtr, CGF.Int8Ty, VBaseAlign); @@ -1660,7 +1656,8 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, llvm::Value *Implicit = getCXXDestructorImplicitParam(CGF, DD, Type, ForVirtualBase, Delegating); // = nullptr - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, + CGF.EmitCXXDestructorCall(GD, Callee, CGF.getAsNaturalPointerTo(This, ThisTy), + ThisTy, /*ImplicitParam=*/Implicit, /*ImplicitParamTy=*/QualType(), nullptr); if (BaseDtorEndBB) { @@ -1791,13 +1788,6 @@ MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base, return VFTablesMap[ID]; } -llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr( - BaseSubobject Base, const CXXRecordDecl *VTableClass) { - llvm::Constant *VFTable = getVTableAddressPoint(Base, VTableClass); - assert(VFTable && "Couldn't find a vftable for the given base?"); - return VFTable; -} - llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) { // getAddrOfVTable may return 0 if asked to get an address of a vtable which @@ -2013,8 +2003,9 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( } This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); - RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, - ImplicitParam, Context.IntTy, CE); + RValue RV = + CGF.EmitCXXDestructorCall(GD, Callee, This.emitRawPointer(CGF), ThisTy, + ImplicitParam, Context.IntTy, CE); return RV.getScalarVal(); } @@ -2212,13 +2203,13 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, Address This, const ThisAdjustment &TA) { if (TA.isEmpty()) - return This.getPointer(); + return This.emitRawPointer(CGF); This = This.withElementType(CGF.Int8Ty); llvm::Value *V; if (TA.Virtual.isEmpty()) { - V = This.getPointer(); + V = This.emitRawPointer(CGF); } else { assert(TA.Virtual.Microsoft.VtordispOffset < 0); // Adjust the this argument based on the vtordisp value. @@ -2227,7 +2218,7 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, CharUnits::fromQuantity(TA.Virtual.Microsoft.VtordispOffset)); VtorDispPtr = VtorDispPtr.withElementType(CGF.Int32Ty); llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp"); - V = CGF.Builder.CreateGEP(This.getElementType(), This.getPointer(), + V = CGF.Builder.CreateGEP(This.getElementType(), This.emitRawPointer(CGF), CGF.Builder.CreateNeg(VtorDisp)); // Unfortunately, having applied the vtordisp means that we no @@ -2264,11 +2255,11 @@ llvm::Value * MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret, const ReturnAdjustment &RA) { if (RA.isEmpty()) - return Ret.getPointer(); + return Ret.emitRawPointer(CGF); Ret = Ret.withElementType(CGF.Int8Ty); - llvm::Value *V = Ret.getPointer(); + llvm::Value *V = Ret.emitRawPointer(CGF); if (RA.Virtual.Microsoft.VBIndex) { assert(RA.Virtual.Microsoft.VBIndex > 0); int32_t IntSize = CGF.getIntSize().getQuantity(); @@ -2583,7 +2574,7 @@ struct ResetGuardBit final : EHScopeStack::Cleanup { struct CallInitThreadAbort final : EHScopeStack::Cleanup { llvm::Value *Guard; - CallInitThreadAbort(Address Guard) : Guard(Guard.getPointer()) {} + CallInitThreadAbort(RawAddress Guard) : Guard(Guard.getPointer()) {} void Emit(CodeGenFunction &CGF, Flags flags) override { // Calling _Init_thread_abort will reset the guard's state. @@ -3123,8 +3114,8 @@ MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, llvm::Value **VBPtrOut) { CGBuilderTy &Builder = CGF.Builder; // Load the vbtable pointer from the vbptr in the instance. - llvm::Value *VBPtr = Builder.CreateInBoundsGEP(CGM.Int8Ty, This.getPointer(), - VBPtrOffset, "vbptr"); + llvm::Value *VBPtr = Builder.CreateInBoundsGEP( + CGM.Int8Ty, This.emitRawPointer(CGF), VBPtrOffset, "vbptr"); if (VBPtrOut) *VBPtrOut = VBPtr; @@ -3203,7 +3194,7 @@ llvm::Value *MicrosoftCXXABI::AdjustVirtualBase( Builder.CreateBr(SkipAdjustBB); CGF.EmitBlock(SkipAdjustBB); llvm::PHINode *Phi = Builder.CreatePHI(CGM.Int8PtrTy, 2, "memptr.base"); - Phi->addIncoming(Base.getPointer(), OriginalBB); + Phi->addIncoming(Base.emitRawPointer(CGF), OriginalBB); Phi->addIncoming(AdjustedBase, VBaseAdjustBB); return Phi; } @@ -3238,7 +3229,7 @@ llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress( Addr = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset, VBPtrOffset); } else { - Addr = Base.getPointer(); + Addr = Base.emitRawPointer(CGF); } // Apply the offset, which we assume is non-null. @@ -3526,7 +3517,7 @@ CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer( ThisPtrForCall = AdjustVirtualBase(CGF, E, RD, This, VirtualBaseAdjustmentOffset, VBPtrOffset); } else { - ThisPtrForCall = This.getPointer(); + ThisPtrForCall = This.emitRawPointer(CGF); } if (NonVirtualBaseAdjustment) @@ -4445,10 +4436,7 @@ void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { llvm::GlobalVariable *TI = getThrowInfo(ThrowType); // Call into the runtime to throw the exception. - llvm::Value *Args[] = { - AI.getPointer(), - TI - }; + llvm::Value *Args[] = {AI.emitRawPointer(CGF), TI}; CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(), Args); } diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp index 16fbf52a517db48ddf8ebdb0d6887a20f7ea330c..ab2e2bd0b30646557c91f26e8353412990cbd5db 100644 --- a/clang/lib/CodeGen/SwiftCallingConv.cpp +++ b/clang/lib/CodeGen/SwiftCallingConv.cpp @@ -78,7 +78,7 @@ void SwiftAggLowering::addTypedData(QualType type, CharUnits begin) { QualType eltType = arrayType->getElementType(); auto eltSize = CGM.getContext().getTypeSizeInChars(eltType); - for (uint64_t i = 0, e = arrayType->getSize().getZExtValue(); i != e; ++i) { + for (uint64_t i = 0, e = arrayType->getZExtSize(); i != e; ++i) { addTypedData(eltType, begin + i * eltSize); } diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index 6893b50a3cfe90861432da5f4a8055e534204a36..b1dfe5bf8f274d1b43c7e3f531faf8da526233a7 100644 --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -295,6 +295,11 @@ public: /// Get the AST address space for alloca. virtual LangAS getASTAllocaAddressSpace() const { return LangAS::Default; } + Address performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, Address Addr, + LangAS SrcAddr, LangAS DestAddr, + llvm::Type *DestTy, + bool IsNonNull = false) const; + /// Perform address space cast of an expression of pointer type. /// \param V is the LLVM value to be casted to another address space. /// \param SrcAddr is the language address space of \p V. diff --git a/clang/lib/CodeGen/Targets/ARM.cpp b/clang/lib/CodeGen/Targets/ARM.cpp index 5d42e6286e525b426341d31f553b8732019bdc05..885d9c77d0e76fd9d62d74c7c54f8bf60809e0b5 100644 --- a/clang/lib/CodeGen/Targets/ARM.cpp +++ b/clang/lib/CodeGen/Targets/ARM.cpp @@ -671,7 +671,7 @@ bool ARMABIInfo::isIllegalVectorType(QualType Ty) const { /// Return true if a type contains any 16-bit floating point vectors bool ARMABIInfo::containsAnyFP16Vectors(QualType Ty) const { if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) { - uint64_t NElements = AT->getSize().getZExtValue(); + uint64_t NElements = AT->getZExtSize(); if (NElements == 0) return false; return containsAnyFP16Vectors(AT->getElementType()); diff --git a/clang/lib/CodeGen/Targets/LoongArch.cpp b/clang/lib/CodeGen/Targets/LoongArch.cpp index 63b9a1fdb988ceba4142c412bbbd1e0c777ac196..3f01d9ad90f132db7230cd835bc41f8313a1eb53 100644 --- a/clang/lib/CodeGen/Targets/LoongArch.cpp +++ b/clang/lib/CodeGen/Targets/LoongArch.cpp @@ -146,7 +146,7 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper( } if (const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) { - uint64_t ArraySize = ATy->getSize().getZExtValue(); + uint64_t ArraySize = ATy->getZExtSize(); QualType EltTy = ATy->getElementType(); // Non-zero-length arrays of empty records make the struct ineligible to be // passed via FARs in C++. diff --git a/clang/lib/CodeGen/Targets/NVPTX.cpp b/clang/lib/CodeGen/Targets/NVPTX.cpp index 8718f1ecf3a7e076b70bc3d18e2d668e0783c93a..7dce5042c3dc203b5fc6e4f16903b90cc9eb1c61 100644 --- a/clang/lib/CodeGen/Targets/NVPTX.cpp +++ b/clang/lib/CodeGen/Targets/NVPTX.cpp @@ -85,7 +85,7 @@ private: LValue Src) { llvm::Value *Handle = nullptr; llvm::Constant *C = - llvm::dyn_cast(Src.getAddress(CGF).getPointer()); + llvm::dyn_cast(Src.getAddress(CGF).emitRawPointer(CGF)); // Lookup `addrspacecast` through the constant pointer if any. if (auto *ASC = llvm::dyn_cast_or_null(C)) C = llvm::cast(ASC->getPointerOperand()); diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 00b04723f17dd2e0a2ed392b57aab43300379c1e..362add30b43500e9e8121b52319e4ae822f444de 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -513,9 +513,10 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, CharUnits RegSize = CharUnits::fromQuantity((isInt || IsSoftFloatABI) ? 4 : 8); llvm::Value *RegOffset = Builder.CreateMul(NumRegs, Builder.getInt8(RegSize.getQuantity())); - RegAddr = Address( - Builder.CreateInBoundsGEP(CGF.Int8Ty, RegAddr.getPointer(), RegOffset), - DirectTy, RegAddr.getAlignment().alignmentOfArrayElement(RegSize)); + RegAddr = Address(Builder.CreateInBoundsGEP( + CGF.Int8Ty, RegAddr.emitRawPointer(CGF), RegOffset), + DirectTy, + RegAddr.getAlignment().alignmentOfArrayElement(RegSize)); // Increase the used-register count. NumRegs = @@ -551,7 +552,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, // Round up address of argument to alignment CharUnits Align = CGF.getContext().getTypeAlignInChars(Ty); if (Align > OverflowAreaAlign) { - llvm::Value *Ptr = OverflowArea.getPointer(); + llvm::Value *Ptr = OverflowArea.emitRawPointer(CGF); OverflowArea = Address(emitRoundPointerUpToAlignment(CGF, Ptr, Align), OverflowArea.getElementType(), Align); } @@ -560,7 +561,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, // Increase the overflow area. OverflowArea = Builder.CreateConstInBoundsByteGEP(OverflowArea, Size); - Builder.CreateStore(OverflowArea.getPointer(), OverflowAreaAddr); + Builder.CreateStore(OverflowArea.emitRawPointer(CGF), OverflowAreaAddr); CGF.EmitBranch(Cont); } diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp index 9a79424c4612ceb45c2f386c28d878d6b66ea655..7b32c797235621e1df5bb952372a0d538f690a57 100644 --- a/clang/lib/CodeGen/Targets/RISCV.cpp +++ b/clang/lib/CodeGen/Targets/RISCV.cpp @@ -152,7 +152,7 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, } if (const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) { - uint64_t ArraySize = ATy->getSize().getZExtValue(); + uint64_t ArraySize = ATy->getZExtSize(); QualType EltTy = ATy->getElementType(); // Non-zero-length arrays of empty records make the struct ineligible for // the FP calling convention in C++. diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index a337a52a94eca940409eb6cb7b5c76bd001668f5..9025a633f328e272901d90ff8effd6222d9842b0 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -326,7 +326,7 @@ Address SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Update VAList. Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Stride, "ap.next"); - Builder.CreateStore(NextPtr.getPointer(), VAListAddr); + Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr); return ArgAddr.withElementType(ArgTy); } diff --git a/clang/lib/CodeGen/Targets/SystemZ.cpp b/clang/lib/CodeGen/Targets/SystemZ.cpp index 6eb0c6ef2f7d637bce2093844ea5287c0ee217c2..deaafc85a31576b64379053669cfb678fbfc7cfd 100644 --- a/clang/lib/CodeGen/Targets/SystemZ.cpp +++ b/clang/lib/CodeGen/Targets/SystemZ.cpp @@ -306,7 +306,7 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Update overflow_arg_area_ptr pointer llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( - OverflowArgArea.getElementType(), OverflowArgArea.getPointer(), + OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF), PaddedSizeV, "overflow_arg_area"); CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); @@ -382,10 +382,9 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, Address MemAddr = RawMemAddr.withElementType(DirectTy); // Update overflow_arg_area_ptr pointer - llvm::Value *NewOverflowArgArea = - CGF.Builder.CreateGEP(OverflowArgArea.getElementType(), - OverflowArgArea.getPointer(), PaddedSizeV, - "overflow_arg_area"); + llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( + OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF), + PaddedSizeV, "overflow_arg_area"); CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); CGF.EmitBranch(ContBlock); diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1ec0f159ebcb8af2f5c8a209df4a095708bec83f..1146a851a7715d0099d7d845a682b56d8378d9ac 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -1993,7 +1993,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, // this, but it isn't worth it and would be harder to verify. Current = NoClass; uint64_t EltSize = getContext().getTypeSize(AT->getElementType()); - uint64_t ArraySize = AT->getSize().getZExtValue(); + uint64_t ArraySize = AT->getZExtSize(); // The only case a 256-bit wide vector could be used is when the array // contains a single 256-bit element. Since Lo and Hi logic isn't extended @@ -2295,7 +2295,7 @@ static bool BitsContainNoUserData(QualType Ty, unsigned StartBit, if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) { unsigned EltSize = (unsigned)Context.getTypeSize(AT->getElementType()); - unsigned NumElts = (unsigned)AT->getSize().getZExtValue(); + unsigned NumElts = (unsigned)AT->getZExtSize(); // Check each element to see if the element overlaps with the queried range. for (unsigned i = 0; i != NumElts; ++i) { @@ -2788,12 +2788,11 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned freeIntRegs, // memory), except in situations involving unions. case X87Up: case SSE: + ++neededSSE; HighPart = GetSSETypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8); if (Lo == NoClass) // Pass HighPart at offset 8 in memory. return ABIArgInfo::getDirect(HighPart, 8); - - ++neededSSE; break; // AMD64-ABI 3.2.3p3: Rule 4. If the class is SSEUP, the diff --git a/clang/lib/CodeGen/Targets/XCore.cpp b/clang/lib/CodeGen/Targets/XCore.cpp index aeb48f851e16936fea7c188e75cdebea3f2df927..88edb781a947b1f4be7efb7b722d034b9be322c7 100644 --- a/clang/lib/CodeGen/Targets/XCore.cpp +++ b/clang/lib/CodeGen/Targets/XCore.cpp @@ -180,7 +180,7 @@ Address XCoreABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Increment the VAList. if (!ArgSize.isZero()) { Address APN = Builder.CreateConstInBoundsByteGEP(AP, ArgSize); - Builder.CreateStore(APN.getPointer(), VAListAddr); + Builder.CreateStore(APN.emitRawPointer(CGF), VAListAddr); } return Val; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 86a287db72a4eb8a95522aab0d7e102e6ff669ec..3bcacff7724c7dab1c46ceed72fdd26356aa0c13 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1776,6 +1776,9 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, } AddUnalignedAccessWarning(CmdArgs); + + Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_intrinsics, + options::OPT_fno_ptrauth_intrinsics); } void Clang::AddLoongArchTargetArgs(const ArgList &Args, @@ -7258,10 +7261,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fno-common is the default, set -fcommon only when that flag is set. Args.addOptInFlag(CmdArgs, options::OPT_fcommon, options::OPT_fno_common); - if (Args.hasFlag(options::OPT_fptrauth_intrinsics, - options::OPT_fno_ptrauth_intrinsics, false)) - CmdArgs.push_back("-fptrauth-intrinsics"); - // -fsigned-bitfields is default, and clang doesn't yet support // -funsigned-bitfields. if (!Args.hasFlag(options::OPT_fsigned_bitfields, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 4478865313636d964003035eccbac16911bfda3a..ace4fb99581e38fa58d4eceb484d4bb4966da42f 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -758,15 +758,15 @@ bool tools::isTLSDESCEnabled(const ToolChain &TC, void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, ArgStringList &CmdArgs, const InputInfo &Output, const InputInfo &Input, bool IsThinLTO) { - const bool IsOSAIX = ToolChain.getTriple().isOSAIX(); - const bool IsAMDGCN = ToolChain.getTriple().isAMDGCN(); + const llvm::Triple &Triple = ToolChain.getTriple(); + const bool IsOSAIX = Triple.isOSAIX(); + const bool IsAMDGCN = Triple.isAMDGCN(); const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath()); const Driver &D = ToolChain.getDriver(); const bool IsFatLTO = Args.hasArg(options::OPT_ffat_lto_objects); const bool IsUnifiedLTO = Args.hasArg(options::OPT_funified_lto); if (llvm::sys::path::filename(Linker) != "ld.lld" && - llvm::sys::path::stem(Linker) != "ld.lld" && - !ToolChain.getTriple().isOSOpenBSD()) { + llvm::sys::path::stem(Linker) != "ld.lld" && !Triple.isOSOpenBSD()) { // Tell the linker to load the plugin. This has to come before // AddLinkerInputs as gold requires -plugin and AIX ld requires -bplugin to // come before any -plugin-opt/-bplugin_opt that -Wl might forward. @@ -835,7 +835,7 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, // the plugin. // Handle flags for selecting CPU variants. - std::string CPU = getCPUName(D, Args, ToolChain.getTriple()); + std::string CPU = getCPUName(D, Args, Triple); if (!CPU.empty()) CmdArgs.push_back( Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + "mcpu=" + CPU)); @@ -966,10 +966,9 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, bool HasRoptr = Args.hasFlag(options::OPT_mxcoff_roptr, options::OPT_mno_xcoff_roptr, false); StringRef OptStr = HasRoptr ? "-mxcoff-roptr" : "-mno-xcoff-roptr"; - if (!IsOSAIX) D.Diag(diag::err_drv_unsupported_opt_for_target) - << OptStr << ToolChain.getTriple().str(); + << OptStr << Triple.str(); if (HasRoptr) { // The data sections option is on by default on AIX. We only need to error @@ -1032,7 +1031,7 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, } if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls, - ToolChain.getTriple().hasDefaultEmulatedTLS())) { + Triple.hasDefaultEmulatedTLS())) { CmdArgs.push_back( Args.MakeArgString(Twine(PluginOptPrefix) + "-emulated-tls")); } @@ -1142,7 +1141,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..d06c42d5f4c5c5bf93db1c6c734da710a2450086 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(); } @@ -463,10 +464,11 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, if (i + 1 != Changes.size()) Changes[i + 1].PreviousEndOfTokenColumn += Shift; - // If PointerAlignment is PAS_Right, keep *s or &s next to the token + // If PointerAlignment is PAS_Right, keep *s or &s next to the token, + // except if the token is equal, then a space is needed. if ((Style.PointerAlignment == FormatStyle::PAS_Right || Style.ReferenceAlignment == FormatStyle::RAS_Right) && - CurrentChange.Spaces != 0) { + CurrentChange.Spaces != 0 && CurrentChange.Tok->isNot(tok::equal)) { const bool ReferenceNotRightAligned = Style.ReferenceAlignment != FormatStyle::RAS_Right && Style.ReferenceAlignment != FormatStyle::RAS_Pointer; @@ -981,6 +983,11 @@ void WhitespaceManager::alignConsecutiveShortCaseStatements() { Changes); } +void WhitespaceManager::alignConsecutiveTableGenBreakingDAGArgColons() { + alignConsecutiveColons(Style.AlignConsecutiveTableGenBreakingDAGArgColons, + TT_TableGenDAGArgListColonToAlign); +} + void WhitespaceManager::alignConsecutiveTableGenCondOperatorColons() { alignConsecutiveColons(Style.AlignConsecutiveTableGenCondOperatorColons, TT_TableGenCondOperatorColon); @@ -1485,7 +1492,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..d47eab453f8747adfb496ed2c293c84aa66913a0 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -392,15 +392,6 @@ float3 cos(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_cos) float4 cos(float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_cos) -double cos(double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_cos) -double2 cos(double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_cos) -double3 cos(double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_cos) -double4 cos(double4); - //===----------------------------------------------------------------------===// // dot product builtins //===----------------------------------------------------------------------===// @@ -737,15 +728,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 +761,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 +794,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 +1138,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 //===----------------------------------------------------------------------===// @@ -1192,19 +1147,6 @@ double4 pow(double4, double4); /// \param Val The input value. #ifdef __HLSL_ENABLE_16_BIT -_HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int16_t reversebits(int16_t); -_HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int16_t2 reversebits(int16_t2); -_HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int16_t3 reversebits(int16_t3); -_HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int16_t4 reversebits(int16_t4); - _HLSL_AVAILABILITY(shadermodel, 6.2) _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint16_t reversebits(uint16_t); @@ -1219,15 +1161,6 @@ _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint16_t4 reversebits(uint16_t4); #endif -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int reversebits(int); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int2 reversebits(int2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int3 reversebits(int3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int4 reversebits(int4); - _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint reversebits(uint); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) @@ -1237,15 +1170,6 @@ uint3 reversebits(uint3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint4 reversebits(uint4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int64_t reversebits(int64_t); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int64_t2 reversebits(int64_t2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int64_t3 reversebits(int64_t3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int64_t4 reversebits(int64_t4); - _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint64_t reversebits(uint64_t); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) @@ -1393,15 +1317,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 +1326,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 +1377,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..ba25e4183a9b8983517a8023dd8a2caac3797bf1 100644 --- a/clang/lib/InstallAPI/DylibVerifier.cpp +++ b/clang/lib/InstallAPI/DylibVerifier.cpp @@ -1,3 +1,11 @@ +//===- DylibVerifier.cpp ----------------------------------------*- C++--*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + #include "clang/InstallAPI/DylibVerifier.h" #include "clang/InstallAPI/FrontendRecords.h" #include "clang/InstallAPI/InstallAPIDiagnostic.h" @@ -66,17 +74,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 +96,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 +335,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 +523,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..6476c5107cb5cc0c65ead6ccb8c4903bd584b1cb 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; } @@ -254,7 +255,7 @@ bool InstallAPIVisitor::VisitFunctionDecl(const FunctionDecl *D) { return true; // Skip methods in CXX RecordDecls. - for (auto P : D->getASTContext().getParents(*M)) { + for (const DynTypedNode &P : D->getASTContext().getParents(*M)) { if (P.get()) 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/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index 370bcbfee8b014c1dea231949bc899c407b1bcdb..5eec2a2fd6d1a69c76a3464997394b681cb133a6 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -375,16 +375,22 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) { TranslationUnitDecl *MostRecentTU = PTU.TUPart; TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl(); if (StoredDeclsMap *Map = FirstTU->getPrimaryContext()->getLookupPtr()) { - for (auto I = Map->begin(); I != Map->end(); ++I) { - StoredDeclsList &List = I->second; + for (auto &&[Key, List] : *Map) { DeclContextLookupResult R = List.getLookupResult(); + std::vector NamedDeclsToRemove; + bool RemoveAll = true; for (NamedDecl *D : R) { - if (D->getTranslationUnitDecl() == MostRecentTU) { + if (D->getTranslationUnitDecl() == MostRecentTU) + NamedDeclsToRemove.push_back(D); + else + RemoveAll = false; + } + if (LLVM_LIKELY(RemoveAll)) { + Map->erase(Key); + } else { + for (NamedDecl *D : NamedDeclsToRemove) List.remove(D); - } } - if (List.isNull()) - Map->erase(I); } } } 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/Sema.cpp b/clang/lib/Sema/Sema.cpp index cd0c42d5ffbacd3de3e7a744fa48762293d3cff6..72393bea62052671e95c699faff0210db15c7b09 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -135,6 +135,7 @@ namespace sema { class SemaPPCallbacks : public PPCallbacks { Sema *S = nullptr; llvm::SmallVector IncludeStack; + llvm::SmallVector ProfilerStack; public: void set(Sema &S) { this->S = &S; } @@ -153,8 +154,8 @@ public: if (IncludeLoc.isValid()) { if (llvm::timeTraceProfilerEnabled()) { OptionalFileEntryRef FE = SM.getFileEntryRefForID(SM.getFileID(Loc)); - llvm::timeTraceProfilerBegin("Source", FE ? FE->getName() - : StringRef("")); + ProfilerStack.push_back(llvm::timeTraceAsyncProfilerBegin( + "Source", FE ? FE->getName() : StringRef(""))); } IncludeStack.push_back(IncludeLoc); @@ -167,7 +168,7 @@ public: case ExitFile: if (!IncludeStack.empty()) { if (llvm::timeTraceProfilerEnabled()) - llvm::timeTraceProfilerEnd(); + llvm::timeTraceProfilerEnd(ProfilerStack.pop_back_val()); S->DiagnoseNonDefaultPragmaAlignPack( Sema::PragmaAlignPackDiagnoseKind::ChangedStateAtExit, @@ -2064,8 +2065,11 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) { targetDiag(D->getLocation(), diag::note_defined_here, FD) << D; } - if (TI.hasRISCVVTypes() && Ty->isRVVSizelessBuiltinType()) - checkRVVTypeSupport(Ty, Loc, D); + if (TI.hasRISCVVTypes() && Ty->isRVVSizelessBuiltinType() && FD) { + llvm::StringMap CallerFeatureMap; + Context.getFunctionFeatureMap(CallerFeatureMap, FD); + checkRVVTypeSupport(Ty, Loc, D, CallerFeatureMap); + } // Don't allow SVE types in functions without a SVE target. if (Ty->isSVESizelessBuiltinType() && FD && FD->hasBody()) { @@ -2206,7 +2210,7 @@ static void checkEscapingByref(VarDecl *VD, Sema &S) { // block copy/destroy functions. Resolve it here. if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) if (CXXDestructorDecl *DD = RD->getDestructor()) { - auto *FPT = DD->getType()->getAs(); + auto *FPT = DD->getType()->castAs(); S.ResolveExceptionSpec(Loc, FPT); } } diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 836c633e9d20421e4be008599f001e211f75984b..a3128306c664fe17ffa439ceda3dda798c2e2f50 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -52,49 +52,54 @@ static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability, if (!Metadata.IsActive) return; - auto IsModified = [&](Decl *D, QualType QT, - NullabilityKind Nullability) -> bool { + auto GetModified = + [&](Decl *D, QualType QT, + NullabilityKind Nullability) -> std::optional { QualType Original = QT; S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(), isa(D), /*OverrideExisting=*/true); - return QT.getTypePtr() != Original.getTypePtr(); + return (QT.getTypePtr() != Original.getTypePtr()) ? std::optional(QT) + : std::nullopt; }; if (auto Function = dyn_cast(D)) { - if (IsModified(D, Function->getReturnType(), Nullability)) { - QualType FnType = Function->getType(); - Function->setType(FnType); + if (auto Modified = + GetModified(D, Function->getReturnType(), Nullability)) { + const FunctionType *FnType = Function->getType()->castAs(); + if (const FunctionProtoType *proto = dyn_cast(FnType)) + Function->setType(S.Context.getFunctionType( + *Modified, proto->getParamTypes(), proto->getExtProtoInfo())); + else + Function->setType( + S.Context.getFunctionNoProtoType(*Modified, FnType->getExtInfo())); } } else if (auto Method = dyn_cast(D)) { - QualType Type = Method->getReturnType(); - if (IsModified(D, Type, Nullability)) { - Method->setReturnType(Type); + if (auto Modified = GetModified(D, Method->getReturnType(), Nullability)) { + Method->setReturnType(*Modified); // Make it a context-sensitive keyword if we can. - if (!isIndirectPointerType(Type)) + if (!isIndirectPointerType(*Modified)) Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier( Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); } } else if (auto Value = dyn_cast(D)) { - QualType Type = Value->getType(); - if (IsModified(D, Type, Nullability)) { - Value->setType(Type); + if (auto Modified = GetModified(D, Value->getType(), Nullability)) { + Value->setType(*Modified); // Make it a context-sensitive keyword if we can. if (auto Parm = dyn_cast(D)) { - if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type)) + if (Parm->isObjCMethodParameter() && !isIndirectPointerType(*Modified)) Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier( Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); } } } else if (auto Property = dyn_cast(D)) { - QualType Type = Property->getType(); - if (IsModified(D, Type, Nullability)) { - Property->setType(Type, Property->getTypeSourceInfo()); + if (auto Modified = GetModified(D, Property->getType(), Nullability)) { + Property->setType(*Modified, Property->getTypeSourceInfo()); // Make it a property attribute if we can. - if (!isIndirectPointerType(Type)) + if (!isIndirectPointerType(*Modified)) Property->setPropertyAttributes( ObjCPropertyAttribute::kind_null_resettable); } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 246e3577809a795f939ea223d739351437b141a7..f5c0c761da75affa27587dc1ab5556aae3c5484f 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1098,7 +1098,7 @@ static bool ProcessFormatStringLiteral(const Expr *FormatExpr, const ConstantArrayType *T = Context.getAsConstantArrayType(Format->getType()); assert(T && "String literal not of constant array type!"); - size_t TypeSize = T->getSize().getZExtValue(); + size_t TypeSize = T->getZExtSize(); // In case there's a null byte somewhere. StrLen = std::min(std::max(TypeSize, size_t(1)) - 1, FormatStrRef.find(0)); return true; @@ -5541,6 +5541,14 @@ bool CheckNoDoubleVectors(Sema *S, CallExpr *TheCall) { checkDoubleVector); } +bool CheckUnsignedIntRepresentation(Sema *S, CallExpr *TheCall) { + auto checkAllUnsignedTypes = [](clang::QualType PassedType) -> bool { + return !PassedType->hasUnsignedIntegerRepresentation(); + }; + return CheckArgsTypesAreCorrect(S, TheCall, S->Context.UnsignedIntTy, + checkAllUnsignedTypes); +} + void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType) { auto *VecTyA = TheCall->getArg(0)->getType()->getAs(); @@ -5624,6 +5632,26 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { TheCall, /*CheckForFloatArgs*/ TheCall->getArg(0)->getType()->hasFloatingRepresentation())) return true; + break; + } + // Note these are llvm builtins that we want to catch invalid intrinsic + // generation. Normal handling of these builitns will occur elsewhere. + case Builtin::BI__builtin_elementwise_bitreverse: { + if (CheckUnsignedIntRepresentation(this, TheCall)) + return true; + break; + } + case Builtin::BI__builtin_elementwise_cos: + case Builtin::BI__builtin_elementwise_sin: + case Builtin::BI__builtin_elementwise_log: + case Builtin::BI__builtin_elementwise_log2: + case Builtin::BI__builtin_elementwise_log10: + case Builtin::BI__builtin_elementwise_pow: + case Builtin::BI__builtin_elementwise_sqrt: + case Builtin::BI__builtin_elementwise_trunc: { + if (CheckFloatOrHalfRepresentations(this, TheCall)) + return true; + break; } } return false; @@ -5745,57 +5773,6 @@ static bool CheckInvalidVLENandLMUL(const TargetInfo &TI, CallExpr *TheCall, bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall) { - // CodeGenFunction can also detect this, but this gives a better error - // message. - bool FeatureMissing = false; - SmallVector ReqFeatures; - StringRef Features = Context.BuiltinInfo.getRequiredFeatures(BuiltinID); - Features.split(ReqFeatures, ',', -1, false); - - // Check if each required feature is included - for (StringRef F : ReqFeatures) { - SmallVector ReqOpFeatures; - F.split(ReqOpFeatures, '|'); - - if (llvm::none_of(ReqOpFeatures, - [&TI](StringRef OF) { return TI.hasFeature(OF); })) { - std::string FeatureStrs; - bool IsExtension = true; - for (StringRef OF : ReqOpFeatures) { - // If the feature is 64bit, alter the string so it will print better in - // the diagnostic. - if (OF == "64bit") { - assert(ReqOpFeatures.size() == 1 && "Expected '64bit' to be alone"); - OF = "RV64"; - IsExtension = false; - } - if (OF == "32bit") { - assert(ReqOpFeatures.size() == 1 && "Expected '32bit' to be alone"); - OF = "RV32"; - IsExtension = false; - } - - // Convert features like "zbr" and "experimental-zbr" to "Zbr". - OF.consume_front("experimental-"); - std::string FeatureStr = OF.str(); - FeatureStr[0] = std::toupper(FeatureStr[0]); - // Combine strings. - FeatureStrs += FeatureStrs.empty() ? "" : ", "; - FeatureStrs += "'"; - FeatureStrs += FeatureStr; - FeatureStrs += "'"; - } - // Error message - FeatureMissing = true; - Diag(TheCall->getBeginLoc(), diag::err_riscv_builtin_requires_extension) - << IsExtension - << TheCall->getSourceRange() << StringRef(FeatureStrs); - } - } - - if (FeatureMissing) - return true; - // vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx, // vsmul.vv, vsmul.vx are not included for EEW=64 in Zve64*. switch (BuiltinID) { @@ -6699,36 +6676,35 @@ bool Sema::CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, return false; } -void Sema::checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D) { - const TargetInfo &TI = Context.getTargetInfo(); - +void Sema::checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D, + const llvm::StringMap &FeatureMap) { ASTContext::BuiltinVectorTypeInfo Info = Context.getBuiltinVectorTypeInfo(Ty->castAs()); unsigned EltSize = Context.getTypeSize(Info.ElementType); unsigned MinElts = Info.EC.getKnownMinValue(); if (Info.ElementType->isSpecificBuiltinType(BuiltinType::Double) && - !TI.hasFeature("zve64d")) + !FeatureMap.lookup("zve64d")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve64d"; // (ELEN, LMUL) pairs of (8, mf8), (16, mf4), (32, mf2), (64, m1) requires at // least zve64x else if (((EltSize == 64 && Info.ElementType->isIntegerType()) || MinElts == 1) && - !TI.hasFeature("zve64x")) + !FeatureMap.lookup("zve64x")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve64x"; - else if (Info.ElementType->isFloat16Type() && !TI.hasFeature("zvfh") && - !TI.hasFeature("zvfhmin")) + else if (Info.ElementType->isFloat16Type() && !FeatureMap.lookup("zvfh") && + !FeatureMap.lookup("zvfhmin")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zvfh or zvfhmin"; else if (Info.ElementType->isBFloat16Type() && - !TI.hasFeature("experimental-zvfbfmin")) + !FeatureMap.lookup("experimental-zvfbfmin")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zvfbfmin"; else if (Info.ElementType->isSpecificBuiltinType(BuiltinType::Float) && - !TI.hasFeature("zve32f")) + !FeatureMap.lookup("zve32f")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve32f"; // Given that caller already checked isRVVType() before calling this function, // if we don't have at least zve32x supported, then we need to emit error. - else if (!TI.hasFeature("zve32x")) + else if (!FeatureMap.lookup("zve32x")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve32x"; } @@ -9694,7 +9670,7 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs, // vector argument can be supported in all of them. if (ElementTy->isVectorType() && IsFPClass) { VectorResultTy = GetSignedVectorType(ElementTy); - ElementTy = ElementTy->getAs()->getElementType(); + ElementTy = ElementTy->castAs()->getElementType(); } // This operation requires a non-_Complex floating-point number. @@ -13029,7 +13005,7 @@ static void CheckFormatString( const ConstantArrayType *T = S.Context.getAsConstantArrayType(FExpr->getType()); assert(T && "String literal not of constant array type!"); - size_t TypeSize = T->getSize().getZExtValue(); + size_t TypeSize = T->getZExtSize(); size_t StrLen = std::min(std::max(TypeSize, size_t(1)) - 1, StrRef.size()); const unsigned numDataArgs = Args.size() - firstDataArg; @@ -13089,7 +13065,7 @@ bool Sema::FormatStringHasSArg(const StringLiteral *FExpr) { // Account for cases where the string literal is truncated in a declaration. const ConstantArrayType *T = Context.getAsConstantArrayType(FExpr->getType()); assert(T && "String literal not of constant array type!"); - size_t TypeSize = T->getSize().getZExtValue(); + size_t TypeSize = T->getZExtSize(); size_t StrLen = std::min(std::max(TypeSize, size_t(1)) - 1, StrRef.size()); return analyze_format_string::ParseFormatStringHasSArg(Str, Str + StrLen, getLangOpts(), @@ -14052,7 +14028,7 @@ static bool isConstantSizeArrayWithMoreThanOneElement(QualType Ty, // Only handle constant-sized or VLAs, but not flexible members. if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(Ty)) { // Only issue the FIXIT for arrays of size > 1. - if (CAT->getSize().getSExtValue() <= 1) + if (CAT->getZExtSize() <= 1) return false; } else if (!Ty->isVariableArrayType()) { return false; diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 73e6baa5278262e29397f9b617e512ffa5d8423c..83ebcaf9e765a78e95de4630df7b0b8f55f370ff 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -20,6 +20,7 @@ #include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/OperationKinds.h" #include "clang/AST/QualTypeNames.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" @@ -5678,6 +5679,10 @@ QualType getApproximateType(const Expr *E) { return getApproximateType(VD->getInit()); } } + if (const auto *UO = llvm::dyn_cast(E)) { + if (UO->getOpcode() == UnaryOperatorKind::UO_Deref) + return UO->getSubExpr()->getType()->getPointeeType(); + } return Unresolved; } diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 1c546e9f5894f024521d2410062e35204f35fa0b..b6c4d3d540ef50caf52f111859fd291c402b1376 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -1269,10 +1269,18 @@ substituteParameterMappings(Sema &S, NormalizedConstraint &N, : SourceLocation())); Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count()); } + SourceLocation InstLocBegin = + ArgsAsWritten->arguments().empty() + ? ArgsAsWritten->getLAngleLoc() + : ArgsAsWritten->arguments().front().getSourceRange().getBegin(); + SourceLocation InstLocEnd = + ArgsAsWritten->arguments().empty() + ? ArgsAsWritten->getRAngleLoc() + : ArgsAsWritten->arguments().front().getSourceRange().getEnd(); Sema::InstantiatingTemplate Inst( - S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(), + S, InstLocBegin, Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept, - ArgsAsWritten->arguments().front().getSourceRange()); + {InstLocBegin, InstLocEnd}); if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs)) return true; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index aa754d47a0c43a0620753b427b33314175b5294a..0bd88ece2aa5442ac6476b3d2558a1cc9faa66b9 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8837,7 +8837,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { return; } const auto *ATy = dyn_cast(T.getTypePtr()); - if (!ATy || ATy->getSize().getSExtValue() != 0) { + if (!ATy || ATy->getZExtSize() != 0) { Diag(NewVD->getLocation(), diag::err_typecheck_wasm_table_must_have_zero_length); NewVD->setInvalidDecl(); @@ -8962,8 +8962,13 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { } } - if (T->isRVVSizelessBuiltinType()) - checkRVVTypeSupport(T, NewVD->getLocation(), cast(CurContext)); + if (T->isRVVSizelessBuiltinType() && isa(CurContext)) { + const FunctionDecl *FD = cast(CurContext); + llvm::StringMap CallerFeatureMap; + Context.getFunctionFeatureMap(CallerFeatureMap, FD); + checkRVVTypeSupport(T, NewVD->getLocation(), cast(CurContext), + CallerFeatureMap); + } } /// Perform semantic checking on a newly-created variable @@ -11260,11 +11265,13 @@ static bool checkNonMultiVersionCompatAttributes(Sema &S, return Diagnose(S, A); break; case attr::TargetVersion: - if (MVKind != MultiVersionKind::TargetVersion) + if (MVKind != MultiVersionKind::TargetVersion && + MVKind != MultiVersionKind::TargetClones) return Diagnose(S, A); break; case attr::TargetClones: - if (MVKind != MultiVersionKind::TargetClones) + if (MVKind != MultiVersionKind::TargetClones && + MVKind != MultiVersionKind::TargetVersion) return Diagnose(S, A); break; default: @@ -11441,9 +11448,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)) { @@ -11469,6 +11476,22 @@ static bool PreviousDeclsHaveMultiVersionAttribute(const FunctionDecl *FD) { return false; } +static void patchDefaultTargetVersion(FunctionDecl *From, FunctionDecl *To) { + if (!From->getASTContext().getTargetInfo().getTriple().isAArch64()) + return; + + MultiVersionKind MVKindFrom = From->getMultiVersionKind(); + MultiVersionKind MVKindTo = To->getMultiVersionKind(); + + if (MVKindTo == MultiVersionKind::None && + (MVKindFrom == MultiVersionKind::TargetVersion || + MVKindFrom == MultiVersionKind::TargetClones)) { + To->setIsMultiVersion(); + To->addAttr(TargetVersionAttr::CreateImplicit( + To->getASTContext(), "default", To->getSourceRange())); + } +} + static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD, bool &Redeclaration, @@ -11479,10 +11502,7 @@ static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD, // The definitions should be allowed in any order. If we have discovered // a new target version and the preceeding was the default, then add the // corresponding attribute to it. - if (OldFD->getMultiVersionKind() == MultiVersionKind::None && - NewFD->getMultiVersionKind() == MultiVersionKind::TargetVersion) - OldFD->addAttr(TargetVersionAttr::CreateImplicit(S.Context, "default", - OldFD->getSourceRange())); + patchDefaultTargetVersion(NewFD, OldFD); const auto *NewTA = NewFD->getAttr(); const auto *NewTVA = NewFD->getAttr(); @@ -11583,36 +11603,60 @@ static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD, return false; } -static bool MultiVersionTypesCompatible(MultiVersionKind Old, - MultiVersionKind New) { - if (Old == New || Old == MultiVersionKind::None || - New == MultiVersionKind::None) +static bool MultiVersionTypesCompatible(FunctionDecl *Old, FunctionDecl *New) { + MultiVersionKind OldKind = Old->getMultiVersionKind(); + MultiVersionKind NewKind = New->getMultiVersionKind(); + + if (OldKind == NewKind || OldKind == MultiVersionKind::None || + NewKind == MultiVersionKind::None) return true; - return (Old == MultiVersionKind::CPUDispatch && - New == MultiVersionKind::CPUSpecific) || - (Old == MultiVersionKind::CPUSpecific && - New == MultiVersionKind::CPUDispatch); + if (Old->getASTContext().getTargetInfo().getTriple().isAArch64()) { + switch (OldKind) { + case MultiVersionKind::TargetVersion: + return NewKind == MultiVersionKind::TargetClones; + case MultiVersionKind::TargetClones: + return NewKind == MultiVersionKind::TargetVersion; + default: + return false; + } + } else { + switch (OldKind) { + case MultiVersionKind::CPUDispatch: + return NewKind == MultiVersionKind::CPUSpecific; + case MultiVersionKind::CPUSpecific: + return NewKind == MultiVersionKind::CPUDispatch; + default: + return false; + } + } } /// Check the validity of a new function declaration being added to an existing /// multiversioned declaration collection. static bool CheckMultiVersionAdditionalDecl( Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD, - MultiVersionKind NewMVKind, const CPUDispatchAttr *NewCPUDisp, - const CPUSpecificAttr *NewCPUSpec, const TargetClonesAttr *NewClones, - bool &Redeclaration, NamedDecl *&OldDecl, LookupResult &Previous) { - const auto *NewTA = NewFD->getAttr(); - const auto *NewTVA = NewFD->getAttr(); - MultiVersionKind OldMVKind = OldFD->getMultiVersionKind(); + const CPUDispatchAttr *NewCPUDisp, const CPUSpecificAttr *NewCPUSpec, + const TargetClonesAttr *NewClones, bool &Redeclaration, NamedDecl *&OldDecl, + LookupResult &Previous) { + // Disallow mixing of multiversioning types. - if (!MultiVersionTypesCompatible(OldMVKind, NewMVKind)) { + if (!MultiVersionTypesCompatible(OldFD, NewFD)) { S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed); S.Diag(OldFD->getLocation(), diag::note_previous_declaration); NewFD->setInvalidDecl(); return true; } + // Add the default target_version attribute if it's missing. + patchDefaultTargetVersion(OldFD, NewFD); + patchDefaultTargetVersion(NewFD, OldFD); + + const auto *NewTA = NewFD->getAttr(); + const auto *NewTVA = NewFD->getAttr(); + MultiVersionKind NewMVKind = NewFD->getMultiVersionKind(); + [[maybe_unused]] MultiVersionKind OldMVKind = OldFD->getMultiVersionKind(); + ParsedTargetAttr NewParsed; if (NewTA) { NewParsed = S.getASTContext().getTargetInfo().parseTargetAttr( @@ -11641,19 +11685,6 @@ static bool CheckMultiVersionAdditionalDecl( S.IsOverload(NewFD, CurFD, UseMemberUsingDeclRules)) continue; - if (NewMVKind == MultiVersionKind::None && - OldMVKind == MultiVersionKind::TargetVersion) { - NewFD->addAttr(TargetVersionAttr::CreateImplicit( - S.Context, "default", NewFD->getSourceRange())); - NewFD->setIsMultiVersion(); - NewMVKind = MultiVersionKind::TargetVersion; - if (!NewTVA) { - NewTVA = NewFD->getAttr(); - NewTVA->getFeatures(NewFeats); - llvm::sort(NewFeats); - } - } - switch (NewMVKind) { case MultiVersionKind::None: assert(OldMVKind == MultiVersionKind::TargetClones && @@ -11681,43 +11712,81 @@ static bool CheckMultiVersionAdditionalDecl( break; } case MultiVersionKind::TargetVersion: { - const auto *CurTVA = CurFD->getAttr(); - if (CurTVA->getName() == NewTVA->getName()) { - NewFD->setIsMultiVersion(); - Redeclaration = true; - OldDecl = ND; - return false; - } - llvm::SmallVector CurFeats; - if (CurTVA) { + if (const auto *CurTVA = CurFD->getAttr()) { + if (CurTVA->getName() == NewTVA->getName()) { + NewFD->setIsMultiVersion(); + Redeclaration = true; + OldDecl = ND; + return false; + } + llvm::SmallVector CurFeats; CurTVA->getFeatures(CurFeats); llvm::sort(CurFeats); - } - if (CurFeats == NewFeats) { - S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); - S.Diag(CurFD->getLocation(), diag::note_previous_declaration); - NewFD->setInvalidDecl(); - return true; + + if (CurFeats == NewFeats) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); + S.Diag(CurFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + } else if (const auto *CurClones = CurFD->getAttr()) { + // Default + if (NewFeats.empty()) + break; + + for (unsigned I = 0; I < CurClones->featuresStrs_size(); ++I) { + llvm::SmallVector CurFeats; + CurClones->getFeatures(CurFeats, I); + llvm::sort(CurFeats); + + if (CurFeats == NewFeats) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); + S.Diag(CurFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + } } break; } case MultiVersionKind::TargetClones: { - const auto *CurClones = CurFD->getAttr(); + assert(NewClones && "MultiVersionKind does not match attribute type"); + if (const auto *CurClones = CurFD->getAttr()) { + if (CurClones->featuresStrs_size() != NewClones->featuresStrs_size() || + !std::equal(CurClones->featuresStrs_begin(), + CurClones->featuresStrs_end(), + NewClones->featuresStrs_begin())) { + S.Diag(NewFD->getLocation(), diag::err_target_clone_doesnt_match); + S.Diag(CurFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + } else if (const auto *CurTVA = CurFD->getAttr()) { + llvm::SmallVector CurFeats; + CurTVA->getFeatures(CurFeats); + llvm::sort(CurFeats); + + // Default + if (CurFeats.empty()) + break; + + for (unsigned I = 0; I < NewClones->featuresStrs_size(); ++I) { + NewFeats.clear(); + NewClones->getFeatures(NewFeats, I); + llvm::sort(NewFeats); + + if (CurFeats == NewFeats) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); + S.Diag(CurFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + } + break; + } Redeclaration = true; OldDecl = CurFD; NewFD->setIsMultiVersion(); - - if (CurClones && NewClones && - (CurClones->featuresStrs_size() != NewClones->featuresStrs_size() || - !std::equal(CurClones->featuresStrs_begin(), - CurClones->featuresStrs_end(), - NewClones->featuresStrs_begin()))) { - S.Diag(NewFD->getLocation(), diag::err_target_clone_doesnt_match); - S.Diag(CurFD->getLocation(), diag::note_previous_declaration); - NewFD->setInvalidDecl(); - return true; - } - return false; } case MultiVersionKind::CPUSpecific: @@ -11913,7 +11982,7 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD, // At this point, we have a multiversion function decl (in OldFD) AND an // appropriate attribute in the current function decl. Resolve that these are // still compatible with previous declarations. - return CheckMultiVersionAdditionalDecl(S, OldFD, NewFD, MVKind, NewCPUDisp, + return CheckMultiVersionAdditionalDecl(S, OldFD, NewFD, NewCPUDisp, NewCPUSpec, NewClones, Redeclaration, OldDecl, Previous); } @@ -19360,15 +19429,11 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, } else if (Record->isUnion()) DiagID = getLangOpts().MicrosoftExt ? diag::ext_flexible_array_union_ms - : getLangOpts().CPlusPlus - ? diag::ext_flexible_array_union_gnu - : diag::err_flexible_array_union; + : diag::ext_flexible_array_union_gnu; else if (NumNamedMembers < 1) DiagID = getLangOpts().MicrosoftExt ? diag::ext_flexible_array_empty_aggregate_ms - : getLangOpts().CPlusPlus - ? diag::ext_flexible_array_empty_aggregate_gnu - : diag::err_flexible_array_empty_aggregate; + : diag::ext_flexible_array_empty_aggregate_gnu; if (DiagID) Diag(FD->getLocation(), DiagID) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 0a62c656d824ffc47d7c28a989dd5dfa4a13e54b..f25f3afd0f4af273cca71e4e6022326ab62aab6e 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5271,6 +5271,9 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { case ParsedAttr::AT_PreserveNone: D->addAttr(::new (S.Context) PreserveNoneAttr(S.Context, AL)); return; + case ParsedAttr::AT_RISCVVectorCC: + D->addAttr(::new (S.Context) RISCVVectorCCAttr(S.Context, AL)); + return; default: llvm_unreachable("unexpected attribute kind"); } @@ -5475,6 +5478,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, case ParsedAttr::AT_PreserveNone: CC = CC_PreserveNone; break; + case ParsedAttr::AT_RISCVVectorCC: + CC = CC_RISCVVectorCall; + break; default: llvm_unreachable("unexpected attribute kind"); } @@ -9637,6 +9643,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_AMDGPUKernelCall: case ParsedAttr::AT_M68kRTD: case ParsedAttr::AT_PreserveNone: + case ParsedAttr::AT_RISCVVectorCC: handleCallConvAttr(S, D, AL); break; case ParsedAttr::AT_Suppress: diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index ee732679417e37c5c5584a6591e16f87c2ebd54e..e9fecaea84b021fe29e011fa18cb4c926e6d092b 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5282,7 +5282,7 @@ static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) { return true; while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) { - if (!ArrayT->getSize()) + if (ArrayT->isZeroSize()) return true; T = ArrayT->getElementType(); @@ -11353,7 +11353,7 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { if (ConvType->isUndeducedAutoType()) { Diag(Conversion->getTypeSpecStartLoc(), diag::err_auto_not_allowed) << getReturnTypeLoc(Conversion).getSourceRange() - << llvm::to_underlying(ConvType->getAs()->getKeyword()) + << llvm::to_underlying(ConvType->castAs()->getKeyword()) << /* in declaration of conversion function template= */ 24; } @@ -16202,7 +16202,8 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { // Emit warning for non-trivial dtor in global scope (a real global, // class-static, function-static). - Diag(VD->getLocation(), diag::warn_exit_time_destructor); + if (!VD->hasAttr()) + Diag(VD->getLocation(), diag::warn_exit_time_destructor); // TODO: this should be re-enabled for static locals by !CXAAtExit if (!VD->isStaticLocal()) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5f03b981428251ca23c34d5cd96b4bec370222b2..091fc3e4836b63c0a2237f0a39ed6ed8e25fbe33 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6857,9 +6857,8 @@ Sema::CheckStaticArrayArgument(SourceLocation CallLoc, ArgCAT->getElementType())) { if (ArgCAT->getSize().ult(CAT->getSize())) { Diag(CallLoc, diag::warn_static_array_too_small) - << ArgExpr->getSourceRange() - << (unsigned)ArgCAT->getSize().getZExtValue() - << (unsigned)CAT->getSize().getZExtValue() << 0; + << ArgExpr->getSourceRange() << (unsigned)ArgCAT->getZExtSize() + << (unsigned)CAT->getZExtSize() << 0; DiagnoseCalleeStaticArrayParam(*this, Param); } return; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index c34a40fa7c81ac9ac3d3c67371a1da05ebe17a92..51c8e04bee8c31b8dc66279f71ed5d08d92e8b5c 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6083,7 +6083,7 @@ static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT, if (Matched && T->isArrayType()) { if (const ConstantArrayType *CAT = Self.Context.getAsConstantArrayType(T)) - return CAT->getSize().getLimitedValue(); + return CAT->getLimitedSize(); } } return 0; diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index aa470adb30b47f545e063cf7102c8c2ac7c32e02..dce225a7204da82a71fc9b4992ae865384887585 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -213,7 +213,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, // Get the length of the string as parsed. auto *ConstantArrayTy = cast(Str->getType()->getAsArrayTypeUnsafe()); - uint64_t StrLength = ConstantArrayTy->getSize().getZExtValue(); + uint64_t StrLength = ConstantArrayTy->getZExtSize(); if (CheckC23ConstexprInit) if (const StringLiteral *SL = dyn_cast(Str->IgnoreParens())) @@ -246,14 +246,13 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, } // [dcl.init.string]p2 - if (StrLength > CAT->getSize().getZExtValue()) + if (StrLength > CAT->getZExtSize()) S.Diag(Str->getBeginLoc(), diag::err_initializer_string_for_char_array_too_long) - << CAT->getSize().getZExtValue() << StrLength - << Str->getSourceRange(); + << CAT->getZExtSize() << StrLength << Str->getSourceRange(); } else { // C99 6.7.8p14. - if (StrLength-1 > CAT->getSize().getZExtValue()) + if (StrLength - 1 > CAT->getZExtSize()) S.Diag(Str->getBeginLoc(), diag::ext_initializer_string_for_char_array_too_long) << Str->getSourceRange(); @@ -879,7 +878,7 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) { ElementType = AType->getElementType(); if (const auto *CAType = dyn_cast(AType)) - NumElements = CAType->getSize().getZExtValue(); + NumElements = CAType->getZExtSize(); // For an array new with an unknown bound, ask for one additional element // in order to populate the array filler. if (Entity.isVariableLengthArrayNew()) @@ -1016,7 +1015,7 @@ int InitListChecker::numArrayElements(QualType DeclType) { int maxElements = 0x7FFFFFFF; if (const ConstantArrayType *CAT = SemaRef.Context.getAsConstantArrayType(DeclType)) { - maxElements = static_cast(CAT->getSize().getZExtValue()); + maxElements = static_cast(CAT->getZExtSize()); } return maxElements; } @@ -2330,11 +2329,11 @@ void InitListChecker::CheckStructUnionTypes( break; } - // We've already initialized a member of a union. We're done. + // We've already initialized a member of a union. We can stop entirely. if (InitializedSomething && RD->isUnion()) - break; + return; - // If we've hit the flexible array member at the end, we're done. + // Stop if we've hit a flexible array member. if (Field->getType()->isIncompleteArrayType()) break; @@ -2457,6 +2456,11 @@ void InitListChecker::CheckStructUnionTypes( else CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index, StructuredList, StructuredIndex); + + if (RD->isUnion() && StructuredList) { + // Initialize the first field within the union. + StructuredList->setInitializedFieldInUnion(*Field); + } } /// Expand a field designator that refers to a member of an @@ -3101,7 +3105,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // Get the length of the string. uint64_t StrLen = SL->getLength(); if (cast(AT)->getSize().ult(StrLen)) - StrLen = cast(AT)->getSize().getZExtValue(); + StrLen = cast(AT)->getZExtSize(); StructuredList->resizeInits(Context, StrLen); // Build a literal for each character in the string, and put them into @@ -3124,7 +3128,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // Get the length of the string. uint64_t StrLen = Str.size(); if (cast(AT)->getSize().ult(StrLen)) - StrLen = cast(AT)->getSize().getZExtValue(); + StrLen = cast(AT)->getZExtSize(); StructuredList->resizeInits(Context, StrLen); // Build a literal for each character in the string, and put them into @@ -3283,7 +3287,7 @@ InitListChecker::createInitListExpr(QualType CurrentObjectType, if (const ArrayType *AType = SemaRef.Context.getAsArrayType(CurrentObjectType)) { if (const ConstantArrayType *CAType = dyn_cast(AType)) { - NumElements = CAType->getSize().getZExtValue(); + NumElements = CAType->getZExtSize(); // Simple heuristic so that we don't allocate a very large // initializer with many empty entries at the end. if (NumElements > ExpectedNumInits) @@ -5492,7 +5496,7 @@ static void TryOrBuildParenListInitialization( // having k elements. if (const ConstantArrayType *CAT = S.getASTContext().getAsConstantArrayType(Entity.getType())) { - ArrayLength = CAT->getSize().getZExtValue(); + ArrayLength = CAT->getZExtSize(); ResultType = Entity.getType(); } else if (const VariableArrayType *VAT = S.getASTContext().getAsVariableArrayType(Entity.getType())) { diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 4636d89ebf2b84f5d817509495f5e3a6cb551c5e..f9e1ad0121e2a2ab9579674b7170598a0280bc05 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -638,8 +638,6 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, PDecl->setInvalidDecl(); } - ProcessDeclAttributes(S, PDecl, FD.D); - // Regardless of setter/getter attribute, we save the default getter/setter // selector names in anticipation of declaration of setter/getter methods. PDecl->setGetterName(GetterSel, GetterNameLoc); @@ -647,6 +645,8 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, PDecl->setPropertyAttributesAsWritten( makePropertyAttributesAsWritten(AttributesAsWritten)); + ProcessDeclAttributes(S, PDecl, FD.D); + if (Attributes & ObjCPropertyAttribute::kind_readonly) PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_readonly); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index e9ad7bbde0f9b5d71e51e929a825b0e253d43cb3..0ba54a3a9cae3565bffc667b0b22e7ce3c825da1 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -21284,7 +21284,7 @@ static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, if (isa(E) || (OASE && OASE->getColonLocFirst().isInvalid())) { if (const auto *ATy = dyn_cast(BaseQTy.getTypePtr())) - return ATy->getSize().getSExtValue() != 1; + return ATy->getSExtSize() != 1; // Size can't be evaluated statically. return false; } @@ -21325,7 +21325,7 @@ static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, return false; // Can't get the integer value as a constant. llvm::APSInt ConstLength = Result.Val.getInt(); - return CATy->getSize().getSExtValue() != ConstLength.getSExtValue(); + return CATy->getSExtSize() != ConstLength.getSExtValue(); } // Return true if it can be proven that the provided array expression (array @@ -21350,7 +21350,7 @@ static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, // is pointer. if (!Length) { if (const auto *ATy = dyn_cast(BaseQTy.getTypePtr())) - return ATy->getSize().getSExtValue() != 1; + return ATy->getSExtSize() != 1; // We cannot assume anything. return false; } 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/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index ca0254d29e7f408a2499a895b428606933dcd3f5..18ebaa13346a443ee9bbff8346b2dbacc94271cf 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -35,7 +35,7 @@ Sema::SemaDiagnosticBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc, static bool isZeroSizedArray(Sema &SemaRef, QualType Ty) { if (const auto *CAT = SemaRef.getASTContext().getAsConstantArrayType(Ty)) - return CAT->getSize() == 0; + return CAT->isZeroSize(); return false; } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 97f8445bf819c8fa4cb8da6a5a8356afaa35e571..9a55881f6442545baac1df55a30a9e0236e3986d 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -5514,9 +5514,9 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate( QualType Obj2Ty; if (TPOC == TPOC_Call) { const FunctionProtoType *Proto1 = - FD1->getType()->getAs(); + FD1->getType()->castAs(); const FunctionProtoType *Proto2 = - FD2->getType()->getAs(); + FD2->getType()->castAs(); // - In the context of a function call, the function parameter types are // used. diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index d7521a5363a3d2c57f4b3dfa313d099973376e44..fd94caa4e1d449a58aa3d9c6f2f2c16dbd266c42 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -138,7 +138,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr, case ParsedAttr::AT_PreserveMost: \ case ParsedAttr::AT_PreserveAll: \ case ParsedAttr::AT_M68kRTD: \ - case ParsedAttr::AT_PreserveNone + case ParsedAttr::AT_PreserveNone: \ + case ParsedAttr::AT_RISCVVectorCC // Function type attributes. #define FUNCTION_TYPE_ATTRS_CASELIST \ @@ -7939,6 +7940,8 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) { return createSimpleAttr(Ctx, Attr); case ParsedAttr::AT_PreserveNone: return createSimpleAttr(Ctx, Attr); + case ParsedAttr::AT_RISCVVectorCC: + return createSimpleAttr(Ctx, Attr); } llvm_unreachable("unexpected attribute kind!"); } 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/CastSizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp index a50772f881f7d0fdabf0427c012fa0fe329331a3..2cff97a591b8c0ac8b3f855f96704cba2ba9774e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp @@ -68,7 +68,7 @@ static bool evenFlexibleArraySize(ASTContext &Ctx, CharUnits RegionSize, FlexSize = Ctx.getTypeSizeInChars(ElemType); if (ArrayTy->getSize() == 1 && TypeSize > FlexSize) TypeSize -= FlexSize; - else if (ArrayTy->getSize() != 0) + else if (!ArrayTy->isZeroSize()) return false; } else if (RD->hasFlexibleArrayMember()) { FlexSize = Ctx.getTypeSizeInChars(ElemType); 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/PaddingChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp index eee9449f31805c2fe4aa32575c3f57302615ed6a..4f35d9442ad9886b90e4889657d7424bc683f6d5 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp @@ -117,7 +117,7 @@ public: return; uint64_t Elts = 0; if (const ConstantArrayType *CArrTy = dyn_cast(ArrTy)) - Elts = CArrTy->getSize().getZExtValue(); + Elts = CArrTy->getZExtSize(); if (Elts == 0) return; const RecordType *RT = ArrTy->getElementType()->getAs(); 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/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index a8e573f7982b12a1eaf336d9fbca06d844d4bfde..d6e4f23cc353f153c2db094ec625d7883f369cb6 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -825,7 +825,7 @@ DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR, }; auto IsArrayOfZero = [](const ArrayType *AT) { const auto *CAT = dyn_cast(AT); - return CAT && CAT->getSize() == 0; + return CAT && CAT->isZeroSize(); }; auto IsArrayOfOne = [](const ArrayType *AT) { const auto *CAT = dyn_cast(AT); diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index da9a1a1a4d1f6945713311ddd02d2e7ea47f879f..755a8c4b22fd9e907a68de2fbd3ec441ac29a8ec 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1166,7 +1166,7 @@ void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR, // Compute lower and upper offsets for region within array. if (const ConstantArrayType *CAT = dyn_cast(AT)) - NumElements = CAT->getSize().getZExtValue(); + NumElements = CAT->getZExtSize(); if (!NumElements) // We are not dealing with a constant size array goto conjure_default; QualType ElementTy = AT->getElementType(); @@ -1613,7 +1613,7 @@ getConstantArrayExtents(const ConstantArrayType *CAT) { CAT = cast(CAT->getCanonicalTypeInternal()); SmallVector Extents; do { - Extents.push_back(CAT->getSize().getZExtValue()); + Extents.push_back(CAT->getZExtSize()); } while ((CAT = dyn_cast(CAT->getElementType()))); return Extents; } @@ -2436,7 +2436,7 @@ std::optional RegionStoreManager::tryBindSmallArray( return std::nullopt; // If the array is too big, create a LCV instead. - uint64_t ArrSize = CAT->getSize().getLimitedValue(); + uint64_t ArrSize = CAT->getLimitedSize(); if (ArrSize > SmallArrayLimit) return std::nullopt; @@ -2465,7 +2465,7 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B, std::optional Size; if (const ConstantArrayType* CAT = dyn_cast(AT)) - Size = CAT->getSize().getZExtValue(); + Size = CAT->getZExtSize(); // Check if the init expr is a literal. If so, bind the rvalue instead. // FIXME: It's not responsibility of the Store to transform this lvalue 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/APINotes/Inputs/APINotes/SomeOtherKit.apinotes b/clang/test/APINotes/Inputs/APINotes/SomeOtherKit.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..ccdc4e15d34d1b236332923843765d50ee8d976b --- /dev/null +++ b/clang/test/APINotes/Inputs/APINotes/SomeOtherKit.apinotes @@ -0,0 +1,8 @@ +Name: SomeOtherKit +Classes: + - Name: A + Methods: + - Selector: "methodB" + MethodKind: Instance + Availability: none + AvailabilityMsg: "anything but this" diff --git a/clang/test/APINotes/Inputs/BrokenHeaders/APINotes.apinotes b/clang/test/APINotes/Inputs/BrokenHeaders/APINotes.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..cd5475b1342315947390b65aca0f4640194fb946 --- /dev/null +++ b/clang/test/APINotes/Inputs/BrokenHeaders/APINotes.apinotes @@ -0,0 +1,5 @@ +Name: SomeBrokenLib +Functions: + - Name: do_something_with_pointers + Nu llabilityOfRet: O + # the space is intentional, to make sure we don't crash on malformed API Notes diff --git a/clang/test/APINotes/Inputs/BrokenHeaders/SomeBrokenLib.h b/clang/test/APINotes/Inputs/BrokenHeaders/SomeBrokenLib.h new file mode 100644 index 0000000000000000000000000000000000000000..b09c6f63eae02edcf0228bebec1a3f504085bb2d --- /dev/null +++ b/clang/test/APINotes/Inputs/BrokenHeaders/SomeBrokenLib.h @@ -0,0 +1,6 @@ +#ifndef SOME_BROKEN_LIB_H +#define SOME_BROKEN_LIB_H + +void do_something_with_pointers(int *ptr1, int *ptr2); + +#endif // SOME_BROKEN_LIB_H diff --git a/clang/test/APINotes/Inputs/BrokenHeaders2/APINotes.apinotes b/clang/test/APINotes/Inputs/BrokenHeaders2/APINotes.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..33eeaaada999d69f0bcb106598407226736abac4 --- /dev/null +++ b/clang/test/APINotes/Inputs/BrokenHeaders2/APINotes.apinotes @@ -0,0 +1,7 @@ +Name: SomeBrokenLib +Functions: + - Name: do_something_with_pointers + NullabilityOfRet: O + - Name: do_something_with_pointers + NullabilityOfRet: O + diff --git a/clang/test/APINotes/Inputs/BrokenHeaders2/SomeBrokenLib.h b/clang/test/APINotes/Inputs/BrokenHeaders2/SomeBrokenLib.h new file mode 100644 index 0000000000000000000000000000000000000000..b09c6f63eae02edcf0228bebec1a3f504085bb2d --- /dev/null +++ b/clang/test/APINotes/Inputs/BrokenHeaders2/SomeBrokenLib.h @@ -0,0 +1,6 @@ +#ifndef SOME_BROKEN_LIB_H +#define SOME_BROKEN_LIB_H + +void do_something_with_pointers(int *ptr1, int *ptr2); + +#endif // SOME_BROKEN_LIB_H diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Headers/FrameworkWithActualPrivateModule.h b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Headers/FrameworkWithActualPrivateModule.h new file mode 100644 index 0000000000000000000000000000000000000000..523de4f7ce0857b950f8d9a810db3db5e3c27545 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Headers/FrameworkWithActualPrivateModule.h @@ -0,0 +1 @@ +extern int FrameworkWithActualPrivateModule; diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..859d723716be217eb69f4474d1a1e82ab5d3c536 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module FrameworkWithActualPrivateModule { + umbrella header "FrameworkWithActualPrivateModule.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.private.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.private.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..e7fafe3bcbb17faf02b5f929eb22512ee698f02a --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.private.modulemap @@ -0,0 +1,5 @@ +framework module FrameworkWithActualPrivateModule_Private { + umbrella header "FrameworkWithActualPrivateModule_Private.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..831cf1e93d35191f02b5af8d98b07a27ee257b44 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.apinotes @@ -0,0 +1 @@ +Name: FrameworkWithActualPrivateModule_Private diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.h b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.h new file mode 100644 index 0000000000000000000000000000000000000000..c07a3e95d740491d7c83b6317e5de75dd92c3943 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.h @@ -0,0 +1,2 @@ +#include +extern int FrameworkWithActualPrivateModule_Private; diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Headers/FrameworkWithWrongCase.h b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Headers/FrameworkWithWrongCase.h new file mode 100644 index 0000000000000000000000000000000000000000..4f3b631c27e30d0f7726d652138d50e3e24970c0 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Headers/FrameworkWithWrongCase.h @@ -0,0 +1 @@ +extern int FrameworkWithWrongCase; diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..e97d361039a150ff26e3b6ac39cd7e4887a7df08 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module FrameworkWithWrongCase { + umbrella header "FrameworkWithWrongCase.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/PrivateHeaders/FrameworkWithWrongCase_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/PrivateHeaders/FrameworkWithWrongCase_Private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..ae5447c61e33d08b400e2ece9608f34116ed94a3 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/PrivateHeaders/FrameworkWithWrongCase_Private.apinotes @@ -0,0 +1 @@ +Name: FrameworkWithWrongCase diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Headers/FrameworkWithWrongCasePrivate.h b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Headers/FrameworkWithWrongCasePrivate.h new file mode 100644 index 0000000000000000000000000000000000000000..d3d61483191c6e017532bdaaa8f8b338bd79c325 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Headers/FrameworkWithWrongCasePrivate.h @@ -0,0 +1 @@ +extern int FrameworkWithWrongCasePrivate; diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..04b96adbbfeb99e45d4a6c33c7f23acced1fffb8 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module FrameworkWithWrongCasePrivate { + umbrella header "FrameworkWithWrongCasePrivate.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.private.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.private.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..d6ad53cdc717970a0e9fc3bc0a60f73fa50c578d --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.private.modulemap @@ -0,0 +1 @@ +module FrameworkWithWrongCasePrivate.Inner {} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/PrivateHeaders/FrameworkWithWrongCasePrivate_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/PrivateHeaders/FrameworkWithWrongCasePrivate_Private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..d7af293e8125f1023d2bc490837f2496637ca8e8 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/PrivateHeaders/FrameworkWithWrongCasePrivate_Private.apinotes @@ -0,0 +1 @@ +Name: FrameworkWithWrongCasePrivate diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Headers/LayeredKit.h b/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Headers/LayeredKit.h new file mode 100644 index 0000000000000000000000000000000000000000..a95d19ecbe9afc32a1e9c33e21394f737d804ef7 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Headers/LayeredKit.h @@ -0,0 +1,11 @@ +@import LayeredKitImpl; + +// @interface declarations already don't inherit attributes from forward +// declarations, so in order to test this properly we have to /not/ define +// UpwardClass anywhere. + +// @interface UpwardClass +// @end + +@protocol UpwardProto +@end diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..04bbe72a2b6e25cba06ac3ccb1d5957f46ce32ef --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module LayeredKit { + umbrella header "LayeredKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.apinotes b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..bece28cfe60577b114e748af5cf8b255a64a23e5 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.apinotes @@ -0,0 +1,9 @@ +Name: LayeredKitImpl +Classes: +- Name: PerfectlyNormalClass + Availability: none +- Name: UpwardClass + Availability: none +Protocols: +- Name: UpwardProto + Availability: none diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.h b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..99591d35803aa1be2eb15e9966a2459a536eb712 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.h @@ -0,0 +1,7 @@ +@protocol UpwardProto; +@class UpwardClass; + +@interface PerfectlyNormalClass +@end + +void doImplementationThings(UpwardClass *first, id second) __attribute((unavailable)); diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..58a6e55c1067f99f460f3a17659a880aec6750d8 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module LayeredKitImpl { + umbrella header "LayeredKitImpl.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..2d07e76c0a142af0ee3fa016732a85f06d591531 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module SimpleKit { + umbrella header "SimpleKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..817af123fc77b6b42c7ef20047dbd327ac0abb47 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit.apinotes @@ -0,0 +1,74 @@ +Name: SomeKit +Classes: + - Name: A + Methods: + - Selector: "transform:" + MethodKind: Instance + Availability: none + AvailabilityMsg: "anything but this" + - Selector: "transform:integer:" + MethodKind: Instance + NullabilityOfRet: N + Nullability: [ N, S ] + Properties: + - Name: intValue + PropertyKind: Instance + Availability: none + AvailabilityMsg: "wouldn't work anyway" + - Name: nonnullAInstance + PropertyKind: Instance + Nullability: N + - Name: nonnullAClass + PropertyKind: Class + Nullability: N + - Name: nonnullABoth + Nullability: N + - Name: B + Availability: none + AvailabilityMsg: "just don't" + - Name: C + Methods: + - Selector: "initWithA:" + MethodKind: Instance + DesignatedInit: true + - Name: OverriddenTypes + Methods: + - Selector: "methodToMangle:second:" + MethodKind: Instance + ResultType: 'char *' + Parameters: + - Position: 0 + Type: 'SOMEKIT_DOUBLE *' + - Position: 1 + Type: 'float *' + Properties: + - Name: intPropertyToMangle + PropertyKind: Instance + Type: 'double *' +Functions: + - Name: global_int_fun + ResultType: 'char *' + Parameters: + - Position: 0 + Type: 'double *' + - Position: 1 + Type: 'float *' +Globals: + - Name: global_int_ptr + Type: 'double *' +SwiftVersions: + - Version: 3.0 + Classes: + - Name: A + Methods: + - Selector: "transform:integer:" + MethodKind: Instance + NullabilityOfRet: O + Nullability: [ O, S ] + Properties: + - Name: explicitNonnullInstance + PropertyKind: Instance + Nullability: O + - Name: explicitNullableInstance + PropertyKind: Instance + Nullability: N diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit_private.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit_private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..28ede9dfa25c08d9fb5067fa9f76ba0309e478ad --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit_private.apinotes @@ -0,0 +1,15 @@ +Name: SomeKit +Classes: + - Name: A + Methods: + - Selector: "privateTransform:input:" + MethodKind: Instance + NullabilityOfRet: N + Nullability: [ N, S ] + Properties: + - Name: internalProperty + Nullability: N +Protocols: + - Name: InternalProtocol + Availability: none + AvailabilityMsg: "not for you" diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKitForNullAnnotation.h b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKitForNullAnnotation.h new file mode 100644 index 0000000000000000000000000000000000000000..bc0c5da8848e9a8aed9cf39a6d6194e1ea856d38 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKitForNullAnnotation.h @@ -0,0 +1,55 @@ +#ifndef SOMEKIT_H +#define SOMEKIT_H + +#define ROOT_CLASS __attribute__((objc_root_class)) + +ROOT_CLASS +@interface A +-(A*)transform:(A*)input; +-(A*)transform:(A*)input integer:(int)integer; + +@property (nonatomic, readonly, retain) A* someA; +@property (nonatomic, retain) A* someOtherA; + +@property (nonatomic) int intValue; +@end + +@interface B : A +@end + +@interface C : A +- (instancetype)init; +- (instancetype)initWithA:(A*)a; +@end + + +@interface MyClass : A +- Inst; ++ Clas; +@end + +struct CGRect { + float origin; + float size; +}; +typedef struct CGRect NSRect; + +@interface I +- (void) Meth : (NSRect[4])exposedRects; +- (void) Meth1 : (const I*)exposedRects; +- (void) Meth2 : (const I*)exposedRects; +- (void) Meth3 : (I*)exposedRects; +- (const I*) Meth4; +- (const I*) Meth5 : (int) Arg1 : (const I*)Arg2 : (double)Arg3 : (const I*) Arg4 :(const volatile id) Arg5; +- (volatile const I*) Meth6 : (const char *)Arg1 : (const char *)Arg2 : (double)Arg3 : (const I*) Arg4 :(const volatile id) Arg5; +@end + +@class NSURL, NSArray, NSError; +@interface INTF_BLOCKS + + (void)getNonLocalVersionsOfItemAtURL:(NSURL *)url completionHandler:(void (^)(NSArray *nonLocalFileVersions, NSError *error))completionHandler; + + (void *)getNonLocalVersionsOfItemAtURL2:(NSURL *)url completionHandler:(void (^)(NSArray *nonLocalFileVersions, NSError *error))completionHandler; + + (NSError **)getNonLocalVersionsOfItemAtURL3:(int)url completionHandler:(void (^)(NSArray *nonLocalFileVersions, NSError *error))completionHandler; + + (id)getNonLocalVersionsOfItemAtURL4:(NSURL *)url completionHandler:(void (^)(int nonLocalFileVersions, NSError *error, NSURL*))completionHandler; +@end + +#endif diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..3abee2df0be1b754b8c65ed9325cea261f08d246 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module SomeKit { + umbrella header "SomeKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.private.modulemap b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.private.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..bbda9d08e3993ee224df34e60339802e2a9e140f --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.private.modulemap @@ -0,0 +1,8 @@ +module SomeKit.Private { + header "SomeKit_Private.h" + export * + + explicit module NullAnnotation { + header "SomeKit_PrivateForNullAnnotation.h" + } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module_private.modulemap b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module_private.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..e31034317cb82ac91c81b596256a83bec859d005 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module_private.modulemap @@ -0,0 +1,8 @@ +explicit framework module SomeKit.Private { + header "SomeKit_Private.h" + explicit NullAnnotation { header "SomeKit_PrivateForNullAnnotation.h" } + export * + module * { export * } +syntax error + +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_Private.h b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_Private.h new file mode 100644 index 0000000000000000000000000000000000000000..c7611123e4ad2f3240ee6f1d3361dacf28967a22 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_Private.h @@ -0,0 +1,16 @@ +#ifndef SOMEKIT_PRIVATE_H +#define SOMEKIT_PRIVATE_H + +#import + +@interface A(Private) +-(A*)privateTransform:(A*)input; + +@property (nonatomic) A* internalProperty; +@end + +@protocol InternalProtocol +@end + +#endif + diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_PrivateForNullAnnotation.h b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_PrivateForNullAnnotation.h new file mode 100644 index 0000000000000000000000000000000000000000..bae4456b4080931af638d0d0585bb58b20a1f232 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_PrivateForNullAnnotation.h @@ -0,0 +1,17 @@ +#ifndef SOMEKIT_PRIVATE_H +#define SOMEKIT_PRIVATE_H + +#import + +@interface A(Private) +-(A*)privateTransform:(A*)input; + +@property (nonatomic) A* internalProperty; +@end + +@protocol InternalProtocol +- (id) MomeMethod; +@end + +#endif + diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_private.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..28ede9dfa25c08d9fb5067fa9f76ba0309e478ad --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_private.apinotes @@ -0,0 +1,15 @@ +Name: SomeKit +Classes: + - Name: A + Methods: + - Selector: "privateTransform:input:" + MethodKind: Instance + NullabilityOfRet: N + Nullability: [ N, S ] + Properties: + - Name: internalProperty + Nullability: N +Protocols: + - Name: InternalProtocol + Availability: none + AvailabilityMsg: "not for you" diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/APINotes/SomeOtherKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/APINotes/SomeOtherKit.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..2ad546b8f8bccaba7ae7db6b335237780035dd59 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/APINotes/SomeOtherKit.apinotes @@ -0,0 +1,8 @@ +Name: SomeOtherKit +Classes: + - Name: A + Methods: + - Selector: "methodA" + MethodKind: Instance + Availability: none + AvailabilityMsg: "anything but this" diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..2ad546b8f8bccaba7ae7db6b335237780035dd59 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.apinotes @@ -0,0 +1,8 @@ +Name: SomeOtherKit +Classes: + - Name: A + Methods: + - Selector: "methodA" + MethodKind: Instance + Availability: none + AvailabilityMsg: "anything but this" diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.h b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.h new file mode 100644 index 0000000000000000000000000000000000000000..3911d765230c6991b433548644e2e3abab16b950 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.h @@ -0,0 +1,9 @@ +#ifndef SOME_OTHER_KIT_H + +__attribute__((objc_root_class)) +@interface A +-(void)methodA; +-(void)methodB; +@end + +#endif diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..0aaad92e041ce34c31eb4768c2577aa25ca86721 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module SomeOtherKit { + umbrella header "SomeOtherKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit.h b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit.h new file mode 100644 index 0000000000000000000000000000000000000000..d3376f1dac5d11a7e63878c0395bfc402c2279f7 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit.h @@ -0,0 +1 @@ +extern int TopLevelPrivateKit_Public; diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit_Private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..ece1dd220adf52f2073481d35a9d4f469439169e --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit_Private.apinotes @@ -0,0 +1 @@ +garbage here because this file shouldn't get read \ No newline at end of file diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..70faa54e8347784186ec2131e4c9414cd3ec7db8 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module TopLevelPrivateKit { + umbrella header "TopLevelPrivateKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.private.modulemap b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.private.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..0958a14d67108920f8ccee1ae3faf2d2ef59e38d --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.private.modulemap @@ -0,0 +1,5 @@ +framework module TopLevelPrivateKit_Private { + umbrella header "TopLevelPrivateKit_Private.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..908dae0e3b0b24cc8c04430a659e1aa0ace59b6c --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit.apinotes @@ -0,0 +1 @@ +garbage here because this file shouldn't get read diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..43323621588bb2afff5ff6e425a63f834fe9b1c7 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.apinotes @@ -0,0 +1,4 @@ +Name: TopLevelPrivateKit_Private +Globals: +- Name: TopLevelPrivateKit_Private + Type: float diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.h b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.h new file mode 100644 index 0000000000000000000000000000000000000000..39cbfe6e9918ba7a39d43de5c2cd10cb7331350b --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.h @@ -0,0 +1 @@ +extern int TopLevelPrivateKit_Private; diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private_private.apinotes b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private_private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..ece1dd220adf52f2073481d35a9d4f469439169e --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private_private.apinotes @@ -0,0 +1 @@ +garbage here because this file shouldn't get read \ No newline at end of file diff --git a/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..572c714b3d61a71703c5162624efdc27cb87d0fa --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes @@ -0,0 +1,156 @@ +Name: VersionedKit +Classes: + - Name: TestProperties + SwiftObjCMembers: true + Properties: + - Name: accessorsOnly + PropertyKind: Instance + SwiftImportAsAccessors: true + - Name: accessorsOnlyForClass + PropertyKind: Class + SwiftImportAsAccessors: true + - Name: accessorsOnlyExceptInVersion3 + PropertyKind: Instance + SwiftImportAsAccessors: true + - Name: accessorsOnlyForClassExceptInVersion3 + PropertyKind: Class + SwiftImportAsAccessors: true +Functions: + - Name: unversionedRenameDUMP + SwiftName: 'unversionedRename_NOTES()' +Tags: + - Name: APINotedFlagEnum + FlagEnum: true + - Name: APINotedOpenEnum + EnumExtensibility: open + - Name: APINotedClosedEnum + EnumExtensibility: closed + - Name: SoonToBeCFEnum + EnumKind: CFEnum + - Name: SoonToBeNSEnum + EnumKind: NSEnum + - Name: SoonToBeCFOptions + EnumKind: CFOptions + - Name: SoonToBeNSOptions + EnumKind: NSOptions + - Name: SoonToBeCFClosedEnum + EnumKind: CFClosedEnum + - Name: SoonToBeNSClosedEnum + EnumKind: NSClosedEnum + - Name: UndoAllThatHasBeenDoneToMe + EnumKind: none +Typedefs: + - Name: MultiVersionedTypedef34Notes + SwiftName: MultiVersionedTypedef34Notes_NEW + - Name: MultiVersionedTypedef345Notes + SwiftName: MultiVersionedTypedef345Notes_NEW + - Name: MultiVersionedTypedef4Notes + SwiftName: MultiVersionedTypedef4Notes_NEW + - Name: MultiVersionedTypedef45Notes + SwiftName: MultiVersionedTypedef45Notes_NEW +SwiftVersions: + - Version: 3.0 + Classes: + - Name: MyReferenceType + SwiftBridge: '' + - Name: TestGenericDUMP + SwiftImportAsNonGeneric: true + - Name: TestProperties + SwiftObjCMembers: false + Properties: + - Name: accessorsOnlyInVersion3 + PropertyKind: Instance + SwiftImportAsAccessors: true + - Name: accessorsOnlyForClassInVersion3 + PropertyKind: Class + SwiftImportAsAccessors: true + - Name: accessorsOnlyExceptInVersion3 + PropertyKind: Instance + SwiftImportAsAccessors: false + - Name: accessorsOnlyForClassExceptInVersion3 + PropertyKind: Class + SwiftImportAsAccessors: false + - Name: Swift3RenamedOnlyDUMP + SwiftName: SpecialSwift3Name + - Name: Swift3RenamedAlsoDUMP + SwiftName: SpecialSwift3Also + Functions: + - Name: moveToPointDUMP + SwiftName: 'moveTo(a:b:)' + - Name: acceptClosure + Parameters: + - Position: 0 + NoEscape: false + - Name: privateFunc + SwiftPrivate: false + Tags: + - Name: MyErrorCode + NSErrorDomain: '' + - Name: NewlyFlagEnum + FlagEnum: false + - Name: OpenToClosedEnum + EnumExtensibility: open + - Name: ClosedToOpenEnum + EnumExtensibility: closed + - Name: NewlyClosedEnum + EnumExtensibility: none + - Name: NewlyOpenEnum + EnumExtensibility: none + Typedefs: + - Name: MyDoubleWrapper + SwiftWrapper: none + - Name: MultiVersionedTypedef34 + SwiftName: MultiVersionedTypedef34_3 + - Name: MultiVersionedTypedef34Header + SwiftName: MultiVersionedTypedef34Header_3 + - Name: MultiVersionedTypedef34Notes + SwiftName: MultiVersionedTypedef34Notes_3 + - Name: MultiVersionedTypedef345 + SwiftName: MultiVersionedTypedef345_3 + - Name: MultiVersionedTypedef345Header + SwiftName: MultiVersionedTypedef345Header_3 + - Name: MultiVersionedTypedef345Notes + SwiftName: MultiVersionedTypedef345Notes_3 + - Version: 5 + Typedefs: + - Name: MultiVersionedTypedef345 + SwiftName: MultiVersionedTypedef345_5 + - Name: MultiVersionedTypedef345Header + SwiftName: MultiVersionedTypedef345Header_5 + - Name: MultiVersionedTypedef345Notes + SwiftName: MultiVersionedTypedef345Notes_5 + - Name: MultiVersionedTypedef45 + SwiftName: MultiVersionedTypedef45_5 + - Name: MultiVersionedTypedef45Header + SwiftName: MultiVersionedTypedef45Header_5 + - Name: MultiVersionedTypedef45Notes + SwiftName: MultiVersionedTypedef45Notes_5 + - Version: 4 # Versions are deliberately ordered as "3, 5, 4" to catch bugs. + Classes: + - Name: Swift4RenamedDUMP + SwiftName: SpecialSwift4Name + Typedefs: + - Name: MultiVersionedTypedef34 + SwiftName: MultiVersionedTypedef34_4 + - Name: MultiVersionedTypedef34Header + SwiftName: MultiVersionedTypedef34Header_4 + - Name: MultiVersionedTypedef34Notes + SwiftName: MultiVersionedTypedef34Notes_4 + - Name: MultiVersionedTypedef345 + SwiftName: MultiVersionedTypedef345_4 + - Name: MultiVersionedTypedef345Header + SwiftName: MultiVersionedTypedef345Header_4 + - Name: MultiVersionedTypedef345Notes + SwiftName: MultiVersionedTypedef345Notes_4 + - Name: MultiVersionedTypedef4 + SwiftName: MultiVersionedTypedef4_4 + - Name: MultiVersionedTypedef4Header + SwiftName: MultiVersionedTypedef4Header_4 + - Name: MultiVersionedTypedef4Notes + SwiftName: MultiVersionedTypedef4Notes_4 + - Name: MultiVersionedTypedef45 + SwiftName: MultiVersionedTypedef45_4 + - Name: MultiVersionedTypedef45Header + SwiftName: MultiVersionedTypedef45Header_4 + - Name: MultiVersionedTypedef45Notes + SwiftName: MultiVersionedTypedef45Notes_4 diff --git a/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h new file mode 100644 index 0000000000000000000000000000000000000000..9ce95633c523b7bc8a203c9f49b1ed240ca41718 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h @@ -0,0 +1,137 @@ +void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(x:y:)"))); + +void unversionedRenameDUMP(void) __attribute__((swift_name("unversionedRename_HEADER()"))); + +void acceptClosure(void (^ __attribute__((noescape)) block)(void)); + +void privateFunc(void) __attribute__((swift_private)); + +typedef double MyDoubleWrapper __attribute__((swift_wrapper(struct))); + +#if __OBJC__ +@class NSString; + +extern NSString *MyErrorDomain; + +enum __attribute__((ns_error_domain(MyErrorDomain))) MyErrorCode { + MyErrorCodeFailed = 1 +}; + +__attribute__((swift_bridge("MyValueType"))) +@interface MyReferenceType +@end + +@interface TestProperties +@property (nonatomic, readwrite, retain) id accessorsOnly; +@property (nonatomic, readwrite, retain, class) id accessorsOnlyForClass; + +@property (nonatomic, readwrite, retain) id accessorsOnlyInVersion3; +@property (nonatomic, readwrite, retain, class) id accessorsOnlyForClassInVersion3; + +@property (nonatomic, readwrite, retain) id accessorsOnlyExceptInVersion3; +@property (nonatomic, readwrite, retain, class) id accessorsOnlyForClassExceptInVersion3; +@end + +@interface Base +@end + +@interface TestGenericDUMP : Base +- (Element)element; +@end + +@interface Swift3RenamedOnlyDUMP +@end + +__attribute__((swift_name("Swift4Name"))) +@interface Swift3RenamedAlsoDUMP +@end + +@interface Swift4RenamedDUMP +@end + +#endif + + +enum __attribute__((flag_enum)) FlagEnum { + FlagEnumA = 1, + FlagEnumB = 2 +}; + +enum __attribute__((flag_enum)) NewlyFlagEnum { + NewlyFlagEnumA = 1, + NewlyFlagEnumB = 2 +}; + +enum APINotedFlagEnum { + APINotedFlagEnumA = 1, + APINotedFlagEnumB = 2 +}; + + +enum __attribute__((enum_extensibility(open))) OpenEnum { + OpenEnumA = 1, +}; + +enum __attribute__((enum_extensibility(open))) NewlyOpenEnum { + NewlyOpenEnumA = 1, +}; + +enum __attribute__((enum_extensibility(closed))) NewlyClosedEnum { + NewlyClosedEnumA = 1, +}; + +enum __attribute__((enum_extensibility(open))) ClosedToOpenEnum { + ClosedToOpenEnumA = 1, +}; + +enum __attribute__((enum_extensibility(closed))) OpenToClosedEnum { + OpenToClosedEnumA = 1, +}; + +enum APINotedOpenEnum { + APINotedOpenEnumA = 1, +}; + +enum APINotedClosedEnum { + APINotedClosedEnumA = 1, +}; + + +enum SoonToBeCFEnum { + SoonToBeCFEnumA = 1 +}; +enum SoonToBeNSEnum { + SoonToBeNSEnumA = 1 +}; +enum SoonToBeCFOptions { + SoonToBeCFOptionsA = 1 +}; +enum SoonToBeNSOptions { + SoonToBeNSOptionsA = 1 +}; +enum SoonToBeCFClosedEnum { + SoonToBeCFClosedEnumA = 1 +}; +enum SoonToBeNSClosedEnum { + SoonToBeNSClosedEnumA = 1 +}; +enum UndoAllThatHasBeenDoneToMe { + UndoAllThatHasBeenDoneToMeA = 1 +} __attribute__((flag_enum)) __attribute__((enum_extensibility(closed))); + + +typedef int MultiVersionedTypedef4; +typedef int MultiVersionedTypedef4Notes; +typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_NEW"))); + +typedef int MultiVersionedTypedef34; +typedef int MultiVersionedTypedef34Notes; +typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_NEW"))); + +typedef int MultiVersionedTypedef45; +typedef int MultiVersionedTypedef45Notes; +typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_NEW"))); + +typedef int MultiVersionedTypedef345; +typedef int MultiVersionedTypedef345Notes; +typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_NEW"))); diff --git a/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..6d957fd68009f0c5a56d0dbf6088365bb12726d2 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module VersionedKit { + umbrella header "VersionedKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Headers/APINotes.apinotes b/clang/test/APINotes/Inputs/Headers/APINotes.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..08210fc7056513b97b5c04622f318114ecf15847 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/APINotes.apinotes @@ -0,0 +1,18 @@ +Name: HeaderLib +SwiftInferImportAsMember: true +Functions: + - Name: custom_realloc + NullabilityOfRet: N + Nullability: [ N, S ] + - Name: unavailable_function + Availability: none + AvailabilityMsg: "I beg you not to use this" + - Name: do_something_with_pointers + NullabilityOfRet: O + Nullability: [ N, O ] + +Globals: + - Name: global_int + Nullability: N + - Name: unavailable_global_int + Availability: none diff --git a/clang/test/APINotes/Inputs/Headers/BrokenTypes.apinotes b/clang/test/APINotes/Inputs/Headers/BrokenTypes.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..00f7b5074e9850c3e516850646449aa7bc460e14 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/BrokenTypes.apinotes @@ -0,0 +1,10 @@ +Name: BrokenTypes +Functions: + - Name: break_me_function + ResultType: 'int * with extra junk' + Parameters: + - Position: 0 + Type: 'not_a_type' +Globals: + - Name: break_me_variable + Type: 'double' diff --git a/clang/test/APINotes/Inputs/Headers/BrokenTypes.h b/clang/test/APINotes/Inputs/Headers/BrokenTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..fee054b74cf701b1a9c374faa259e38fe6f05fc1 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/BrokenTypes.h @@ -0,0 +1,8 @@ +#ifndef BROKEN_TYPES_H +#define BROKEN_TYPES_H + +char break_me_function(void *ptr); + +extern char break_me_variable; + +#endif // BROKEN_TYPES_H diff --git a/clang/test/APINotes/Inputs/Headers/ExternCtx.apinotes b/clang/test/APINotes/Inputs/Headers/ExternCtx.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..0f47ac6deea85d270cc684853382b1f5d00e2e8c --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExternCtx.apinotes @@ -0,0 +1,15 @@ +Name: ExternCtx +Globals: + - Name: globalInExternC + Availability: none + AvailabilityMsg: "oh no" + - Name: globalInExternCXX + Availability: none + AvailabilityMsg: "oh no #2" +Functions: + - Name: globalFuncInExternC + Availability: none + AvailabilityMsg: "oh no #3" + - Name: globalFuncInExternCXX + Availability: none + AvailabilityMsg: "oh no #4" diff --git a/clang/test/APINotes/Inputs/Headers/ExternCtx.h b/clang/test/APINotes/Inputs/Headers/ExternCtx.h new file mode 100644 index 0000000000000000000000000000000000000000..669d443f60ecf13d2ff63ad9b37ebb863ee88925 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExternCtx.h @@ -0,0 +1,11 @@ +extern "C" { + static int globalInExternC = 1; + + static void globalFuncInExternC() {} +} + +extern "C++" { + static int globalInExternCXX = 2; + + static void globalFuncInExternCXX() {} +} diff --git a/clang/test/APINotes/Inputs/Headers/HeaderLib.apinotes b/clang/test/APINotes/Inputs/Headers/HeaderLib.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..7dcb22476a1d26af1e127e6b6963ae79c149fa9a --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/HeaderLib.apinotes @@ -0,0 +1,37 @@ +Name: HeaderLib +SwiftInferImportAsMember: true +Functions: + - Name: custom_realloc + NullabilityOfRet: N + Nullability: [ N, S ] + - Name: unavailable_function + Availability: none + AvailabilityMsg: "I beg you not to use this" + - Name: do_something_with_pointers + NullabilityOfRet: O + Nullability: [ N, O ] + - Name: do_something_with_arrays + Parameters: + - Position: 0 + Nullability: N + - Position: 1 + Nullability: N + - Name: take_pointer_and_int + Parameters: + - Position: 0 + Nullability: N + NoEscape: true + - Position: 1 + NoEscape: true +Globals: + - Name: global_int + Nullability: N + - Name: unavailable_global_int + Availability: none +Tags: + - Name: unavailable_struct + Availability: none + +Typedefs: + - Name: unavailable_typedef + Availability: none diff --git a/clang/test/APINotes/Inputs/Headers/HeaderLib.h b/clang/test/APINotes/Inputs/Headers/HeaderLib.h new file mode 100644 index 0000000000000000000000000000000000000000..8065249607851bd20152f47adfcfba99e698796d --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/HeaderLib.h @@ -0,0 +1,19 @@ +#ifndef HEADER_LIB_H +#define HEADER_LIB_H + +void *custom_realloc(void *member, unsigned size); + +int *global_int; + +int unavailable_function(void); +int unavailable_global_int; + +void do_something_with_pointers(int *ptr1, int *ptr2); +void do_something_with_arrays(int simple[], int nested[][2]); + +typedef int unavailable_typedef; +struct unavailable_struct { int x, y, z; }; + +void take_pointer_and_int(int *ptr1, int value); + +#endif diff --git a/clang/test/APINotes/Inputs/Headers/InstancetypeModule.apinotes b/clang/test/APINotes/Inputs/Headers/InstancetypeModule.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..813eb506f39a748eabaadff147379474fdc24617 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/InstancetypeModule.apinotes @@ -0,0 +1,10 @@ +Name: InstancetypeModule +Classes: +- Name: SomeBaseClass + Methods: + - Selector: instancetypeFactoryMethod + MethodKind: Class + ResultType: SomeBaseClass * _Nonnull + - Selector: staticFactoryMethod + MethodKind: Class + ResultType: SomeBaseClass * _Nonnull diff --git a/clang/test/APINotes/Inputs/Headers/InstancetypeModule.h b/clang/test/APINotes/Inputs/Headers/InstancetypeModule.h new file mode 100644 index 0000000000000000000000000000000000000000..767f201d9faf63c60413af95ee6f779f8cd9210c --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/InstancetypeModule.h @@ -0,0 +1,10 @@ +@interface Object +@end + +@interface SomeBaseClass : Object ++ (nullable instancetype)instancetypeFactoryMethod; ++ (nullable SomeBaseClass *)staticFactoryMethod; +@end + +@interface SomeSubclass : SomeBaseClass +@end diff --git a/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase.h b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase.h new file mode 100644 index 0000000000000000000000000000000000000000..867a15cae9a66413323319f78268bec39aa5bb68 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase.h @@ -0,0 +1 @@ +extern int ModuleWithWrongCase; diff --git a/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate.h b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate.h new file mode 100644 index 0000000000000000000000000000000000000000..aa014296ca7d232d29b3b979b6b30a459dd82147 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate.h @@ -0,0 +1 @@ +extern int ModuleWithWrongCasePrivate; diff --git a/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate_Private.apinotes b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate_Private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..dc6dc50bab6e6987a972bd06bcfdf5524b3c520e --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate_Private.apinotes @@ -0,0 +1 @@ +Name: ModuleWithWrongCasePrivate diff --git a/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase_Private.apinotes b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase_Private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..dc6dc50bab6e6987a972bd06bcfdf5524b3c520e --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase_Private.apinotes @@ -0,0 +1 @@ +Name: ModuleWithWrongCasePrivate diff --git a/clang/test/APINotes/Inputs/Headers/Namespaces.apinotes b/clang/test/APINotes/Inputs/Headers/Namespaces.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..e9da36787b638d1f08dbab87861d263ad743463c --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/Namespaces.apinotes @@ -0,0 +1,53 @@ +--- +Name: Namespaces +Globals: + - Name: varInInlineNamespace + SwiftName: swiftVarInInlineNamespace +Functions: + - Name: funcInNamespace + SwiftName: inWrongContext() + - Name: funcInInlineNamespace + SwiftName: swiftFuncInInlineNamespace() +Tags: + - Name: char_box + SwiftName: InWrongContext +Namespaces: + - Name: Namespace1 + Typedefs: + - Name: my_typedef + SwiftName: SwiftTypedef + - Name: my_using_decl + SwiftName: SwiftUsingDecl + Globals: + - Name: varInNamespace + SwiftName: swiftVarInNamespace + Functions: + - Name: funcInNamespace + SwiftName: swiftFuncInNamespace() + Tags: + - Name: char_box + SwiftName: CharBox + Namespaces: + - Name: Nested1 + Globals: + - Name: varInNestedNamespace + SwiftName: swiftVarInNestedNamespace + Functions: + - Name: funcInNestedNamespace + SwiftName: swiftFuncInNestedNamespace(_:) + Tags: + - Name: char_box + SwiftName: NestedCharBox + Namespaces: + - Name: Namespace1 + Tags: + - Name: char_box + SwiftName: DeepNestedCharBox + - Name: Nested2 + Globals: + - Name: varInNestedNamespace + SwiftName: swiftAnotherVarInNestedNamespace + - Name: InlineNamespace1 + Functions: + - Name: funcInInlineNamespace + SwiftName: shouldNotSpellOutInlineNamespaces() diff --git a/clang/test/APINotes/Inputs/Headers/Namespaces.h b/clang/test/APINotes/Inputs/Headers/Namespaces.h new file mode 100644 index 0000000000000000000000000000000000000000..6a79e996be86cd2ad07ef68b69274e8858095a77 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/Namespaces.h @@ -0,0 +1,39 @@ +namespace Namespace1 { namespace Nested1 {} } + +namespace Namespace1 { +static int varInNamespace = 1; +struct char_box { char c; }; +void funcInNamespace(); + +namespace Nested1 { +void funcInNestedNamespace(int i); +struct char_box { + char c; +}; +} + +namespace Nested1 { +static int varInNestedNamespace = 1; +void funcInNestedNamespace(int i); + +namespace Namespace1 { +struct char_box { char c; }; +} // namespace Namespace1 +} // namespace Nested1 + +namespace Nested2 { +static int varInNestedNamespace = 2; +} // namespace Nested2 + +namespace Nested1 { namespace Namespace1 {} } +} // namespace Namespace1 + +namespace Namespace1 { +typedef int my_typedef; +using my_using_decl = int; +} + +inline namespace InlineNamespace1 { +static int varInInlineNamespace = 3; +void funcInInlineNamespace(); +} diff --git a/clang/test/APINotes/Inputs/Headers/PrivateLib.apinotes b/clang/test/APINotes/Inputs/Headers/PrivateLib.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..5f62284aadcaf73e53a4a713e23439751eaf7b8b --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/PrivateLib.apinotes @@ -0,0 +1,4 @@ +Name: HeaderLib +Globals: +- Name: PrivateLib + Type: float diff --git a/clang/test/APINotes/Inputs/Headers/PrivateLib.h b/clang/test/APINotes/Inputs/Headers/PrivateLib.h new file mode 100644 index 0000000000000000000000000000000000000000..59aeef09bdd3b649b0157fee5c4b472e2c20fa84 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/PrivateLib.h @@ -0,0 +1 @@ +extern int PrivateLib; diff --git a/clang/test/APINotes/Inputs/Headers/PrivateLib_private.apinotes b/clang/test/APINotes/Inputs/Headers/PrivateLib_private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..908dae0e3b0b24cc8c04430a659e1aa0ace59b6c --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/PrivateLib_private.apinotes @@ -0,0 +1 @@ +garbage here because this file shouldn't get read diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..5dbb83cab86bd7968b3e9248ef9f8bcdf8762130 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes @@ -0,0 +1,9 @@ +--- +Name: SwiftImportAs +Tags: +- Name: ImmortalRefType + SwiftImportAs: reference +- Name: RefCountedType + SwiftImportAs: reference + SwiftReleaseOp: RCRelease + SwiftRetainOp: RCRetain diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h new file mode 100644 index 0000000000000000000000000000000000000000..82b8a6749c4fe2a8a714db5b2622cc8ab61f2b69 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h @@ -0,0 +1,6 @@ +struct ImmortalRefType {}; + +struct RefCountedType { int value; }; + +inline void RCRetain(RefCountedType *x) { x->value++; } +inline void RCRelease(RefCountedType *x) { x->value--; } diff --git a/clang/test/APINotes/Inputs/Headers/module.modulemap b/clang/test/APINotes/Inputs/Headers/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..98b4ee3e96cfe721f92c91717189e478aa8b74e5 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/module.modulemap @@ -0,0 +1,31 @@ +module ExternCtx { + header "ExternCtx.h" +} + +module HeaderLib { + header "HeaderLib.h" +} + +module InstancetypeModule { + header "InstancetypeModule.h" +} + +module BrokenTypes { + header "BrokenTypes.h" +} + +module ModuleWithWrongCase { + header "ModuleWithWrongCase.h" +} + +module ModuleWithWrongCasePrivate { + header "ModuleWithWrongCasePrivate.h" +} + +module Namespaces { + header "Namespaces.h" +} + +module SwiftImportAs { + header "SwiftImportAs.h" +} diff --git a/clang/test/APINotes/Inputs/Headers/module.private.modulemap b/clang/test/APINotes/Inputs/Headers/module.private.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..2ecf322ed18d9cca21d1036a4b5cdc3950c759fa --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/module.private.modulemap @@ -0,0 +1,5 @@ +module PrivateLib { + header "PrivateLib.h" +} + +module ModuleWithWrongCasePrivate.Inner {} diff --git a/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.apinotes b/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..77db844008990d216c3e022908505365182538aa --- /dev/null +++ b/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.apinotes @@ -0,0 +1,65 @@ +--- +Name: UIKit +Classes: + - Name: UIFont + Methods: + - Selector: 'fontWithName:size:' + MethodKind: Instance + Nullability: [ N ] + NullabilityOfRet: O + DesignatedInit: true +# CHECK: duplicate definition of method '-[UIFont fontWithName:size:]' + - Selector: 'fontWithName:size:' + MethodKind: Instance + Nullability: [ N ] + NullabilityOfRet: O + DesignatedInit: true + Properties: + - Name: familyName + Nullability: N + - Name: fontName + Nullability: N +# CHECK: duplicate definition of instance property 'UIFont.familyName' + - Name: familyName + Nullability: N +# CHECK: multiple definitions of class 'UIFont' + - Name: UIFont +Protocols: + - Name: MyProto + AuditedForNullability: true +# CHECK: multiple definitions of protocol 'MyProto' + - Name: MyProto + AuditedForNullability: true +Functions: + - Name: 'globalFoo' + Nullability: [ N, N, O, S ] + NullabilityOfRet: O + - Name: 'globalFoo2' + Nullability: [ N, N, O, S ] + NullabilityOfRet: O +Globals: + - Name: globalVar + Nullability: O + - Name: globalVar2 + Nullability: O +Tags: +# CHECK: cannot mix EnumKind and FlagEnum (for FlagAndEnumKind) + - Name: FlagAndEnumKind + FlagEnum: true + EnumKind: CFOptions +# CHECK: cannot mix EnumKind and FlagEnum (for FlagAndEnumKind2) + - Name: FlagAndEnumKind2 + EnumKind: CFOptions + FlagEnum: false +# CHECK: cannot mix EnumKind and EnumExtensibility (for ExtensibilityAndEnumKind) + - Name: ExtensibilityAndEnumKind + EnumExtensibility: open + EnumKind: CFOptions +# CHECK: cannot mix EnumKind and EnumExtensibility (for ExtensibilityAndEnumKind2) + - Name: ExtensibilityAndEnumKind2 + EnumKind: CFOptions + EnumExtensibility: closed +# CHECK: cannot mix EnumKind and EnumExtensibility (for ExtensibilityAndEnumKind3) + - Name: ExtensibilityAndEnumKind3 + EnumKind: none + EnumExtensibility: none diff --git a/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.h b/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.h new file mode 100644 index 0000000000000000000000000000000000000000..55313ae260ae11cce3d79d43dbcdb50100548766 --- /dev/null +++ b/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.h @@ -0,0 +1 @@ +extern int yesOfCourseThisIsWhatUIKitLooksLike; diff --git a/clang/test/APINotes/Inputs/yaml-reader-errors/module.modulemap b/clang/test/APINotes/Inputs/yaml-reader-errors/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..3d683d705cacf8fa20f409f0e05fd7d374810a7c --- /dev/null +++ b/clang/test/APINotes/Inputs/yaml-reader-errors/module.modulemap @@ -0,0 +1,3 @@ +module UIKit { + header "UIKit.h" +} diff --git a/clang/test/APINotes/availability.m b/clang/test/APINotes/availability.m new file mode 100644 index 0000000000000000000000000000000000000000..2ddc2a73da80462b9ba0d6f4e712e1402d3ffebb --- /dev/null +++ b/clang/test/APINotes/availability.m @@ -0,0 +1,48 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -Wno-private-module -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +#include "HeaderLib.h" +#import +#import + +int main() { + int i; + i = unavailable_function(); // expected-error{{'unavailable_function' is unavailable: I beg you not to use this}} + // expected-note@HeaderLib.h:8{{'unavailable_function' has been explicitly marked unavailable here}} + i = unavailable_global_int; // expected-error{{'unavailable_global_int' is unavailable}} + // expected-note@HeaderLib.h:9{{'unavailable_global_int' has been explicitly marked unavailable here}} + + unavailable_typedef t; // expected-error{{'unavailable_typedef' is unavailable}} + // expected-note@HeaderLib.h:14{{'unavailable_typedef' has been explicitly marked unavailable here}} + + struct unavailable_struct s; // expected-error{{'unavailable_struct' is unavailable}} + // expected-note@HeaderLib.h:15{{'unavailable_struct' has been explicitly marked unavailable here}} + + B *b = 0; // expected-error{{'B' is unavailable: just don't}} + // expected-note@SomeKit/SomeKit.h:15{{'B' has been explicitly marked unavailable here}} + + id proto = 0; // expected-error{{'InternalProtocol' is unavailable: not for you}} + // expected-note@SomeKit/SomeKit_Private.h:12{{'InternalProtocol' has been explicitly marked unavailable here}} + + A *a = 0; + i = a.intValue; // expected-error{{intValue' is unavailable: wouldn't work anyway}} + // expected-note@SomeKit/SomeKit.h:12{{'intValue' has been explicitly marked unavailable here}} + + [a transform:a]; // expected-error{{'transform:' is unavailable: anything but this}} + // expected-note@SomeKit/SomeKit.h:6{{'transform:' has been explicitly marked unavailable here}} + + [a implicitGetOnlyInstance]; // expected-error{{'implicitGetOnlyInstance' is unavailable: getter gone}} + // expected-note@SomeKit/SomeKit.h:53{{'implicitGetOnlyInstance' has been explicitly marked unavailable here}} + [A implicitGetOnlyClass]; // expected-error{{'implicitGetOnlyClass' is unavailable: getter gone}} + // expected-note@SomeKit/SomeKit.h:54{{'implicitGetOnlyClass' has been explicitly marked unavailable here}} + [a implicitGetSetInstance]; // expected-error{{'implicitGetSetInstance' is unavailable: getter gone}} + // expected-note@SomeKit/SomeKit.h:56{{'implicitGetSetInstance' has been explicitly marked unavailable here}} + [a setImplicitGetSetInstance: a]; // expected-error{{'setImplicitGetSetInstance:' is unavailable: setter gone}} + // expected-note@SomeKit/SomeKit.h:56{{'setImplicitGetSetInstance:' has been explicitly marked unavailable here}} + [A implicitGetSetClass]; // expected-error{{'implicitGetSetClass' is unavailable: getter gone}} + // expected-note@SomeKit/SomeKit.h:57{{'implicitGetSetClass' has been explicitly marked unavailable here}} + [A setImplicitGetSetClass: a]; // expected-error{{'setImplicitGetSetClass:' is unavailable: setter gone}} + // expected-note@SomeKit/SomeKit.h:57{{'setImplicitGetSetClass:' has been explicitly marked unavailable here}} + return 0; +} + diff --git a/clang/test/APINotes/broken_types.m b/clang/test/APINotes/broken_types.m new file mode 100644 index 0000000000000000000000000000000000000000..ee33ff7c4b4b9cbe59b209abcd6f91bf77e71e3d --- /dev/null +++ b/clang/test/APINotes/broken_types.m @@ -0,0 +1,19 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s 2> %t.err +// RUN: FileCheck %s < %t.err + +#include "BrokenTypes.h" + +// CHECK: :1:1: error: unknown type name 'not_a_type' +// CHECK-NEXT: not_a_type +// CHECK-NEXT: ^ + +// CHECK: :1:7: error: unparsed tokens following type +// CHECK-NEXT: int * with extra junk +// CHECK-NEXT: ^ + +// CHECK: BrokenTypes.h:4:6: error: API notes replacement type 'int *' has a different size from original type 'char' + +// CHECK: BrokenTypes.h:6:13: error: API notes replacement type 'double' has a different size from original type 'char' + +// CHECK: 5 errors generated. diff --git a/clang/test/APINotes/case-for-private-apinotes-file.c b/clang/test/APINotes/case-for-private-apinotes-file.c new file mode 100644 index 0000000000000000000000000000000000000000..6aff3db54918e4a8dc68b20671f1172d3b99c335 --- /dev/null +++ b/clang/test/APINotes/case-for-private-apinotes-file.c @@ -0,0 +1,22 @@ +// REQUIRES: case-insensitive-filesystem + +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -fmodules -fapinotes-modules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/Frameworks -I %S/Inputs/Headers %s 2>&1 | FileCheck %s + +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -fmodules -fapinotes-modules -fimplicit-module-maps -fmodules-cache-path=%t -iframework %S/Inputs/Frameworks -isystem %S/Inputs/Headers %s -Werror + +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -fmodules -fapinotes-modules -fimplicit-module-maps -fmodules-cache-path=%t -iframework %S/Inputs/Frameworks -isystem %S/Inputs/Headers %s -Wnonportable-private-system-apinotes-path 2>&1 | FileCheck %s + +#include +#include +#include +#include +#include + +// CHECK-NOT: warning: +// CHECK: warning: private API notes file for module 'ModuleWithWrongCasePrivate' should be named 'ModuleWithWrongCasePrivate_private.apinotes', not 'ModuleWithWrongCasePrivate_Private.apinotes' +// CHECK-NOT: warning: +// CHECK: warning: private API notes file for module 'FrameworkWithWrongCasePrivate' should be named 'FrameworkWithWrongCasePrivate_private.apinotes', not 'FrameworkWithWrongCasePrivate_Private.apinotes' +// CHECK-NOT: warning: diff --git a/clang/test/APINotes/extern-context.cpp b/clang/test/APINotes/extern-context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..331dee002361c0271c12ac6b7d68780a0eae45a9 --- /dev/null +++ b/clang/test/APINotes/extern-context.cpp @@ -0,0 +1,23 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalInExternC -x c++ | FileCheck -check-prefix=CHECK-EXTERN-C %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalInExternCXX -x c++ | FileCheck -check-prefix=CHECK-EXTERN-CXX %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalFuncInExternC -x c++ | FileCheck -check-prefix=CHECK-FUNC-EXTERN-C %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalFuncInExternCXX -x c++ | FileCheck -check-prefix=CHECK-FUNC-EXTERN-CXX %s + +#include "ExternCtx.h" + +// CHECK-EXTERN-C: Dumping globalInExternC: +// CHECK-EXTERN-C: VarDecl {{.+}} imported in ExternCtx globalInExternC 'int' +// CHECK-EXTERN-C: UnavailableAttr {{.+}} <> "oh no" + +// CHECK-EXTERN-CXX: Dumping globalInExternCXX: +// CHECK-EXTERN-CXX: VarDecl {{.+}} imported in ExternCtx globalInExternCXX 'int' +// CHECK-EXTERN-CXX: UnavailableAttr {{.+}} <> "oh no #2" + +// CHECK-FUNC-EXTERN-C: Dumping globalFuncInExternC: +// CHECK-FUNC-EXTERN-C: FunctionDecl {{.+}} imported in ExternCtx globalFuncInExternC 'void ()' +// CHECK-FUNC-EXTERN-C: UnavailableAttr {{.+}} <> "oh no #3" + +// CHECK-FUNC-EXTERN-CXX: Dumping globalFuncInExternCXX: +// CHECK-FUNC-EXTERN-CXX: FunctionDecl {{.+}} imported in ExternCtx globalFuncInExternCXX 'void ()' +// CHECK-FUNC-EXTERN-CXX: UnavailableAttr {{.+}} <> "oh no #4" diff --git a/clang/test/APINotes/instancetype.m b/clang/test/APINotes/instancetype.m new file mode 100644 index 0000000000000000000000000000000000000000..30339e5386f634ad05262d097fcb547a3306e462 --- /dev/null +++ b/clang/test/APINotes/instancetype.m @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -verify %s + +@import InstancetypeModule; + +void test() { + // The nullability is here to verify that the API notes were applied. + int good = [SomeSubclass instancetypeFactoryMethod]; // expected-error {{initializing 'int' with an expression of type 'SomeSubclass * _Nonnull'}} + int bad = [SomeSubclass staticFactoryMethod]; // expected-error {{initializing 'int' with an expression of type 'SomeBaseClass * _Nonnull'}} +} diff --git a/clang/test/APINotes/module-cache.m b/clang/test/APINotes/module-cache.m new file mode 100644 index 0000000000000000000000000000000000000000..5dcaf1181f9dcfc85ddeb1706e3d1600f84667bf --- /dev/null +++ b/clang/test/APINotes/module-cache.m @@ -0,0 +1,65 @@ +// RUN: rm -rf %t + +// Set up directories +// RUN: mkdir -p %t/APINotes +// RUN: cp %S/Inputs/APINotes/SomeOtherKit.apinotes %t/APINotes/SomeOtherKit.apinotes +// RUN: mkdir -p %t/Frameworks +// RUN: cp -r %S/Inputs/Frameworks/SomeOtherKit.framework %t/Frameworks + +// First build: check that 'methodB' is unavailable but 'methodA' is available. +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/before.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-REBUILD %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-ONE-ERROR %s < %t/before.log + +// Do it again; now we're using caches. +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/before.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-WITHOUT-REBUILD %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-ONE-ERROR %s < %t/before.log + +// Add a blank line to the header to force the module to rebuild, without +// (yet) changing API notes. +// RUN: echo >> %t/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.h +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/before.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-REBUILD %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-ONE-ERROR %s < %t/before.log + +// Change the API notes file, after the module has rebuilt once. +// RUN: echo ' - Selector: "methodA"' >> %t/APINotes/SomeOtherKit.apinotes +// RUN: echo ' MethodKind: Instance' >> %t/APINotes/SomeOtherKit.apinotes +// RUN: echo ' Availability: none' >> %t/APINotes/SomeOtherKit.apinotes +// RUN: echo ' AvailabilityMsg: "not here either"' >> %t/APINotes/SomeOtherKit.apinotes + +// Build again: check that both methods are now unavailable and that the module rebuilt. +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/after.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODA %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-REBUILD %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-TWO-ERRORS %s < %t/after.log + +// Run the build again: check that both methods are now unavailable +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/after.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODA %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-WITHOUT-REBUILD %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-TWO-ERRORS %s < %t/after.log + +@import SomeOtherKit; + +void test(A *a) { + // CHECK-METHODA: error: 'methodA' is unavailable: not here either + [a methodA]; + + // CHECK-METHODB: error: 'methodB' is unavailable: anything but this + [a methodB]; +} + +// CHECK-REBUILD: remark: building module{{.*}}SomeOtherKit + +// CHECK-WITHOUT-REBUILD-NOT: remark: building module{{.*}}SomeOtherKit + +// CHECK-ONE-ERROR: 1 error generated. +// CHECK-TWO-ERRORS: 2 errors generated. + diff --git a/clang/test/APINotes/namespaces.cpp b/clang/test/APINotes/namespaces.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f9d93c2ea0e5a3ad0763cba5c2995a4f498d447 --- /dev/null +++ b/clang/test/APINotes/namespaces.cpp @@ -0,0 +1,69 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -x objective-c++ +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::my_typedef -x objective-c++ | FileCheck -check-prefix=CHECK-TYPEDEF-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::my_using_decl -x objective-c++ | FileCheck -check-prefix=CHECK-USING-DECL-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::varInNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-GLOBAL-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::funcInNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-FUNC-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::char_box -x objective-c++ | FileCheck -check-prefix=CHECK-STRUCT-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::varInNestedNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-GLOBAL-IN-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested2::varInNestedNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::char_box -x objective-c++ | FileCheck -check-prefix=CHECK-STRUCT-IN-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::funcInNestedNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-FUNC-IN-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::Namespace1::char_box -x objective-c++ | FileCheck -check-prefix=CHECK-STRUCT-IN-DEEP-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter varInInlineNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-GLOBAL-IN-INLINE-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter funcInInlineNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-FUNC-IN-INLINE-NAMESPACE %s + +#import + +// CHECK-TYPEDEF-IN-NAMESPACE: Dumping Namespace1::my_typedef: +// CHECK-TYPEDEF-IN-NAMESPACE-NEXT: TypedefDecl {{.+}} imported in Namespaces my_typedef 'int' +// CHECK-TYPEDEF-IN-NAMESPACE: SwiftNameAttr {{.+}} <> "SwiftTypedef" + +// CHECK-USING-DECL-IN-NAMESPACE: Dumping Namespace1::my_using_decl: +// CHECK-USING-DECL-IN-NAMESPACE-NEXT: TypeAliasDecl {{.+}} imported in Namespaces my_using_decl 'int' +// CHECK-USING-DECL-IN-NAMESPACE: SwiftNameAttr {{.+}} <> "SwiftUsingDecl" + +// CHECK-GLOBAL-IN-NAMESPACE: Dumping Namespace1::varInNamespace: +// CHECK-GLOBAL-IN-NAMESPACE-NEXT: VarDecl {{.+}} imported in Namespaces varInNamespace 'int' static cinit +// CHECK-GLOBAL-IN-NAMESPACE-NEXT: IntegerLiteral {{.+}} 'int' 1 +// CHECK-GLOBAL-IN-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <> "swiftVarInNamespace" + +// CHECK-FUNC-IN-NAMESPACE: Dumping Namespace1::funcInNamespace: +// CHECK-FUNC-IN-NAMESPACE-NEXT: FunctionDecl {{.+}} imported in Namespaces funcInNamespace 'void ()' +// CHECK-FUNC-IN-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <> "swiftFuncInNamespace()" + +// CHECK-STRUCT-IN-NAMESPACE: Dumping Namespace1::char_box: +// CHECK-STRUCT-IN-NAMESPACE-NEXT: CXXRecordDecl {{.+}} imported in Namespaces struct char_box +// CHECK-STRUCT-IN-NAMESPACE: SwiftNameAttr {{.+}} <> "CharBox" + +// CHECK-GLOBAL-IN-NESTED-NAMESPACE: Dumping Namespace1::Nested1::varInNestedNamespace: +// CHECK-GLOBAL-IN-NESTED-NAMESPACE-NEXT: VarDecl {{.+}} imported in Namespaces varInNestedNamespace 'int' static cinit +// CHECK-GLOBAL-IN-NESTED-NAMESPACE-NEXT: IntegerLiteral {{.+}} 'int' 1 +// CHECK-GLOBAL-IN-NESTED-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <> "swiftVarInNestedNamespace" + +// CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE: Dumping Namespace1::Nested2::varInNestedNamespace: +// CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE-NEXT: VarDecl {{.+}} imported in Namespaces varInNestedNamespace 'int' static cinit +// CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE-NEXT: IntegerLiteral {{.+}} 'int' 2 +// CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <> "swiftAnotherVarInNestedNamespace" + +// CHECK-FUNC-IN-NESTED-NAMESPACE: Dumping Namespace1::Nested1::funcInNestedNamespace: +// CHECK-FUNC-IN-NESTED-NAMESPACE-NEXT: FunctionDecl {{.+}} imported in Namespaces funcInNestedNamespace 'void (int)' +// CHECK-FUNC-IN-NESTED-NAMESPACE-NEXT: ParmVarDecl {{.+}} i 'int' +// CHECK-FUNC-IN-NESTED-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <> "swiftFuncInNestedNamespace(_:)" + +// CHECK-STRUCT-IN-NESTED-NAMESPACE: Dumping Namespace1::Nested1::char_box: +// CHECK-STRUCT-IN-NESTED-NAMESPACE-NEXT: CXXRecordDecl {{.+}} imported in Namespaces struct char_box +// CHECK-STRUCT-IN-NESTED-NAMESPACE: SwiftNameAttr {{.+}} <> "NestedCharBox" + +// CHECK-STRUCT-IN-DEEP-NESTED-NAMESPACE: Dumping Namespace1::Nested1::Namespace1::char_box: +// CHECK-STRUCT-IN-DEEP-NESTED-NAMESPACE-NEXT: CXXRecordDecl {{.+}} imported in Namespaces struct char_box +// CHECK-STRUCT-IN-DEEP-NESTED-NAMESPACE: SwiftNameAttr {{.+}} <> "DeepNestedCharBox" + +// CHECK-GLOBAL-IN-INLINE-NAMESPACE: Dumping varInInlineNamespace: +// CHECK-GLOBAL-IN-INLINE-NAMESPACE-NEXT: VarDecl {{.+}} imported in Namespaces varInInlineNamespace 'int' static cinit +// CHECK-GLOBAL-IN-INLINE-NAMESPACE-NEXT: IntegerLiteral {{.+}} 'int' 3 +// CHECK-GLOBAL-IN-INLINE-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <> "swiftVarInInlineNamespace" + +// CHECK-FUNC-IN-INLINE-NAMESPACE: Dumping funcInInlineNamespace: +// CHECK-FUNC-IN-INLINE-NAMESPACE-NEXT: FunctionDecl {{.+}} imported in Namespaces funcInInlineNamespace 'void ()' +// CHECK-FUNC-IN-INLINE-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <> "swiftFuncInInlineNamespace()" diff --git a/clang/test/APINotes/nullability.c b/clang/test/APINotes/nullability.c new file mode 100644 index 0000000000000000000000000000000000000000..e07fc2e5c11743e9a8bcc6333bff65cb97dff014 --- /dev/null +++ b/clang/test/APINotes/nullability.c @@ -0,0 +1,21 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +#include "HeaderLib.h" + +int main() { + custom_realloc(0, 0); // expected-warning{{null passed to a callee that requires a non-null argument}} + int i = 0; + do_something_with_pointers(&i, 0); + do_something_with_pointers(0, &i); // expected-warning{{null passed to a callee that requires a non-null argument}} + + extern void *p; + do_something_with_arrays(0, p); // expected-warning{{null passed to a callee that requires a non-null argument}} + do_something_with_arrays(p, 0); // expected-warning{{null passed to a callee that requires a non-null argument}} + + take_pointer_and_int(0, 0); // expected-warning{{null passed to a callee that requires a non-null argument}} + + float *fp = global_int; // expected-warning{{incompatible pointer types initializing 'float *' with an expression of type 'int * _Nonnull'}} + return 0; +} + diff --git a/clang/test/APINotes/nullability.m b/clang/test/APINotes/nullability.m new file mode 100644 index 0000000000000000000000000000000000000000..21ec6680fa714d1b2b629851ba4ea3243f08aba3 --- /dev/null +++ b/clang/test/APINotes/nullability.m @@ -0,0 +1,46 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +// Test with Swift version 3.0. This should only affect the few APIs that have an entry in the 3.0 tables. + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fapinotes-swift-version=3.0 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify -DSWIFT_VERSION_3_0 -fmodules-ignore-macro=SWIFT_VERSION_3_0 + +#import + +int main() { + A *a; + +#if SWIFT_VERSION_3_0 + float *fp = // expected-warning{{incompatible pointer types initializing 'float *' with an expression of type 'A * _Nullable'}} + [a transform: 0 integer: 0]; +#else + float *fp = // expected-warning{{incompatible pointer types initializing 'float *' with an expression of type 'A *'}} + [a transform: 0 integer: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} +#endif + + [a setNonnullAInstance: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + [A setNonnullAInstance: 0]; // no warning + a.nonnullAInstance = 0; // expected-warning{{null passed to a callee that requires a non-null argument}} + A* _Nonnull aPtr = a.nonnullAInstance; // no warning + + [a setNonnullAClass: 0]; // no warning + [A setNonnullAClass: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + + [a setNonnullABoth: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + [A setNonnullABoth: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + + [a setInternalProperty: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + +#if SWIFT_VERSION_3_0 + // Version 3 information overrides header information. + [a setExplicitNonnullInstance: 0]; // okay + [a setExplicitNullableInstance: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} +#else + // Header information overrides unversioned information. + [a setExplicitNonnullInstance: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + [a setExplicitNullableInstance: 0]; // okay +#endif + + return 0; +} + diff --git a/clang/test/APINotes/objc-forward-declarations.m b/clang/test/APINotes/objc-forward-declarations.m new file mode 100644 index 0000000000000000000000000000000000000000..e82bed20555049b968cefe30faaf30c8d2f36a49 --- /dev/null +++ b/clang/test/APINotes/objc-forward-declarations.m @@ -0,0 +1,12 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -F %S/Inputs/Frameworks %s -verify + +@import LayeredKit; + +void test( + UpwardClass *okayClass, + id okayProto, + PerfectlyNormalClass *badClass // expected-error {{'PerfectlyNormalClass' is unavailable}} +) { + // expected-note@LayeredKitImpl/LayeredKitImpl.h:4 {{'PerfectlyNormalClass' has been explicitly marked unavailable here}} +} diff --git a/clang/test/APINotes/objc_designated_inits.m b/clang/test/APINotes/objc_designated_inits.m new file mode 100644 index 0000000000000000000000000000000000000000..1f2b8ed534b7a170b9915e8dfb2894d476e36b54 --- /dev/null +++ b/clang/test/APINotes/objc_designated_inits.m @@ -0,0 +1,17 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +#include "HeaderLib.h" +#import + +@interface CSub : C +-(instancetype)initWithA:(A*)a; +@end + +@implementation CSub +-(instancetype)initWithA:(A*)a { // expected-warning{{designated initializer missing a 'super' call to a designated initializer of the super class}} + // expected-note@SomeKit/SomeKit.h:20 2{{method marked as designated initializer of the class here}} + self = [super init]; // expected-warning{{designated initializer invoked a non-designated initializer}} + return self; +} +@end diff --git a/clang/test/APINotes/properties.m b/clang/test/APINotes/properties.m new file mode 100644 index 0000000000000000000000000000000000000000..f218092a66e1dc10e07ace0b751c84660cf0e8f1 --- /dev/null +++ b/clang/test/APINotes/properties.m @@ -0,0 +1,42 @@ +// RUN: rm -rf %t && mkdir -p %t + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fblocks -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter 'TestProperties::' | FileCheck -check-prefix=CHECK -check-prefix=CHECK-4 %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fblocks -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter 'TestProperties::' -fapinotes-swift-version=3 | FileCheck -check-prefix=CHECK -check-prefix=CHECK-3 %s + +@import VersionedKit; + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnly 'id' +// CHECK-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClass 'id' +// CHECK-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyInVersion3 'id' +// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-4-NEXT: SwiftVersionedAdditionAttr {{.+}} 3.0{{$}} +// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClassInVersion3 'id' +// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-4-NEXT: SwiftVersionedAdditionAttr {{.+}} 3.0{{$}} +// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyExceptInVersion3 'id' +// CHECK-3-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}} +// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-4-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}} +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClassExceptInVersion3 'id' +// CHECK-3-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}} +// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-4-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}} +// CHECK-NOT: Attr + +// CHECK-LABEL: Decl diff --git a/clang/test/APINotes/retain-count-convention.m b/clang/test/APINotes/retain-count-convention.m new file mode 100644 index 0000000000000000000000000000000000000000..4bf9610a352a7533de4522c1e6dc42fb890eb9e2 --- /dev/null +++ b/clang/test/APINotes/retain-count-convention.m @@ -0,0 +1,38 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fdisable-module-hash -fsyntax-only -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/SimpleKit.pcm | FileCheck %s +// RUN: %clang_cc1 -ast-dump -ast-dump-filter 'DUMP' %t/ModulesCache/SimpleKit.pcm | FileCheck -check-prefix CHECK-DUMP %s + +#import + +// CHECK: void *getCFOwnedToUnowned(void) __attribute__((cf_returns_not_retained)); +// CHECK: void *getCFUnownedToOwned(void) __attribute__((cf_returns_retained)); +// CHECK: void *getCFOwnedToNone(void) __attribute__((cf_unknown_transfer)); +// CHECK: id getObjCOwnedToUnowned(void) __attribute__((ns_returns_not_retained)); +// CHECK: id getObjCUnownedToOwned(void) __attribute__((ns_returns_retained)); +// CHECK: int indirectGetCFOwnedToUnowned(void * _Nullable *out __attribute__((cf_returns_not_retained))); +// CHECK: int indirectGetCFUnownedToOwned(void * _Nullable *out __attribute__((cf_returns_retained))); +// CHECK: int indirectGetCFOwnedToNone(void * _Nullable *out); +// CHECK: int indirectGetCFNoneToOwned(void **out __attribute__((cf_returns_not_retained))); + +// CHECK-LABEL: @interface MethodTest +// CHECK: - (id)getOwnedToUnowned __attribute__((ns_returns_not_retained)); +// CHECK: - (id)getUnownedToOwned __attribute__((ns_returns_retained)); +// CHECK: @end + +// CHECK-DUMP-LABEL: Dumping getCFAuditedToUnowned_DUMP: +// CHECK-DUMP-NEXT: FunctionDecl +// CHECK-DUMP-NEXT: CFReturnsNotRetainedAttr +// CHECK-DUMP-NEXT: CFAuditedTransferAttr +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping getCFAuditedToOwned_DUMP: +// CHECK-DUMP-NEXT: FunctionDecl +// CHECK-DUMP-NEXT: CFReturnsRetainedAttr +// CHECK-DUMP-NEXT: CFAuditedTransferAttr +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping getCFAuditedToNone_DUMP: +// CHECK-DUMP-NEXT: FunctionDecl +// CHECK-DUMP-NEXT: CFUnknownTransferAttr +// CHECK-DUMP-NOT: Attr diff --git a/clang/test/APINotes/search-order.m b/clang/test/APINotes/search-order.m new file mode 100644 index 0000000000000000000000000000000000000000..17e81d5eb2d691d480a743f59368846b2a9438a4 --- /dev/null +++ b/clang/test/APINotes/search-order.m @@ -0,0 +1,25 @@ +// RUN: rm -rf %t && mkdir -p %t + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -DFROM_FRAMEWORK=1 -verify + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %S/Inputs/APINotes -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -DFROM_SEARCH_PATH=1 -verify + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -iapinotes-modules %S/Inputs/APINotes -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -DFROM_FRAMEWORK=1 -verify + +@import SomeOtherKit; + +void test(A *a) { +#if FROM_FRAMEWORK + [a methodA]; // expected-error{{unavailable}} + [a methodB]; + + // expected-note@SomeOtherKit/SomeOtherKit.h:5{{'methodA' has been explicitly marked unavailable here}} +#elif FROM_SEARCH_PATH + [a methodA]; + [a methodB]; // expected-error{{unavailable}} + + // expected-note@SomeOtherKit/SomeOtherKit.h:6{{'methodB' has been explicitly marked unavailable here}} +#else +# error Not something we need to test +#endif +} diff --git a/clang/test/APINotes/swift-import-as.cpp b/clang/test/APINotes/swift-import-as.cpp new file mode 100644 index 0000000000000000000000000000000000000000..904857e5859303f9f498c98c6e7717bff9c4a2c7 --- /dev/null +++ b/clang/test/APINotes/swift-import-as.cpp @@ -0,0 +1,16 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -x c++ +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter ImmortalRefType | FileCheck -check-prefix=CHECK-IMMORTAL %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter RefCountedType | FileCheck -check-prefix=CHECK-REF-COUNTED %s + +#include + +// CHECK-IMMORTAL: Dumping ImmortalRefType: +// CHECK-IMMORTAL-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct ImmortalRefType +// CHECK-IMMORTAL: SwiftAttrAttr {{.+}} <> "import_reference" + +// CHECK-REF-COUNTED: Dumping RefCountedType: +// CHECK-REF-COUNTED-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct RefCountedType +// CHECK-REF-COUNTED: SwiftAttrAttr {{.+}} <> "import_reference" +// CHECK-REF-COUNTED: SwiftAttrAttr {{.+}} <> "retain:RCRetain" +// CHECK-REF-COUNTED: SwiftAttrAttr {{.+}} <> "release:RCRelease" diff --git a/clang/test/APINotes/top-level-private-modules.c b/clang/test/APINotes/top-level-private-modules.c new file mode 100644 index 0000000000000000000000000000000000000000..0da72b2e36f4f2b1be3bb05e011963d4f559adfa --- /dev/null +++ b/clang/test/APINotes/top-level-private-modules.c @@ -0,0 +1,8 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +#include +#include + +void *testPlain = PrivateLib; // expected-error {{initializing 'void *' with an expression of incompatible type 'float'}} +void *testFramework = TopLevelPrivateKit_Private; // expected-error {{initializing 'void *' with an expression of incompatible type 'float'}} diff --git a/clang/test/APINotes/types.m b/clang/test/APINotes/types.m new file mode 100644 index 0000000000000000000000000000000000000000..133d504713d76cd97a1772fadfec3e9c5fcc1e07 --- /dev/null +++ b/clang/test/APINotes/types.m @@ -0,0 +1,28 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fdisable-module-hash -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify +// RUN: %clang_cc1 -ast-print %t/ModulesCache/SimpleKit.pcm | FileCheck %s + +#import +#import + +// CHECK: struct __attribute__((swift_name("SuccessfullyRenamedA"))) RenamedAgainInAPINotesA { +// CHECK: struct __attribute__((swift_name("SuccessfullyRenamedB"))) RenamedAgainInAPINotesB { + +void test(OverriddenTypes *overridden) { + int *ip1 = global_int_ptr; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'double (*)(int, int)'}} + + int *ip2 = global_int_fun( // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'char *'}} + ip2, // expected-warning{{incompatible pointer types passing 'int *' to parameter of type 'double *'}} + ip2); // expected-warning{{incompatible pointer types passing 'int *' to parameter of type 'float *'}} + + int *ip3 = [overridden // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'char *'}} + methodToMangle: ip3 // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'double *'}} + second: ip3]; // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'float *'}} + + int *ip4 = overridden.intPropertyToMangle; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'double *'}} +} + +// expected-note@SomeKit/SomeKit.h:42{{passing argument to parameter 'ptr' here}} +// expected-note@SomeKit/SomeKit.h:42{{passing argument to parameter 'ptr2' here}} +// expected-note@SomeKit/SomeKit.h:48{{passing argument to parameter 'ptr1' here}} +// expected-note@SomeKit/SomeKit.h:48{{passing argument to parameter 'ptr2' here}} diff --git a/clang/test/APINotes/versioned-multi.c b/clang/test/APINotes/versioned-multi.c new file mode 100644 index 0000000000000000000000000000000000000000..48c51fd932e17ca43541d6dce4654546fbc7002f --- /dev/null +++ b/clang/test/APINotes/versioned-multi.c @@ -0,0 +1,69 @@ +// RUN: rm -rf %t && mkdir -p %t + +// Build and check the unversioned module file. +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Unversioned/VersionedKit.pcm | FileCheck -check-prefix=CHECK-UNVERSIONED %s + +// Build and check the various versions. +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned3 -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=3 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Versioned3/VersionedKit.pcm | FileCheck -check-prefix=CHECK-VERSIONED-3 %s + +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned4 -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=4 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Versioned4/VersionedKit.pcm | FileCheck -check-prefix=CHECK-VERSIONED-4 %s + +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned5 -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=5 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Versioned5/VersionedKit.pcm | FileCheck -check-prefix=CHECK-VERSIONED-5 %s + +#import + +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef4; +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef4Notes __attribute__((swift_name("MultiVersionedTypedef4Notes_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef34; +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef34Notes __attribute__((swift_name("MultiVersionedTypedef34Notes_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef45; +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef45Notes __attribute__((swift_name("MultiVersionedTypedef45Notes_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef345; +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef345Notes __attribute__((swift_name("MultiVersionedTypedef345Notes_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_NEW"))); + +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef4 __attribute__((swift_name("MultiVersionedTypedef4_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef4Notes __attribute__((swift_name("MultiVersionedTypedef4Notes_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef34 __attribute__((swift_name("MultiVersionedTypedef34_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef34Notes __attribute__((swift_name("MultiVersionedTypedef34Notes_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef45 __attribute__((swift_name("MultiVersionedTypedef45_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef45Notes __attribute__((swift_name("MultiVersionedTypedef45Notes_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef345 __attribute__((swift_name("MultiVersionedTypedef345_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef345Notes __attribute__((swift_name("MultiVersionedTypedef345Notes_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_3"))); + +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef4 __attribute__((swift_name("MultiVersionedTypedef4_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef4Notes __attribute__((swift_name("MultiVersionedTypedef4Notes_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef34 __attribute__((swift_name("MultiVersionedTypedef34_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef34Notes __attribute__((swift_name("MultiVersionedTypedef34Notes_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef45 __attribute__((swift_name("MultiVersionedTypedef45_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef45Notes __attribute__((swift_name("MultiVersionedTypedef45Notes_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef345 __attribute__((swift_name("MultiVersionedTypedef345_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef345Notes __attribute__((swift_name("MultiVersionedTypedef345Notes_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_4"))); + +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef4; +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef4Notes __attribute__((swift_name("MultiVersionedTypedef4Notes_NEW"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_NEW"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef34; +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef34Notes __attribute__((swift_name("MultiVersionedTypedef34Notes_NEW"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_NEW"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef45 __attribute__((swift_name("MultiVersionedTypedef45_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef45Notes __attribute__((swift_name("MultiVersionedTypedef45Notes_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef345 __attribute__((swift_name("MultiVersionedTypedef345_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef345Notes __attribute__((swift_name("MultiVersionedTypedef345Notes_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_5"))); diff --git a/clang/test/APINotes/versioned.m b/clang/test/APINotes/versioned.m new file mode 100644 index 0000000000000000000000000000000000000000..61cc8c3f7c4d1ea80b2f71880d3ad13d24ae7b2d --- /dev/null +++ b/clang/test/APINotes/versioned.m @@ -0,0 +1,187 @@ +// RUN: rm -rf %t && mkdir -p %t + +// Build and check the unversioned module file. +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Unversioned/VersionedKit.pcm | FileCheck -check-prefix=CHECK-UNVERSIONED %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter 'DUMP' | FileCheck -check-prefix=CHECK-DUMP -check-prefix=CHECK-UNVERSIONED-DUMP %s + +// Build and check the versioned module file. +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=3 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Versioned/VersionedKit.pcm | FileCheck -check-prefix=CHECK-VERSIONED %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=3 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter 'DUMP' | FileCheck -check-prefix=CHECK-DUMP -check-prefix=CHECK-VERSIONED-DUMP %s + +#import + +// CHECK-UNVERSIONED: void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(x:y:)"))); +// CHECK-VERSIONED: void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(a:b:)"))); + +// CHECK-DUMP-LABEL: Dumping moveToPointDUMP +// CHECK-VERSIONED-DUMP: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}} +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "moveTo(x:y:)" +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <> "moveTo(a:b:)" +// CHECK-UNVERSIONED-DUMP: SwiftNameAttr {{.+}} "moveTo(x:y:)" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <> "moveTo(a:b:)" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping unversionedRenameDUMP +// CHECK-DUMP: in VersionedKit unversionedRenameDUMP +// CHECK-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 0 IsReplacedByActive{{$}} +// CHECK-DUMP-NEXT: SwiftNameAttr {{.+}} "unversionedRename_HEADER()" +// CHECK-DUMP-NEXT: SwiftNameAttr {{.+}} "unversionedRename_NOTES()" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping TestGenericDUMP +// CHECK-VERSIONED-DUMP: SwiftImportAsNonGenericAttr {{.+}} <> +// CHECK-UNVERSIONED-DUMP: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftImportAsNonGenericAttr {{.+}} <> +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping Swift3RenamedOnlyDUMP +// CHECK-DUMP: in VersionedKit Swift3RenamedOnlyDUMP +// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}} IsReplacedByActive{{$}} +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift3Name" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <> "SpecialSwift3Name" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping Swift3RenamedAlsoDUMP +// CHECK-DUMP: in VersionedKit Swift3RenamedAlsoDUMP +// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}} +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "Swift4Name" +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift3Also" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "Swift4Name" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <> "SpecialSwift3Also" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping Swift4RenamedDUMP +// CHECK-DUMP: in VersionedKit Swift4RenamedDUMP +// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 4 {{[0-9]+}} IsReplacedByActive{{$}} +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift4Name" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 4{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <> "SpecialSwift4Name" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-NOT: Dumping + +// CHECK-UNVERSIONED: void acceptClosure(void (^block)(void) __attribute__((noescape))); +// CHECK-VERSIONED: void acceptClosure(void (^block)(void)); + +// CHECK-UNVERSIONED: void privateFunc(void) __attribute__((swift_private)); + +// CHECK-UNVERSIONED: typedef double MyDoubleWrapper __attribute__((swift_wrapper("struct"))); + +// CHECK-UNVERSIONED: enum __attribute__((ns_error_domain(MyErrorDomain))) MyErrorCode { +// CHECK-UNVERSIONED-NEXT: MyErrorCodeFailed = 1 +// CHECK-UNVERSIONED-NEXT: }; + +// CHECK-UNVERSIONED: __attribute__((swift_bridge("MyValueType"))) +// CHECK-UNVERSIONED: @interface MyReferenceType + +// CHECK-VERSIONED: void privateFunc(void); + +// CHECK-VERSIONED: typedef double MyDoubleWrapper; + +// CHECK-VERSIONED: enum MyErrorCode { +// CHECK-VERSIONED-NEXT: MyErrorCodeFailed = 1 +// CHECK-VERSIONED-NEXT: }; + +// CHECK-VERSIONED-NOT: __attribute__((swift_bridge("MyValueType"))) +// CHECK-VERSIONED: @interface MyReferenceType + +// CHECK-UNVERSIONED: __attribute__((swift_objc_members) +// CHECK-UNVERSIONED-NEXT: @interface TestProperties +// CHECK-VERSIONED-NOT: __attribute__((swift_objc_members) +// CHECK-VERSIONED: @interface TestProperties + +// CHECK-UNVERSIONED-LABEL: enum __attribute__((flag_enum)) FlagEnum { +// CHECK-UNVERSIONED-NEXT: FlagEnumA = 1, +// CHECK-UNVERSIONED-NEXT: FlagEnumB = 2 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((flag_enum)) NewlyFlagEnum { +// CHECK-UNVERSIONED-NEXT: NewlyFlagEnumA = 1, +// CHECK-UNVERSIONED-NEXT: NewlyFlagEnumB = 2 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((flag_enum)) APINotedFlagEnum { +// CHECK-UNVERSIONED-NEXT: APINotedFlagEnumA = 1, +// CHECK-UNVERSIONED-NEXT: APINotedFlagEnumB = 2 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) OpenEnum { +// CHECK-UNVERSIONED-NEXT: OpenEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) NewlyOpenEnum { +// CHECK-UNVERSIONED-NEXT: NewlyOpenEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) NewlyClosedEnum { +// CHECK-UNVERSIONED-NEXT: NewlyClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) ClosedToOpenEnum { +// CHECK-UNVERSIONED-NEXT: ClosedToOpenEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) OpenToClosedEnum { +// CHECK-UNVERSIONED-NEXT: OpenToClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) APINotedOpenEnum { +// CHECK-UNVERSIONED-NEXT: APINotedOpenEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) APINotedClosedEnum { +// CHECK-UNVERSIONED-NEXT: APINotedClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; + +// CHECK-VERSIONED-LABEL: enum __attribute__((flag_enum)) FlagEnum { +// CHECK-VERSIONED-NEXT: FlagEnumA = 1, +// CHECK-VERSIONED-NEXT: FlagEnumB = 2 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum NewlyFlagEnum { +// CHECK-VERSIONED-NEXT: NewlyFlagEnumA = 1, +// CHECK-VERSIONED-NEXT: NewlyFlagEnumB = 2 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((flag_enum)) APINotedFlagEnum { +// CHECK-VERSIONED-NEXT: APINotedFlagEnumA = 1, +// CHECK-VERSIONED-NEXT: APINotedFlagEnumB = 2 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) OpenEnum { +// CHECK-VERSIONED-NEXT: OpenEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum NewlyOpenEnum { +// CHECK-VERSIONED-NEXT: NewlyOpenEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum NewlyClosedEnum { +// CHECK-VERSIONED-NEXT: NewlyClosedEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) ClosedToOpenEnum { +// CHECK-VERSIONED-NEXT: ClosedToOpenEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) OpenToClosedEnum { +// CHECK-VERSIONED-NEXT: OpenToClosedEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) APINotedOpenEnum { +// CHECK-VERSIONED-NEXT: APINotedOpenEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) APINotedClosedEnum { +// CHECK-VERSIONED-NEXT: APINotedClosedEnumA = 1 +// CHECK-VERSIONED-NEXT: }; + +// These don't actually have versioned information, so we just check them once. +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) SoonToBeCFEnum { +// CHECK-UNVERSIONED-NEXT: SoonToBeCFEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) SoonToBeNSEnum { +// CHECK-UNVERSIONED-NEXT: SoonToBeNSEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) __attribute__((flag_enum)) SoonToBeCFOptions { +// CHECK-UNVERSIONED-NEXT: SoonToBeCFOptionsA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) __attribute__((flag_enum)) SoonToBeNSOptions { +// CHECK-UNVERSIONED-NEXT: SoonToBeNSOptionsA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) SoonToBeCFClosedEnum { +// CHECK-UNVERSIONED-NEXT: SoonToBeCFClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) SoonToBeNSClosedEnum { +// CHECK-UNVERSIONED-NEXT: SoonToBeNSClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum UndoAllThatHasBeenDoneToMe { +// CHECK-UNVERSIONED-NEXT: UndoAllThatHasBeenDoneToMeA = 1 +// CHECK-UNVERSIONED-NEXT: }; diff --git a/clang/test/APINotes/yaml-convert-diags.c b/clang/test/APINotes/yaml-convert-diags.c new file mode 100644 index 0000000000000000000000000000000000000000..1d352dc2c52309691a9c7a23460a0d20973a5e90 --- /dev/null +++ b/clang/test/APINotes/yaml-convert-diags.c @@ -0,0 +1,6 @@ +// RUN: rm -rf %t +// RUN: not %clang_cc1 -fsyntax-only -fapinotes %s -I %S/Inputs/BrokenHeaders2 2>&1 | FileCheck %s + +#include "SomeBrokenLib.h" + +// CHECK: error: multiple definitions of global function 'do_something_with_pointers' diff --git a/clang/test/APINotes/yaml-parse-diags.c b/clang/test/APINotes/yaml-parse-diags.c new file mode 100644 index 0000000000000000000000000000000000000000..3ae39ccb301d3d9af8604be4eeb9001c2095cca8 --- /dev/null +++ b/clang/test/APINotes/yaml-parse-diags.c @@ -0,0 +1,6 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -fapinotes %s -I %S/Inputs/BrokenHeaders -verify + +#include "SomeBrokenLib.h" + +// expected-error@APINotes.apinotes:4{{unknown key 'Nu llabilityOfRet'}} diff --git a/clang/test/APINotes/yaml-reader-errors.m b/clang/test/APINotes/yaml-reader-errors.m new file mode 100644 index 0000000000000000000000000000000000000000..9e5ee34c3e4152feb2afb6dc45838642a6f5d442 --- /dev/null +++ b/clang/test/APINotes/yaml-reader-errors.m @@ -0,0 +1,5 @@ +// RUN: rm -rf %t +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fapinotes -fapinotes-modules -fmodules-cache-path=%t -I %S/Inputs/yaml-reader-errors/ -fsyntax-only %s > %t.err 2>&1 +// RUN: FileCheck %S/Inputs/yaml-reader-errors/UIKit.apinotes < %t.err + +@import UIKit; 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/digraphs.c b/clang/test/C/C99/digraphs.c new file mode 100644 index 0000000000000000000000000000000000000000..870a441118161af9d05f8b868d6555af52c57c08 --- /dev/null +++ b/clang/test/C/C99/digraphs.c @@ -0,0 +1,90 @@ +// RUN: %clang_cc1 -verify -ffreestanding %s + +/* WG14 ???: yes + * restricted character set support via digraphs and + * + * NB: I cannot find a definitive document number associated with the feature, + * which was pulled from the editor's report in the C99 front matter. However, + * based on discussion in the C99 rationale document, I believe this is + * referring to features added by AMD1 to support ISO 646 and digraphs. + */ + +// Validate that we provide iso646.h in freestanding mode. +#include + +// Validate that we define all the expected macros and their expected +// expansions (when suitable for a constant expression) as well. +#ifndef and +#error "missing and" +#else +_Static_assert((1 and 1) == (1 && 1), ""); +#endif + +#ifndef and_eq +#error "missing and_eq" +#endif + +#ifndef bitand +#error "missing bitand" +#else +_Static_assert((1 bitand 3) == (1 & 3), ""); +#endif + +#ifndef bitor +#error "missing bitor" +#else +_Static_assert((1 bitor 2) == (1 | 2), ""); +#endif + +#ifndef compl +#error "missing compl" +#else +_Static_assert((compl 0) == (~0), ""); +#endif + +#ifndef not +#error "missing not" +#else +_Static_assert((not 12) == (!12), ""); +#endif + +#ifndef not_eq +#error "missing not_eq" +#else +_Static_assert((0 not_eq 12) == (0 != 12), ""); +#endif + +#ifndef or +#error "missing or" +#else +// This intentionally diagnoses use of '||' only, because the user likely did +// not confuse the operator when using 'or' instead. +_Static_assert((0 or 12) == (0 || 12), ""); // expected-warning {{use of logical '||' with constant operand}} \ + expected-note {{use '|' for a bitwise operation}} +#endif + +#ifndef or_eq +#error "missing or_eq" +#endif + +#ifndef xor +#error "missing xor" +#else +_Static_assert((1 xor 3) == (1 ^ 3), ""); +#endif + +#ifndef xor_eq +#error "missing xor_eq" +#endif + +// Validate that digraphs behave the same as their expected counterparts. The +// definition should match the declaration in every way except spelling. +#define DI_NAME(f, b) f %:%: b +#define STD_NAME(f, b) f ## b +void DI_NAME(foo, bar)(int (*array)<: 0 :>); +void STD_NAME(foo, bar)(int (*array)[0]) {} + +#define DI_STR(f) %:f +#define STD_STR(f) #f +_Static_assert(__builtin_strcmp(DI_STR(testing), STD_STR(testing)) == 0, ""); + 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/C/drs/dr5xx.c b/clang/test/C/drs/dr5xx.c index 68bcef78baccd7caca8f0d373ca91bc2c72ab70d..13464f78b6a654a3821e8b587fd3642a6d1a1e0b 100644 --- a/clang/test/C/drs/dr5xx.c +++ b/clang/test/C/drs/dr5xx.c @@ -29,7 +29,7 @@ void dr502(void) { */ struct t { int i; - struct { int a[]; }; /* expected-error {{flexible array member 'a' not allowed in otherwise empty struct}} + struct { int a[]; }; /* expected-warning {{flexible array member 'a' in otherwise empty struct is a GNU extension}} c89only-warning {{flexible array members are a C99 feature}} expected-warning {{'' may not be nested in a struct due to flexible array member}} */ 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/CodeCompletion/member-access.cpp b/clang/test/CodeCompletion/member-access.cpp index 474b909ab11592c5520b714dcb5744f65fcfe6e1..9f8c21c0bca6de1efaf6c4e74821e87274f09d01 100644 --- a/clang/test/CodeCompletion/member-access.cpp +++ b/clang/test/CodeCompletion/member-access.cpp @@ -348,7 +348,23 @@ namespace function_can_be_call { T foo(U, V); }; - &S::f - // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:351:7 %s -o - | FileCheck -check-prefix=CHECK_FUNCTION_CAN_BE_CALL %s + void test() { + &S::f + } + // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:352:9 %s -o - | FileCheck -check-prefix=CHECK_FUNCTION_CAN_BE_CALL %s // CHECK_FUNCTION_CAN_BE_CALL: COMPLETION: foo : [#T#]foo<<#typename T#>, <#typename U#>>(<#U#>, <#V#>) } + +namespace deref_dependent_this { +template +class A { + int field; + + void function() { + (*this).field; +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:364:13 %s -o - | FileCheck -check-prefix=CHECK-DEREF-THIS %s +// CHECK-DEREF-THIS: field : [#int#]field +// CHECK-DEREF-THIS: [#void#]function() + } +}; +} diff --git a/clang/test/CodeGen/CSKY/csky-abi.c b/clang/test/CodeGen/CSKY/csky-abi.c index 2e549376ba93301b7eef4e746817fc2497843ead..29ed661aea75d94853ae28eff77136ee97547ee1 100644 --- a/clang/test/CodeGen/CSKY/csky-abi.c +++ b/clang/test/CodeGen/CSKY/csky-abi.c @@ -185,13 +185,13 @@ void f_va_caller(void) { // CHECK: [[VA:%.*]] = alloca ptr, align 4 // CHECK: [[V:%.*]] = alloca i32, align 4 // CHECK: store ptr %fmt, ptr [[FMT_ADDR]], align 4 -// CHECK: call void @llvm.va_start(ptr [[VA]]) +// CHECK: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK: [[TMP1:%.*]] = load i32, ptr [[ARGP_CUR]], align 4 // CHECK: store i32 [[TMP1]], ptr [[V]], align 4 -// CHECK: call void @llvm.va_end(ptr [[VA]]) +// CHECK: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK: [[TMP2:%.*]] = load i32, ptr [[V]], align 4 // CHECK: ret i32 [[TMP2]] // CHECK: } @@ -210,13 +210,13 @@ int f_va_1(char *fmt, ...) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[V:%.*]] = alloca double, align 4 // CHECK-NEXT: store ptr [[FMT:%.*]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP4:%.*]] = load double, ptr [[ARGP_CUR]], align 4 // CHECK-NEXT: store double [[TMP4]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP5:%.*]] = load double, ptr [[V]], align 4 // CHECK-NEXT: ret double [[TMP5]] double f_va_2(char *fmt, ...) { @@ -236,7 +236,7 @@ double f_va_2(char *fmt, ...) { // CHECK-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[X:%.*]] = alloca double, align 4 // CHECK-NEXT: store ptr [[FMT:%.*]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -252,7 +252,7 @@ double f_va_2(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT5]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP11:%.*]] = load double, ptr [[ARGP_CUR4]], align 4 // CHECK-NEXT: store double [[TMP11]], ptr [[X]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP12:%.*]] = load double, ptr [[V]], align 4 // CHECK-NEXT: [[TMP13:%.*]] = load double, ptr [[X]], align 4 // CHECK-NEXT: [[ADD:%.*]] = fadd double [[TMP12]], [[TMP13]] @@ -279,7 +279,7 @@ double f_va_3(char *fmt, ...) { // CHECK-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4 // CHECK-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT:%.*]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -302,7 +302,7 @@ double f_va_3(char *fmt, ...) { // CHECK-NEXT: [[ARGP_NEXT9:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR8]], i32 16 // CHECK-NEXT: store ptr [[ARGP_NEXT9]], ptr [[VA]], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[ARGP_CUR8]], i32 16, i1 false) -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) int f_va_4(char *fmt, ...) { __builtin_va_list va; diff --git a/clang/test/CodeGen/LoongArch/abi-lp64d.c b/clang/test/CodeGen/LoongArch/abi-lp64d.c index 66b480a7f068945484b3292014de43fe6db5dd23..fc7f1eada586b38e90fb610dee2f582ff5cce5a3 100644 --- a/clang/test/CodeGen/LoongArch/abi-lp64d.c +++ b/clang/test/CodeGen/LoongArch/abi-lp64d.c @@ -449,13 +449,13 @@ void f_va_caller(void) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT:%.*]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 8 // CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] int f_va_int(char *fmt, ...) { diff --git a/clang/test/CodeGen/PowerPC/aix-altivec-vaargs.c b/clang/test/CodeGen/PowerPC/aix-altivec-vaargs.c index 03182423a422c1e8bd440f3664a5b29dab9ef268..b3f1e93b6394405dd5c359cdf1bebd1ace550b5f 100644 --- a/clang/test/CodeGen/PowerPC/aix-altivec-vaargs.c +++ b/clang/test/CodeGen/PowerPC/aix-altivec-vaargs.c @@ -17,7 +17,7 @@ vector double vector_varargs(int count, ...) { } // CHECK: %arg_list = alloca ptr -// CHECK: call void @llvm.va_start(ptr %arg_list) +// CHECK: call void @llvm.va_start.p0(ptr %arg_list) // AIX32: for.body: // AIX32-NEXT: %argp.cur = load ptr, ptr %arg_list, align 4 @@ -41,4 +41,4 @@ vector double vector_varargs(int count, ...) { // CHECK: for.end: -// CHECK: call void @llvm.va_end(ptr %arg_list) +// CHECK: call void @llvm.va_end.p0(ptr %arg_list) diff --git a/clang/test/CodeGen/PowerPC/aix-vaargs.c b/clang/test/CodeGen/PowerPC/aix-vaargs.c index 8b8417d315a504577e8b5b2b5138532d999abe2d..724ba6560cdb97125c335e97336abcda537fcd96 100644 --- a/clang/test/CodeGen/PowerPC/aix-vaargs.c +++ b/clang/test/CodeGen/PowerPC/aix-vaargs.c @@ -35,7 +35,7 @@ void testva (int n, ...) { // CHECK-NEXT: %v = alloca i32, align 4 // CHECK-NEXT: store i32 %n, ptr %n.addr, align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr %ap) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr %ap) // AIX32-NEXT: %argp.cur = load ptr, ptr %ap, align 4 // AIX32-NEXT: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 16 @@ -48,7 +48,7 @@ void testva (int n, ...) { // AIX32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 %t, ptr align 4 %argp.cur, i32 16, i1 false) // AIX64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %t, ptr align 8 %argp.cur, i64 16, i1 false) -// CHECK-NEXT: call void @llvm.va_copy(ptr %ap2, ptr %ap) +// CHECK-NEXT: call void @llvm.va_copy.p0(ptr %ap2, ptr %ap) // AIX32-NEXT: %argp.cur1 = load ptr, ptr %ap2, align 4 // AIX32-NEXT: %argp.next2 = getelementptr inbounds i8, ptr %argp.cur1, i32 4 @@ -62,14 +62,14 @@ void testva (int n, ...) { // AIX64-NEXT: %1 = load i32, ptr %0, align 4 // AIX64-NEXT: store i32 %1, ptr %v, align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr %ap2) -// CHECK-NEXT: call void @llvm.va_end(ptr %ap) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr %ap2) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr %ap) // CHECK-NEXT: ret void -// CHECK: declare void @llvm.va_start(ptr) +// CHECK: declare void @llvm.va_start.p0(ptr) // AIX32: declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) // AIX64: declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) -// CHECK: declare void @llvm.va_copy(ptr, ptr) -// CHECK: declare void @llvm.va_end(ptr) +// CHECK: declare void @llvm.va_copy.p0(ptr, ptr) +// CHECK: declare void @llvm.va_end.p0(ptr) diff --git a/clang/test/CodeGen/PowerPC/ppc64le-varargs-f128.c b/clang/test/CodeGen/PowerPC/ppc64le-varargs-f128.c index 396614fe5bac2f326cda066041562370082f8fb3..2f5459d1bb9c4c14d347a8cd403c7d169acd3317 100644 --- a/clang/test/CodeGen/PowerPC/ppc64le-varargs-f128.c +++ b/clang/test/CodeGen/PowerPC/ppc64le-varargs-f128.c @@ -31,7 +31,7 @@ void foo_ls(ldbl128_s); // OMP-TARGET: call void @foo_ld(ppc_fp128 noundef %[[V3]]) // OMP-HOST-LABEL: define{{.*}} void @omp( -// OMP-HOST: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// OMP-HOST: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // OMP-HOST: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]], align 8 // OMP-HOST: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // OMP-HOST: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) @@ -49,13 +49,13 @@ void omp(int n, ...) { } // IEEE-LABEL: define{{.*}} void @f128 -// IEEE: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// IEEE: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // IEEE: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]] // IEEE: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // IEEE: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) // IEEE: %[[V4:[0-9a-zA-Z_.]+]] = load fp128, ptr %[[ALIGN]], align 16 // IEEE: call void @foo_fq(fp128 noundef %[[V4]]) -// IEEE: call void @llvm.va_end(ptr %[[AP]]) +// IEEE: call void @llvm.va_end.p0(ptr %[[AP]]) void f128(int n, ...) { va_list ap; va_start(ap, n); @@ -64,20 +64,20 @@ void f128(int n, ...) { } // IEEE-LABEL: define{{.*}} void @long_double -// IEEE: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// IEEE: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // IEEE: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]] // IEEE: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // IEEE: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) // IEEE: %[[V4:[0-9a-zA-Z_.]+]] = load fp128, ptr %[[ALIGN]], align 16 // IEEE: call void @foo_ld(fp128 noundef %[[V4]]) -// IEEE: call void @llvm.va_end(ptr %[[AP]]) +// IEEE: call void @llvm.va_end.p0(ptr %[[AP]]) // IBM-LABEL: define{{.*}} void @long_double -// IBM: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// IBM: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // IBM: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]] // IBM: %[[V4:[0-9a-zA-Z_.]+]] = load ppc_fp128, ptr %[[CUR]], align 8 // IBM: call void @foo_ld(ppc_fp128 noundef %[[V4]]) -// IBM: call void @llvm.va_end(ptr %[[AP]]) +// IBM: call void @llvm.va_end.p0(ptr %[[AP]]) void long_double(int n, ...) { va_list ap; va_start(ap, n); @@ -86,7 +86,7 @@ void long_double(int n, ...) { } // IEEE-LABEL: define{{.*}} void @long_double_struct -// IEEE: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// IEEE: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // IEEE: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]] // IEEE: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // IEEE: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) @@ -96,7 +96,7 @@ void long_double(int n, ...) { // IEEE: %[[COERCE:[0-9a-zA-Z_.]+]] = getelementptr inbounds %struct.ldbl128_s, ptr %[[TMP]], i32 0, i32 0 // IEEE: %[[V4:[0-9a-zA-Z_.]+]] = load fp128, ptr %[[COERCE]], align 16 // IEEE: call void @foo_ls(fp128 inreg %[[V4]]) -// IEEE: call void @llvm.va_end(ptr %[[AP]]) +// IEEE: call void @llvm.va_end.p0(ptr %[[AP]]) void long_double_struct(int n, ...) { va_list ap; va_start(ap, n); diff --git a/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c b/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c index 35d6973818d01c0e4134616a2706869505463711..b303d71304bf3ece9b14905e395618055f66a48a 100644 --- a/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c +++ b/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c @@ -2,6 +2,28 @@ // RUN: not %clang_cc1 -triple riscv64 -target-feature +zifencei -target-feature +m -target-feature +a \ // RUN: -emit-llvm %s 2>&1 | FileCheck %s +#include + +void test_builtin() { +// CHECK: error: '__builtin_rvv_vsetvli' needs target feature zve32x + __riscv_vsetvl_e8m8(1); +} + +void test_rvv_i32_type() { +// CHECK: error: RISC-V type 'vint32m1_t' (aka '__rvv_int32m1_t') requires the 'zve32x' extension + vint32m1_t v; +} + +void test_rvv_f32_type() { +// CHECK: error: RISC-V type 'vfloat32m1_t' (aka '__rvv_float32m1_t') requires the 'zve32f' extension + vfloat32m1_t v; +} + +void test_rvv_f64_type() { +// CHECK: error: RISC-V type 'vfloat64m1_t' (aka '__rvv_float64m1_t') requires the 'zve64d' extension + vfloat64m1_t v; +} + // CHECK: error: duplicate 'arch=' in the 'target' attribute string; __attribute__((target("arch=rv64gc;arch=rv64gc_zbb"))) void testMultiArchSelectLast() {} // CHECK: error: duplicate 'cpu=' in the 'target' attribute string; diff --git a/clang/test/CodeGen/RISCV/riscv-func-attr-target.c b/clang/test/CodeGen/RISCV/riscv-func-attr-target.c index f216eaf735b4a8546c95008f4bd573225d1ad984..1f8682179ea813886c1a1d9f82dfa134f1f844d9 100644 --- a/clang/test/CodeGen/RISCV/riscv-func-attr-target.c +++ b/clang/test/CodeGen/RISCV/riscv-func-attr-target.c @@ -4,6 +4,8 @@ // RUN: -target-feature -relax -target-feature -zfa \ // RUN: -emit-llvm %s -o - | FileCheck %s +#include + // CHECK-LABEL: define dso_local void @testDefault // CHECK-SAME: () #0 { void testDefault() {} @@ -35,6 +37,34 @@ testAttrFullArchAndAttrCpu() {} // CHECK-SAME: () #8 { __attribute__((target("cpu=sifive-u54"))) void testAttrCpuOnly() {} +__attribute__((target("arch=+zve32x"))) +void test_builtin_w_zve32x() { +// CHECK-LABEL: test_builtin_w_zve32x +// CHECK-SAME: #9 + __riscv_vsetvl_e8m8(1); +} + +__attribute__((target("arch=+zve32x"))) +void test_rvv_i32_type_w_zve32x() { +// CHECK-LABEL: test_rvv_i32_type_w_zve32x +// CHECK-SAME: #9 + vint32m1_t v; +} + +__attribute__((target("arch=+zve32f"))) +void test_rvv_f32_type_w_zve32f() { +// CHECK-LABEL: test_rvv_f32_type_w_zve32f +// CHECK-SAME: #11 + vfloat32m1_t v; +} + +__attribute__((target("arch=+zve64d"))) +void test_rvv_f64_type_w_zve64d() { +// CHECK-LABEL: test_rvv_f64_type_w_zve64d +// CHECK-SAME: #12 + vfloat64m1_t v; +} + //. // CHECK: attributes #0 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zifencei,-relax,-zbb,-zfa" } // CHECK: attributes #1 = { {{.*}}"target-cpu"="rocket-rv64" "target-features"="+64bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zbb,-zfa" "tune-cpu"="generic-rv64" } @@ -46,3 +76,6 @@ __attribute__((target("cpu=sifive-u54"))) void testAttrCpuOnly() {} // CHECK: attributes #6 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei,-relax,-zfa" } // CHECK: attributes #7 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+m,+save-restore,{{(-[[:alnum:]-]+)(,-[[:alnum:]-]+)*}}" } // CHECK: attributes #8 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zicsr,+zifencei,{{(-[[:alnum:]-]+)(,-[[:alnum:]-]+)*}}" } +// CHECK: attributes #9 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zicsr,+zifencei,+zve32x,+zvl32b,-relax,-zbb,-zfa" } +// CHECK: attributes #11 = { {{.*}}"target-features"="+64bit,+a,+f,+m,+save-restore,+zicsr,+zifencei,+zve32f,+zve32x,+zvl32b,-relax,-zbb,-zfa" } +// CHECK: attributes #12 = { {{.*}}"target-features"="+64bit,+a,+d,+f,+m,+save-restore,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl32b,+zvl64b,-relax,-zbb,-zfa" } diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c new file mode 100644 index 0000000000000000000000000000000000000000..072d8a863d45705b7faacb0fa8f6abecea0655eb --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c @@ -0,0 +1,34 @@ +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +v \ +// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s +// RUN: %clang_cc1 -std=c23 -triple riscv64 -target-feature +v \ +// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s + +#include + +// CHECK-LLVM: call riscv_vector_cc @bar +vint32m1_t __attribute__((riscv_vector_cc)) bar(vint32m1_t input); +vint32m1_t test_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = bar(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} + +// CHECK-LLVM: call riscv_vector_cc @bar +[[riscv::vector_cc]] vint32m1_t bar(vint32m1_t input); +vint32m1_t test_vector_cc_attr2(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = bar(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} + +// CHECK-LLVM: call @baz +vint32m1_t baz(vint32m1_t input); +vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = baz(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c01aeb21f675714d328f375853671099e1789371 --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp @@ -0,0 +1,32 @@ +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -std=c++11 -triple riscv64 -target-feature +v \ +// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s + +#include + +// CHECK-LLVM: call riscv_vector_cc @_Z3baru15__rvv_int32m1_t +vint32m1_t __attribute__((riscv_vector_cc)) bar(vint32m1_t input); +vint32m1_t test_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = bar(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} + +// CHECK-LLVM: call riscv_vector_cc @_Z3baru15__rvv_int32m1_t +[[riscv::vector_cc]] vint32m1_t bar(vint32m1_t input); +vint32m1_t test_vector_cc_attr2(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = bar(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} + +// CHECK-LLVM: call @_Z3bazu15__rvv_int32m1_t +vint32m1_t baz(vint32m1_t input); +vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = baz(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c new file mode 100644 index 0000000000000000000000000000000000000000..5c35901799b4276b8959003d904d5b210519645f --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 %s -std=c23 -triple riscv64 -target-feature +v -verify + +__attribute__((riscv_vector_cc)) int var; // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'int'}} + +__attribute__((riscv_vector_cc)) void func(); +__attribute__((riscv_vector_cc(1))) void func_invalid(); // expected-error {{'riscv_vector_cc' attribute takes no arguments}} + +void test_no_attribute(int); // expected-note {{previous declaration is here}} +void __attribute__((riscv_vector_cc)) test_no_attribute(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}} + +[[riscv::vector_cc]] int var2; // expected-warning {{'vector_cc' only applies to function types; type here is 'int'}} + +[[riscv::vector_cc]] void func2(); +[[riscv::vector_cc(1)]] void func_invalid2(); // expected-error {{'vector_cc' attribute takes no arguments}} + +void test_no_attribute2(int); // expected-note {{previous declaration is here}} +[[riscv::vector_cc]] void test_no_attribute2(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}} diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..264bb7d9ad7c00172a2c3dc9d5dcfa535054fe64 --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 %s -triple riscv64 -target-feature +v -verify + +__attribute__((riscv_vector_cc)) int var; // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'int'}} + +__attribute__((riscv_vector_cc)) void func(); +__attribute__((riscv_vector_cc(1))) void func_invalid(); // expected-error {{'riscv_vector_cc' attribute takes no arguments}} + +void test_no_attribute(int); // expected-note {{previous declaration is here}} +void __attribute__((riscv_vector_cc)) test_no_attribute(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}} + +class test_cc { + __attribute__((riscv_vector_cc)) void member_func(); +}; + +void test_lambda() { + __attribute__((riscv_vector_cc)) auto lambda = []() { // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'auto'}} + }; +} + +[[riscv::vector_cc]] int var2; // expected-warning {{'vector_cc' only applies to function types; type here is 'int'}} + +[[riscv::vector_cc]] void func2(); +[[riscv::vector_cc(1)]] void func_invalid2(); // expected-error {{'vector_cc' attribute takes no arguments}} + +void test_no_attribute2(int); // expected-note {{previous declaration is here}} +[[riscv::vector_cc]] void test_no_attribute2(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}} + +class test_cc2 { + [[riscv::vector_cc]] void member_func(); +}; + +void test_lambda2() { + [[riscv::vector_cc]] auto lambda = []() { // expected-warning {{'vector_cc' only applies to function types; type here is 'auto'}} + }; +} diff --git a/clang/test/CodeGen/RISCV/riscv32-vararg.c b/clang/test/CodeGen/RISCV/riscv32-vararg.c index 1c4e41f2f54c8f77d632f5a251c81691bb5a67b2..00e04eb894675eb68b2174a66a276c2f1ca9355d 100644 --- a/clang/test/CodeGen/RISCV/riscv32-vararg.c +++ b/clang/test/CodeGen/RISCV/riscv32-vararg.c @@ -80,13 +80,13 @@ void f_va_caller(void) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 4 // CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] // @@ -111,7 +111,7 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32F-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-ILP32F-NEXT: [[V:%.*]] = alloca double, align 8 // CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32F-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-ILP32F-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -119,7 +119,7 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP1:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED]], align 8 // CHECK-ILP32F-NEXT: store double [[TMP1]], ptr [[V]], align 8 -// CHECK-ILP32F-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[TMP2:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32F-NEXT: ret double [[TMP2]] // @@ -130,7 +130,7 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32D-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-ILP32D-NEXT: [[V:%.*]] = alloca double, align 8 // CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32D-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-ILP32D-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -138,7 +138,7 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP1:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED]], align 8 // CHECK-ILP32D-NEXT: store double [[TMP1]], ptr [[V]], align 8 -// CHECK-ILP32D-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[TMP2:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32D-NEXT: ret double [[TMP2]] // @@ -149,13 +149,13 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32E-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-ILP32E-NEXT: [[V:%.*]] = alloca double, align 8 // CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32E-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8 // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[TMP0:%.*]] = load double, ptr [[ARGP_CUR]], align 4 // CHECK-ILP32E-NEXT: store double [[TMP0]], ptr [[V]], align 8 -// CHECK-ILP32E-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[TMP1:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32E-NEXT: ret double [[TMP1]] // @@ -180,7 +180,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32F-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-ILP32F-NEXT: [[X:%.*]] = alloca double, align 8 // CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32F-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-ILP32F-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -200,7 +200,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP4:%.*]] = load double, ptr [[ARGP_CUR3_ALIGNED]], align 8 // CHECK-ILP32F-NEXT: store double [[TMP4]], ptr [[X]], align 8 -// CHECK-ILP32F-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[TMP5:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32F-NEXT: [[TMP6:%.*]] = load double, ptr [[X]], align 8 // CHECK-ILP32F-NEXT: [[ADD:%.*]] = fadd double [[TMP5]], [[TMP6]] @@ -215,7 +215,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32D-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-ILP32D-NEXT: [[X:%.*]] = alloca double, align 8 // CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32D-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-ILP32D-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -235,7 +235,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP4:%.*]] = load double, ptr [[ARGP_CUR3_ALIGNED]], align 8 // CHECK-ILP32D-NEXT: store double [[TMP4]], ptr [[X]], align 8 -// CHECK-ILP32D-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[TMP5:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32D-NEXT: [[TMP6:%.*]] = load double, ptr [[X]], align 8 // CHECK-ILP32D-NEXT: [[ADD:%.*]] = fadd double [[TMP5]], [[TMP6]] @@ -250,7 +250,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32E-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-ILP32E-NEXT: [[X:%.*]] = alloca double, align 8 // CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32E-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8 // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -266,7 +266,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[TMP2:%.*]] = load double, ptr [[ARGP_CUR3]], align 4 // CHECK-ILP32E-NEXT: store double [[TMP2]], ptr [[X]], align 8 -// CHECK-ILP32E-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[TMP3:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32E-NEXT: [[TMP4:%.*]] = load double, ptr [[X]], align 8 // CHECK-ILP32E-NEXT: [[ADD:%.*]] = fadd double [[TMP3]], [[TMP4]] @@ -296,7 +296,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32F-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4 // CHECK-ILP32F-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32F-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -321,7 +321,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4 // CHECK-ILP32F-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false) -// CHECK-ILP32F-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4 // CHECK-ILP32F-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128 // CHECK-ILP32F-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16 @@ -384,7 +384,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32D-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4 // CHECK-ILP32D-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32D-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -409,7 +409,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4 // CHECK-ILP32D-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false) -// CHECK-ILP32D-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4 // CHECK-ILP32D-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128 // CHECK-ILP32D-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16 @@ -472,7 +472,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32E-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4 // CHECK-ILP32E-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32E-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -497,7 +497,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4 // CHECK-ILP32E-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false) -// CHECK-ILP32E-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4 // CHECK-ILP32E-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128 // CHECK-ILP32E-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16 diff --git a/clang/test/CodeGen/RISCV/riscv64-vararg.c b/clang/test/CodeGen/RISCV/riscv64-vararg.c index 634cde61320cb61e894ba386ba8813213371677a..efdffa2687e624125bcd882ff3b56c0cfccb3580 100644 --- a/clang/test/CodeGen/RISCV/riscv64-vararg.c +++ b/clang/test/CodeGen/RISCV/riscv64-vararg.c @@ -135,13 +135,13 @@ void f_va_caller(void) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 8 // CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] // @@ -166,7 +166,7 @@ int f_va_1(char *fmt, ...) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[V:%.*]] = alloca fp128, align 16 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15 // CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP0]], i64 -16) @@ -174,7 +174,7 @@ int f_va_1(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load fp128, ptr [[ARGP_CUR_ALIGNED]], align 16 // CHECK-NEXT: store fp128 [[TMP1]], ptr [[V]], align 16 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP2:%.*]] = load fp128, ptr [[V]], align 16 // CHECK-NEXT: ret fp128 [[TMP2]] // @@ -199,7 +199,7 @@ long double f_va_2(char *fmt, ...) { // CHECK-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[X:%.*]] = alloca fp128, align 16 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15 // CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP0]], i64 -16) @@ -219,7 +219,7 @@ long double f_va_2(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP4:%.*]] = load fp128, ptr [[ARGP_CUR3_ALIGNED]], align 16 // CHECK-NEXT: store fp128 [[TMP4]], ptr [[X]], align 16 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP5:%.*]] = load fp128, ptr [[V]], align 16 // CHECK-NEXT: [[TMP6:%.*]] = load fp128, ptr [[X]], align 16 // CHECK-NEXT: [[ADD:%.*]] = fadd fp128 [[TMP5]], [[TMP6]] @@ -248,7 +248,7 @@ long double f_va_3(char *fmt, ...) { // CHECK-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 8 // CHECK-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8 @@ -267,7 +267,7 @@ long double f_va_3(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT6]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR5]], align 8 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[LS]], ptr align 8 [[TMP1]], i64 32, i1 false) -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 0 // CHECK-NEXT: [[TMP2:%.*]] = load i16, ptr [[A]], align 2 // CHECK-NEXT: [[CONV:%.*]] = zext i16 [[TMP2]] to i64 diff --git a/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb-error.c b/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb-error.c index ecf090a128aac702d3ea6cb25fc5c4c1ed0827ab..bad68504fab055719a27dc19e6260952a5c67252 100644 --- a/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb-error.c +++ b/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb-error.c @@ -1,6 +1,6 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple riscv32 -target-feature +zbb -verify %s -o - +// RUN: %clang_cc1 -triple riscv32 -target-feature +zbb -S -verify %s -o - unsigned int orc_b_64(unsigned int a) { - return __builtin_riscv_orc_b_64(a); // expected-error {{builtin requires: 'RV64'}} + return __builtin_riscv_orc_b_64(a); // expected-error {{'__builtin_riscv_orc_b_64' needs target feature zbb,64bit}} } diff --git a/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbkb-error.c b/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbkb-error.c index d2e3e76043aef16304ff7ad0ad73709182d9a55c..a256bf75b031c6ddc13204bee185d5b087a4b03c 100644 --- a/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbkb-error.c +++ b/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbkb-error.c @@ -1,14 +1,10 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple riscv64 -target-feature +zbkb -verify %s -o - +// RUN: %clang_cc1 -triple riscv64 -target-feature +zbkb -S -verify %s -o - #include -uint32_t zip(uint32_t rs1) +uint32_t zip_unzip(uint32_t rs1) { - return __builtin_riscv_zip_32(rs1); // expected-error {{builtin requires: 'RV32'}} -} - -uint32_t unzip(uint32_t rs1) -{ - return __builtin_riscv_unzip_32(rs1); // expected-error {{builtin requires: 'RV32'}} + (void)__builtin_riscv_zip_32(rs1); // expected-error {{'__builtin_riscv_zip_32' needs target feature zbkb,32bit}} + return __builtin_riscv_unzip_32(rs1); // expected-error {{'__builtin_riscv_unzip_32' needs target feature zbkb,32bit}} } diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c index 6ec9b057997690a919a39da38a85e31372af0ffe..ecb6c5f27025779aafbdbd96606137f34cb2a60f 100644 --- a/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c @@ -11,7 +11,7 @@ // CHECK-RV64V-NEXT: ret i32 [[CONV]] // -// CHECK-RV64-ERR: error: builtin requires at least one of the following extensions: 'Zve32x' +// CHECK-RV64-ERR: error: '__builtin_rvv_vsetvli' needs target feature zve32x int test() { return __builtin_rvv_vsetvli(1, 0, 0); diff --git a/clang/test/CodeGen/WebAssembly/wasm-varargs.c b/clang/test/CodeGen/WebAssembly/wasm-varargs.c index c475de19ae4487830f9f8f76d2cea5906819fd35..e794857304e1c9eab782ab9c817b0810f73b31cc 100644 --- a/clang/test/CodeGen/WebAssembly/wasm-varargs.c +++ b/clang/test/CodeGen/WebAssembly/wasm-varargs.c @@ -10,13 +10,13 @@ // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 4 // CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] // @@ -38,7 +38,7 @@ int test_i32(char *fmt, ...) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[V:%.*]] = alloca i64, align 8 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -46,7 +46,7 @@ int test_i32(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[ARGP_CUR_ALIGNED]], align 8 // CHECK-NEXT: store i64 [[TMP1]], ptr [[V]], align 8 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[V]], align 8 // CHECK-NEXT: ret i64 [[TMP2]] // @@ -73,13 +73,13 @@ struct S { // CHECK-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_RESULT]], ptr align 4 [[TMP0]], i32 12, i1 false) -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: ret void // struct S test_struct(char *fmt, ...) { @@ -102,7 +102,7 @@ struct Z {}; // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[U:%.*]] = alloca [[STRUCT_Z:%.*]], align 1 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 0 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -112,7 +112,7 @@ struct Z {}; // CHECK-NEXT: store ptr [[ARGP_NEXT2]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARGP_CUR1]], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_RESULT]], ptr align 4 [[TMP0]], i32 12, i1 false) -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: ret void // struct S test_empty_struct(char *fmt, ...) { diff --git a/clang/test/CodeGen/X86/va-arg-sse.c b/clang/test/CodeGen/X86/va-arg-sse.c index e040b0e5790bd17c92381059d1a657fea6eeeb6d..b7d00dad1453d3b97297104733f8ac315bde71a4 100644 --- a/clang/test/CodeGen/X86/va-arg-sse.c +++ b/clang/test/CodeGen/X86/va-arg-sse.c @@ -21,7 +21,7 @@ struct S a[5]; // CHECK-NEXT: store i32 0, ptr [[J]], align 4 // CHECK-NEXT: store i32 0, ptr [[K]], align 4 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[AP]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) // CHECK-NEXT: store ptr getelementptr inbounds ([5 x %struct.S], ptr @a, i64 0, i64 2), ptr [[P]], align 8 // CHECK-NEXT: [[ARRAYDECAY2:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[AP]], i64 0, i64 0 // CHECK-NEXT: [[FP_OFFSET_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY2]], i32 0, i32 1 @@ -52,7 +52,7 @@ struct S a[5]; // CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ] // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[ARG]], ptr align 4 [[VAARG_ADDR]], i64 12, i1 false) // CHECK-NEXT: [[ARRAYDECAY3:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[AP]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_end(ptr [[ARRAYDECAY3]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[ARRAYDECAY3]]) // CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[P]], align 8 // CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[TMP15]], null // CHECK-NEXT: br i1 [[TOBOOL]], label [[LAND_LHS_TRUE:%.*]], label [[IF_END:%.*]] diff --git a/clang/test/CodeGen/X86/x86_64-vaarg.c b/clang/test/CodeGen/X86/x86_64-vaarg.c new file mode 100644 index 0000000000000000000000000000000000000000..07c6df14a0b812061219e21cf2189e9b9a797e7a --- /dev/null +++ b/clang/test/CodeGen/X86/x86_64-vaarg.c @@ -0,0 +1,69 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s + + +typedef struct { struct {} a; } empty; + +// CHECK-LABEL: define dso_local void @empty_record_test( +// CHECK-SAME: i32 noundef [[Z:%.*]], ...) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1 +// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_EMPTY]], align 1 +// CHECK-NEXT: store i32 [[Z]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[RETVAL]], ptr align 1 [[TMP]], i64 0, i1 false) +// CHECK-NEXT: ret void +// +empty empty_record_test(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, empty); +} + +typedef struct { + struct{} a; + double b; +} s1; + +// CHECK-LABEL: define dso_local double @f( +// CHECK-SAME: i32 noundef [[Z:%.*]], ...) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 +// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT: store i32 [[Z]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT: [[FP_OFFSET_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 1 +// CHECK-NEXT: [[FP_OFFSET:%.*]] = load i32, ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT: [[FITS_IN_FP:%.*]] = icmp ule i32 [[FP_OFFSET]], 160 +// CHECK-NEXT: br i1 [[FITS_IN_FP]], label [[VAARG_IN_REG:%.*]], label [[VAARG_IN_MEM:%.*]] +// CHECK: vaarg.in_reg: +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 +// CHECK-NEXT: [[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] +// CHECK-NEXT: [[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT: br label [[VAARG_END:%.*]] +// CHECK: vaarg.in_mem: +// CHECK-NEXT: [[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2 +// CHECK-NEXT: [[OVERFLOW_ARG_AREA:%.*]] = load ptr, ptr [[OVERFLOW_ARG_AREA_P]], align 8 +// CHECK-NEXT: [[OVERFLOW_ARG_AREA_NEXT:%.*]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i32 8 +// CHECK-NEXT: store ptr [[OVERFLOW_ARG_AREA_NEXT]], ptr [[OVERFLOW_ARG_AREA_P]], align 8 +// CHECK-NEXT: br label [[VAARG_END]] +// CHECK: vaarg.end: +// CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP1]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[VAARG_ADDR]], i64 8, i1 false) +// CHECK-NEXT: [[TMP3:%.*]] = load double, ptr [[RETVAL]], align 8 +// CHECK-NEXT: ret double [[TMP3]] +// +s1 f(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, s1); +} diff --git a/clang/test/CodeGen/aarch64-ABI-align-packed.c b/clang/test/CodeGen/aarch64-ABI-align-packed.c index 2b029f6458956758892c07b2ac89d70bb200f16e..13c68fe54b849fe03ee3c9a061c4e4a90e91f249 100644 --- a/clang/test/CodeGen/aarch64-ABI-align-packed.c +++ b/clang/test/CodeGen/aarch64-ABI-align-packed.c @@ -73,7 +73,7 @@ __attribute__((noinline)) void named_arg_non_packed_struct(double d0, double d1, // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6:[0-9]+]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_non_packed_struct(double d0, double d1, double d2, double d3, @@ -128,7 +128,7 @@ __attribute__((noinline)) void named_arg_packed_struct(double d0, double d1, dou // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_packed_struct(double d0, double d1, double d2, double d3, @@ -183,7 +183,7 @@ __attribute__((noinline)) void named_arg_packed_member(double d0, double d1, dou // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_packed_member(double d0, double d1, double d2, double d3, @@ -238,7 +238,7 @@ __attribute__((noinline)) void named_arg_aligned_struct_8(double d0, double d1, // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_aligned_struct_8(double d0, double d1, double d2, double d3, @@ -293,7 +293,7 @@ __attribute__((noinline)) void named_arg_aligned_member_8(double d0, double d1, // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_aligned_member_8(double d0, double d1, double d2, double d3, @@ -348,7 +348,7 @@ __attribute__((noinline)) void named_arg_pragma_packed_struct_8(double d0, doubl // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_pragma_packed_struct_8(double d0, double d1, double d2, double d3, @@ -403,7 +403,7 @@ __attribute__((noinline)) void named_arg_pragma_packed_struct_4(double d0, doubl // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_pragma_packed_struct_4(double d0, double d1, double d2, double d3, diff --git a/clang/test/CodeGen/aarch64-mixed-target-attributes.c b/clang/test/CodeGen/aarch64-mixed-target-attributes.c new file mode 100644 index 0000000000000000000000000000000000000000..aef6ce36ab1c05a09c03f04dfd267423dc9cb118 --- /dev/null +++ b/clang/test/CodeGen/aarch64-mixed-target-attributes.c @@ -0,0 +1,278 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals --include-generated-funcs +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -v9.5a -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fmv -S -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-NOFMV + +// The following is guarded because in NOFMV we get an error for redefining the default. +#ifdef __HAVE_FUNCTION_MULTI_VERSIONING +int explicit_default(void) { return 0; } +__attribute__((target_version("jscvt"))) int explicit_default(void) { return 1; } +__attribute__((target_clones("dotprod", "lse"))) int explicit_default(void) { return 2; } +__attribute__((target_version("rdma"))) int explicit_default(void) { return 3; } + +int foo(void) { return explicit_default(); } +#endif + +__attribute__((target_version("jscvt"))) int implicit_default(void) { return 1; } +__attribute__((target_clones("dotprod", "lse"))) int implicit_default(void) { return 2; } +__attribute__((target_version("rdma"))) int implicit_default(void) { return 3; } + +int bar(void) { return implicit_default(); } + +// These shouldn't generate anything. +int unused_version_declarations(void); +__attribute__((target_clones("dotprod", "lse"))) int unused_version_declarations(void); +__attribute__((target_version("jscvt"))) 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_clones("dotprod", "lse"))) int default_def_with_version_decls(void); +__attribute__((target_version("jscvt"))) int default_def_with_version_decls(void); + +//. +// CHECK: @__aarch64_cpu_features = external dso_local global { i64 } +// CHECK: @explicit_default.ifunc = weak_odr alias i32 (), ptr @explicit_default +// CHECK: @implicit_default.ifunc = weak_odr alias i32 (), ptr @implicit_default +// CHECK: @default_def_with_version_decls.ifunc = weak_odr alias i32 (), ptr @default_def_with_version_decls +// CHECK: @explicit_default = weak_odr ifunc i32 (), ptr @explicit_default.resolver +// CHECK: @implicit_default = weak_odr ifunc i32 (), ptr @implicit_default.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 {{[^@]+}}@explicit_default.default +// CHECK-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 0 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@explicit_default._Mjscvt +// CHECK-SAME: () #[[ATTR1:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@explicit_default._Mdotprod +// CHECK-SAME: () #[[ATTR2:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@explicit_default._Mlse +// CHECK-SAME: () #[[ATTR3:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK-LABEL: define {{[^@]+}}@explicit_default.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 @explicit_default._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 @explicit_default._Mrdm +// CHECK: resolver_else2: +// CHECK-NEXT: [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP8]], 16 +// CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 16 +// CHECK-NEXT: [[TMP11:%.*]] = and i1 true, [[TMP10]] +// CHECK-NEXT: br i1 [[TMP11]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]] +// CHECK: resolver_return3: +// CHECK-NEXT: ret ptr @explicit_default._Mdotprod +// CHECK: resolver_else4: +// CHECK-NEXT: [[TMP12:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = and i64 [[TMP12]], 128 +// CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[TMP13]], 128 +// CHECK-NEXT: [[TMP15:%.*]] = and i1 true, [[TMP14]] +// CHECK-NEXT: br i1 [[TMP15]], label [[RESOLVER_RETURN5:%.*]], label [[RESOLVER_ELSE6:%.*]] +// CHECK: resolver_return5: +// CHECK-NEXT: ret ptr @explicit_default._Mlse +// CHECK: resolver_else6: +// CHECK-NEXT: ret ptr @explicit_default.default +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@explicit_default._Mrdm +// CHECK-SAME: () #[[ATTR4:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 3 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@foo +// CHECK-SAME: () #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = call i32 @explicit_default() +// CHECK-NEXT: ret i32 [[CALL]] +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@implicit_default._Mjscvt +// CHECK-SAME: () #[[ATTR1]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@implicit_default._Mdotprod +// CHECK-SAME: () #[[ATTR2]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@implicit_default._Mlse +// CHECK-SAME: () #[[ATTR3]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK-LABEL: define {{[^@]+}}@implicit_default.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 @implicit_default._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 @implicit_default._Mrdm +// CHECK: resolver_else2: +// CHECK-NEXT: [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP8]], 16 +// CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 16 +// CHECK-NEXT: [[TMP11:%.*]] = and i1 true, [[TMP10]] +// CHECK-NEXT: br i1 [[TMP11]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]] +// CHECK: resolver_return3: +// CHECK-NEXT: ret ptr @implicit_default._Mdotprod +// CHECK: resolver_else4: +// CHECK-NEXT: [[TMP12:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = and i64 [[TMP12]], 128 +// CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[TMP13]], 128 +// CHECK-NEXT: [[TMP15:%.*]] = and i1 true, [[TMP14]] +// CHECK-NEXT: br i1 [[TMP15]], label [[RESOLVER_RETURN5:%.*]], label [[RESOLVER_ELSE6:%.*]] +// CHECK: resolver_return5: +// CHECK-NEXT: ret ptr @implicit_default._Mlse +// CHECK: resolver_else6: +// CHECK-NEXT: ret ptr @implicit_default.default +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@implicit_default._Mrdm +// CHECK-SAME: () #[[ATTR4]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 3 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@bar +// CHECK-SAME: () #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = call i32 @implicit_default() +// CHECK-NEXT: ret i32 [[CALL]] +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@default_def_with_version_decls.default +// CHECK-SAME: () #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 0 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@implicit_default.default +// CHECK-SAME: () #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// 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]], 16 +// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 16 +// 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._Mdotprod +// CHECK: resolver_else2: +// CHECK-NEXT: [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP8]], 128 +// CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 128 +// CHECK-NEXT: [[TMP11:%.*]] = and i1 true, [[TMP10]] +// CHECK-NEXT: br i1 [[TMP11]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]] +// CHECK: resolver_return3: +// CHECK-NEXT: ret ptr @default_def_with_version_decls._Mlse +// CHECK: resolver_else4: +// CHECK-NEXT: ret ptr @default_def_with_version_decls.default +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@implicit_default +// CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: ret i32 2 +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@bar +// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @implicit_default() +// CHECK-NOFMV-NEXT: ret i32 [[CALL]] +// +// +// 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"="-v9.5a" } +// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+jsconv,+neon,-v9.5a" } +// CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon,-v9.5a" } +// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,-v9.5a" } +// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm,-v9.5a" } +// CHECK: attributes #[[ATTR5:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon,-v9.5a" } +// CHECK: attributes #[[ATTR6:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+jsconv,+neon,-v9.5a" } +// CHECK: attributes #[[ATTR7:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-v9.5a" } +// CHECK: attributes #[[ATTR8:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,-v9.5a" } +//. +// CHECK-NOFMV: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" } +//. +// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} +// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} +//. +// CHECK-NOFMV: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} +// CHECK-NOFMV: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} +//. diff --git a/clang/test/CodeGen/aarch64-varargs.c b/clang/test/CodeGen/aarch64-varargs.c index 44b87029e7b3d3fe1e43edd2f32e302d24e19be3..ee4e88eda4ef44142f1afb0d44e73beb57bd5e60 100644 --- a/clang/test/CodeGen/aarch64-varargs.c +++ b/clang/test/CodeGen/aarch64-varargs.c @@ -837,7 +837,7 @@ void check_start(int n, ...) { va_list the_list; va_start(the_list, n); // CHECK: [[THE_LIST:%[a-z_0-9]+]] = alloca %struct.__va_list -// CHECK: call void @llvm.va_start(ptr [[THE_LIST]]) +// CHECK: call void @llvm.va_start.p0(ptr [[THE_LIST]]) } typedef struct {} empty; diff --git a/clang/test/CodeGen/arm-varargs.c b/clang/test/CodeGen/arm-varargs.c index f754c7f52e59046e5cf659023be5a58f282b792a..ab4ac46924e605d3d5b6c9d52f7fa9327d645acd 100644 --- a/clang/test/CodeGen/arm-varargs.c +++ b/clang/test/CodeGen/arm-varargs.c @@ -264,5 +264,5 @@ void check_start(int n, ...) { va_list the_list; va_start(the_list, n); // CHECK: [[THE_LIST:%[a-z0-9._]+]] = alloca %struct.__va_list -// CHECK: call void @llvm.va_start(ptr [[THE_LIST]]) +// CHECK: call void @llvm.va_start.p0(ptr [[THE_LIST]]) } 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-clones-aarch64.c b/clang/test/CodeGen/attr-target-clones-aarch64.c index 94095f9aa3e1f4e6f1f9d217e4d7ae3930c8f670..8c8b951e9118d7a421af644b726011b07895d890 100644 --- a/clang/test/CodeGen/attr-target-clones-aarch64.c +++ b/clang/test/CodeGen/attr-target-clones-aarch64.c @@ -29,8 +29,8 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // CHECK: @ftc_def.ifunc = weak_odr alias i32 (), ptr @ftc_def // CHECK: @ftc_dup1.ifunc = weak_odr alias i32 (), ptr @ftc_dup1 // CHECK: @ftc_dup2.ifunc = weak_odr alias i32 (), ptr @ftc_dup2 -// CHECK: @ftc_inline1.ifunc = weak_odr alias i32 (), ptr @ftc_inline1 // CHECK: @ftc_inline2.ifunc = weak_odr alias i32 (), ptr @ftc_inline2 +// CHECK: @ftc_inline1.ifunc = weak_odr alias i32 (), ptr @ftc_inline1 // CHECK: @ftc_inline3.ifunc = weak_odr alias i32 (), ptr @ftc_inline3 // CHECK: @ftc = weak_odr ifunc i32 (), ptr @ftc.resolver // CHECK: @ftc_def = weak_odr ifunc i32 (), ptr @ftc_def.resolver @@ -52,12 +52,6 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // CHECK-NEXT: ret i32 0 // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 0 -// -// // CHECK-LABEL: @ftc.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -92,12 +86,6 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // CHECK-NEXT: ret i32 1 // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_def.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 -// -// // CHECK-LABEL: @ftc_def.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -126,12 +114,6 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // CHECK-NEXT: ret i32 2 // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_dup1.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 -// -// // CHECK-LABEL: @ftc_dup1.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -158,12 +140,6 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // CHECK-NEXT: ret i32 3 // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_dup2.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 3 -// -// // CHECK-LABEL: @ftc_dup2.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -192,6 +168,12 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // // CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: @ftc_inline2._Mfp16( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: @ftc_direct( // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 4 @@ -287,45 +269,63 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_inline1._MrngMsimd( +// CHECK-LABEL: @ftc_inline2._MfcmaMsve2-bitperm( // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 +// CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_inline1._MpredresMrcpc( +// CHECK-LABEL: @ftc.default( // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 +// CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_inline1._Msve2-aesMwfxt( +// CHECK-LABEL: @ftc_def.default( // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_inline1.default( +// CHECK-LABEL: @ftc_dup1.default( // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 +// CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_inline2._Mfp16( +// CHECK-LABEL: @ftc_dup2.default( // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 +// CHECK-NEXT: ret i32 3 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_inline2._MfcmaMsve2-bitperm( +// CHECK-LABEL: @ftc_inline2.default( // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_inline2.default( +// CHECK-LABEL: @ftc_inline1._MrngMsimd( // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: @ftc_inline1._MpredresMrcpc( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: @ftc_inline1._Msve2-aesMwfxt( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: @ftc_inline1.default( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone @@ -406,16 +406,16 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) //. // CHECK: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+lse,+neon" } // CHECK: attributes #[[ATTR1:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2" } -// CHECK: attributes #[[ATTR2:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } -// CHECK: attributes #[[ATTR3:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+sha2" } -// CHECK: attributes #[[ATTR4:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+mte,+neon,+sha2" } -// CHECK: attributes #[[ATTR5:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" } -// CHECK: attributes #[[ATTR6:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+dotprod,+fp-armv8,+neon" } -// CHECK: attributes #[[ATTR7:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rand" } -// CHECK: attributes #[[ATTR8:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+predres,+rcpc" } -// CHECK: attributes #[[ATTR9:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+wfxt" } -// CHECK: attributes #[[ATTR10:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" } -// CHECK: attributes #[[ATTR11:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+complxnum,+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-bitperm" } +// CHECK: attributes #[[ATTR2:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+sha2" } +// CHECK: attributes #[[ATTR3:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+mte,+neon,+sha2" } +// CHECK: attributes #[[ATTR4:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" } +// CHECK: attributes #[[ATTR5:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+dotprod,+fp-armv8,+neon" } +// CHECK: attributes #[[ATTR6:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +// CHECK: attributes #[[ATTR7:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" } +// CHECK: attributes #[[ATTR8:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+complxnum,+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-bitperm" } +// CHECK: attributes #[[ATTR9:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rand" } +// CHECK: attributes #[[ATTR10:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+predres,+rcpc" } +// CHECK: attributes #[[ATTR11:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+wfxt" } // CHECK: attributes #[[ATTR12:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti" } // CHECK: attributes #[[ATTR13:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sb,+sve" } //. 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/CodeGen/cfi-check-attrs.c b/clang/test/CodeGen/cfi-check-attrs.c new file mode 100644 index 0000000000000000000000000000000000000000..375aa30074d8874b5a5ddae8c5b15652af10044a --- /dev/null +++ b/clang/test/CodeGen/cfi-check-attrs.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple arm-unknown-linux -funwind-tables=1 -fsanitize-cfi-cross-dso -emit-llvm -o - %s | FileCheck %s + +// CHECK: define weak {{.*}}void @__cfi_check({{.*}} [[ATTR:#[0-9]*]] + +// CHECK: attributes [[ATTR]] = {{.*}} uwtable(sync) diff --git a/clang/test/CodeGen/cfi-check-fail.c b/clang/test/CodeGen/cfi-check-fail.c index 2f12cee9dec6026b0c8b93c6ec10e54f57c1e9c7..15f6c77abf2b20a86154abfa11e67abc6f435b8b 100644 --- a/clang/test/CodeGen/cfi-check-fail.c +++ b/clang/test/CodeGen/cfi-check-fail.c @@ -72,7 +72,7 @@ void caller(void (*f)(void)) { // CHECK: [[CONT5]]: // CHECK: ret void -// CHECK: define weak void @__cfi_check(i64 %[[TYPE:.*]], ptr %[[ADDR:.*]], ptr %[[DATA:.*]]) align 4096 +// CHECK: define weak void @__cfi_check(i64 noundef %[[TYPE:.*]], ptr noundef %[[ADDR:.*]], ptr noundef %[[DATA:.*]]){{.*}} align 4096 // CHECK-NOT: } // CHECK: call void @__cfi_check_fail(ptr %[[DATA]], ptr %[[ADDR]]) // CHECK-NEXT: ret void diff --git a/clang/test/CodeGen/flexible-array-init.c b/clang/test/CodeGen/flexible-array-init.c index bae926da5feb0701a5a5f5ec0af2009ff6c65b32..15a30c15ac966effae52a0716a5ca4f8e2ccb5b1 100644 --- a/clang/test/CodeGen/flexible-array-init.c +++ b/clang/test/CodeGen/flexible-array-init.c @@ -3,9 +3,15 @@ struct { int x; int y[]; } a = { 1, 7, 11 }; // CHECK: @a ={{.*}} global { i32, [2 x i32] } { i32 1, [2 x i32] [i32 7, i32 11] } +struct { int y[]; } a1 = { 8, 12 }; +// CHECK: @a1 ={{.*}} global { [2 x i32] } { [2 x i32] [i32 8, i32 12] } + struct { int x; int y[]; } b = { 1, { 13, 15 } }; // CHECK: @b ={{.*}} global { i32, [2 x i32] } { i32 1, [2 x i32] [i32 13, i32 15] } +struct { int y[]; } b1 = { { 14, 16 } }; +// CHECK: @b1 ={{.*}} global { [2 x i32] } { [2 x i32] [i32 14, i32 16] } + // sizeof(c) == 8, so this global should be at least 8 bytes. struct { int x; char c; char y[]; } c = { 1, 2, { 13, 15 } }; // CHECK: @c ={{.*}} global { i32, i8, [2 x i8] } { i32 1, i8 2, [2 x i8] c"\0D\0F" } @@ -21,10 +27,79 @@ struct __attribute((packed, aligned(4))) { char a; int x; char z[]; } e = { 1, 2 struct { int x; char y[]; } f = { 1, { 13, 15 } }; // CHECK: @f ={{.*}} global <{ i32, [2 x i8] }> <{ i32 1, [2 x i8] c"\0D\0F" }> -union { - struct { - int a; - char b[]; - } x; -} in_union = {}; -// CHECK: @in_union ={{.*}} global %union.anon zeroinitializer +struct __attribute((packed)) { short a; char z[]; } g = { 2, { 11, 13, 15 } }; +// CHECK: @g ={{.*}} <{ i16, [3 x i8] }> <{ i16 2, [3 x i8] c"\0B\0D\0F" }>, + +// Last member is the potential flexible array, unnamed initializer skips it. +struct { int a; union { int b; short x; }; int c; int d; } h = {1, 2, {}, 3}; +// CHECK: @h = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } +struct { int a; union { int b; short x[0]; }; int c; int d; } h0 = {1, 2, {}, 3}; +// CHECK: @h0 = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } +struct { int a; union { int b; short x[1]; }; int c; int d; } h1 = {1, 2, {}, 3}; +// CHECK: @h1 = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } +struct { + int a; + union { + int b; + struct { + struct { } __ununsed; + short x[]; + }; + }; + int c; + int d; +} hiding = {1, 2, {}, 3}; +// CHECK: @hiding = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } +struct { int a; union { int b; short x[]; }; int c; int d; } hf = {1, 2, {}, 3}; +// CHECK: @hf = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } + +// First member is the potential flexible array, initialization requires braces. +struct { int a; union { short x; int b; }; int c; int d; } i = {1, 2, {}, 3}; +// CHECK: @i = global { i32, { i16, [2 x i8] }, i32, i32 } { i32 1, { i16, [2 x i8] } { i16 2, [2 x i8] undef }, i32 0, i32 3 } +struct { int a; union { short x[0]; int b; }; int c; int d; } i0 = {1, {}, 2, 3}; +// CHECK: @i0 = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 1, { [0 x i16], [4 x i8] } { [0 x i16] zeroinitializer, [4 x i8] undef }, i32 2, i32 3 } +struct { int a; union { short x[1]; int b; }; int c; int d; } i1 = {1, {2}, {}, 3}; +// CHECK: @i1 = global { i32, { [1 x i16], [2 x i8] }, i32, i32 } { i32 1, { [1 x i16], [2 x i8] } { [1 x i16] [i16 2], [2 x i8] undef }, i32 0, i32 3 } +struct { int a; union { short x[]; int b; }; int c; int d; } i_f = {4, {}, {}, 6}; +// CHECK: @i_f = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 4, { [0 x i16], [4 x i8] } { [0 x i16] zeroinitializer, [4 x i8] undef }, i32 0, i32 6 } + +// Named initializers; order doesn't matter. +struct { int a; union { int b; short x; }; int c; int d; } hn = {.a = 1, .x = 2, .c = 3}; +// CHECK: @hn = global { i32, { i16, [2 x i8] }, i32, i32 } { i32 1, { i16, [2 x i8] } { i16 2, [2 x i8] undef }, i32 3, i32 0 } +struct { int a; union { int b; short x[0]; }; int c; int d; } hn0 = {.a = 1, .x = {2}, .c = 3}; +// CHECK: @hn0 = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 1, { [0 x i16], [4 x i8] } { [0 x i16] zeroinitializer, [4 x i8] undef }, i32 3, i32 0 } +struct { int a; union { int b; short x[1]; }; int c; int d; } hn1 = {.a = 1, .x = {2}, .c = 3}; +// CHECK: @hn1 = global { i32, { [1 x i16], [2 x i8] }, i32, i32 } { i32 1, { [1 x i16], [2 x i8] } { [1 x i16] [i16 2], [2 x i8] undef }, i32 3, i32 0 } + +struct { char a[]; } empty_struct = {}; +// CHECK: @empty_struct ={{.*}} global %struct.anon{{.*}} zeroinitializer, align 1 + +struct { char a[]; } empty_struct0 = {0}; +// CHECK: @empty_struct0 = global { [1 x i8] } zeroinitializer, align 1 + +union { struct { int a; char b[]; }; } struct_in_union = {}; +// CHECK: @struct_in_union = global %union.anon{{.*}} zeroinitializer, align 4 + +union { struct { int a; char b[]; }; } struct_in_union0 = {0}; +// CHECK: @struct_in_union0 = global %union.anon{{.*}} zeroinitializer, align 4 + +union { int a; char b[]; } trailing_in_union = {}; +// CHECK: @trailing_in_union = global %union.anon{{.*}} zeroinitializer, align 4 + +union { int a; char b[]; } trailing_in_union0 = {0}; +// CHECK: @trailing_in_union0 = global %union.anon{{.*}} zeroinitializer, align 4 + +union { char a[]; } only_in_union = {}; +// CHECK: @only_in_union = global %union.anon{{.*}} zeroinitializer, align 1 + +union { char a[]; } only_in_union0 = {0}; +// CHECK: @only_in_union0 = global { [1 x i8] } zeroinitializer, align 1 + +union { char a[]; int b; } first_in_union = {}; +// CHECK: @first_in_union = global { [0 x i8], [4 x i8] } { [0 x i8] zeroinitializer, [4 x i8] undef }, align 4 + +union { char a[]; int b; } first_in_union0 = {0}; +// CHECK: @first_in_union0 = global { [1 x i8], [3 x i8] } { [1 x i8] zeroinitializer, [3 x i8] undef }, align 4 + +union { char a[]; int b; } first_in_union123 = { {1, 2, 3} }; +// CHECK: @first_in_union123 = global { [3 x i8], i8 } { [3 x i8] c"\01\02\03", i8 undef }, align 4 diff --git a/clang/test/CodeGen/flexible-array-init.cpp b/clang/test/CodeGen/flexible-array-init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d067a614e1afe5da1d8d9dc4fb08323cd175f745 --- /dev/null +++ b/clang/test/CodeGen/flexible-array-init.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -x c++ -emit-llvm -o - %s | FileCheck %s + +union _u { char a[]; } u = {}; +union _u0 { char a[]; } u0 = {0}; + +// CHECK: %union._u = type { [0 x i8] } + +// CHECK: @u = global %union._u zeroinitializer, align 1 +// CHECK: @u0 = global { [1 x i8] } zeroinitializer, align 1 + +union { char a[]; } z = {}; +// CHECK: @z = internal global %union.{{.*}} zeroinitializer, align 1 +union { char a[]; } z0 = {0}; +// CHECK: @z0 = internal global { [1 x i8] } zeroinitializer, align 1 + +/* C++ requires global anonymous unions have static storage, so we have to + reference them to keep them in the IR output. */ +char keep(int pick) +{ + if (pick) + return z.a[0]; + else + return z0.a[0]; +} diff --git a/clang/test/CodeGen/hexagon-linux-vararg.c b/clang/test/CodeGen/hexagon-linux-vararg.c index 033e72ab449d319991203fc6376343a38a4bd60b..84945e872d28bc8f0522cc35abb4b72aca795439 100644 --- a/clang/test/CodeGen/hexagon-linux-vararg.c +++ b/clang/test/CodeGen/hexagon-linux-vararg.c @@ -9,7 +9,7 @@ struct AAA { int d; }; -// CHECK: call void @llvm.va_start(ptr %arraydecay) +// CHECK: call void @llvm.va_start.p0(ptr %arraydecay) // CHECK: %arraydecay1 = getelementptr inbounds [1 x %struct.__va_list_tag], // ptr %ap, i32 0, i32 0 // CHECK: br label %vaarg.maybe_reg diff --git a/clang/test/CodeGen/mips-varargs.c b/clang/test/CodeGen/mips-varargs.c index 052aedd1cd1e2c7dbfecce85c417277f319db378..029f000c121a5b8c4b18d4e9d4fafa0cc6d4f8e6 100644 --- a/clang/test/CodeGen/mips-varargs.c +++ b/clang/test/CodeGen/mips-varargs.c @@ -29,7 +29,7 @@ int test_i32(char *fmt, ...) { // ALL: [[V:%.*]] = alloca i32, align 4 // NEW: [[PROMOTION_TEMP:%.*]] = alloca i32, align 4 // -// ALL: call void @llvm.va_start(ptr %va) +// ALL: call void @llvm.va_start.p0(ptr %va) // ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]] // O32: [[AP_NEXT:%.+]] = getelementptr inbounds i8, ptr [[AP_CUR]], [[$INTPTR_T:i32]] [[$CHUNKSIZE:4]] // NEW: [[AP_NEXT:%.+]] = getelementptr inbounds i8, ptr [[AP_CUR]], [[$INTPTR_T:i32|i64]] [[$CHUNKSIZE:8]] @@ -45,7 +45,7 @@ int test_i32(char *fmt, ...) { // NEW: [[ARG:%.+]] = load i32, ptr [[PROMOTION_TEMP]], align 4 // ALL: store i32 [[ARG]], ptr [[V]], align 4 // -// ALL: call void @llvm.va_end(ptr %va) +// ALL: call void @llvm.va_end.p0(ptr %va) // ALL: } long long test_i64(char *fmt, ...) { @@ -61,7 +61,7 @@ long long test_i64(char *fmt, ...) { // ALL-LABEL: define{{.*}} i64 @test_i64(ptr{{.*}} %fmt, ...) // // ALL: %va = alloca ptr, align [[$PTRALIGN]] -// ALL: call void @llvm.va_start(ptr %va) +// ALL: call void @llvm.va_start.p0(ptr %va) // ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]] // // i64 is 8-byte aligned, while this is within O32's stack alignment there's no @@ -74,7 +74,7 @@ long long test_i64(char *fmt, ...) { // // ALL: [[ARG:%.+]] = load i64, ptr [[AP_CUR]], align 8 // -// ALL: call void @llvm.va_end(ptr %va) +// ALL: call void @llvm.va_end.p0(ptr %va) // ALL: } char *test_ptr(char *fmt, ...) { @@ -92,7 +92,7 @@ char *test_ptr(char *fmt, ...) { // ALL: %va = alloca ptr, align [[$PTRALIGN]] // ALL: [[V:%.*]] = alloca ptr, align [[$PTRALIGN]] // N32: [[AP_CAST:%.+]] = alloca ptr, align 4 -// ALL: call void @llvm.va_start(ptr %va) +// ALL: call void @llvm.va_start.p0(ptr %va) // ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]] // ALL: [[AP_NEXT:%.+]] = getelementptr inbounds i8, ptr [[AP_CUR]], [[$INTPTR_T]] [[$CHUNKSIZE]] // ALL: store ptr [[AP_NEXT]], ptr %va, align [[$PTRALIGN]] @@ -109,7 +109,7 @@ char *test_ptr(char *fmt, ...) { // N64: [[ARG:%.+]] = load ptr, ptr [[AP_CUR]], align [[$PTRALIGN]] // ALL: store ptr [[ARG]], ptr [[V]], align [[$PTRALIGN]] // -// ALL: call void @llvm.va_end(ptr %va) +// ALL: call void @llvm.va_end.p0(ptr %va) // ALL: } int test_v4i32(char *fmt, ...) { @@ -128,7 +128,7 @@ int test_v4i32(char *fmt, ...) { // // ALL: %va = alloca ptr, align [[$PTRALIGN]] // ALL: [[V:%.+]] = alloca <4 x i32>, align 16 -// ALL: call void @llvm.va_start(ptr %va) +// ALL: call void @llvm.va_start.p0(ptr %va) // ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]] // // Vectors are 16-byte aligned, however the O32 ABI has a maximum alignment of @@ -152,7 +152,7 @@ int test_v4i32(char *fmt, ...) { // N32: [[ARG:%.+]] = load <4 x i32>, ptr [[AP_CUR]], align 16 // ALL: store <4 x i32> [[ARG]], ptr [[V]], align 16 // -// ALL: call void @llvm.va_end(ptr %va) +// ALL: call void @llvm.va_end.p0(ptr %va) // ALL: [[VECEXT:%.+]] = extractelement <4 x i32> {{.*}}, i32 0 // ALL: ret i32 [[VECEXT]] // ALL: } diff --git a/clang/test/CodeGen/pr53127.cpp b/clang/test/CodeGen/pr53127.cpp index 97fe1291352d3cf642b301e73b0403a411fa99bc..5a52b4860eecdd3eec7447f55cad7613c0a1b38f 100644 --- a/clang/test/CodeGen/pr53127.cpp +++ b/clang/test/CodeGen/pr53127.cpp @@ -34,7 +34,7 @@ void operator delete(void*); // CHECK-NEXT: br i1 [[CALL6]], label [[COND_TRUE7:%.*]], label [[COND_FALSE8:%.*]] // CHECK: cond.true7: // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[L]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) // CHECK-NEXT: br label [[COND_END9:%.*]] // CHECK: cond.false8: // CHECK-NEXT: br label [[COND_END9]] @@ -44,7 +44,7 @@ void operator delete(void*); // CHECK: cond.true11: // CHECK-NEXT: [[ARRAYDECAY12:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[L]], i64 0, i64 0 // CHECK-NEXT: [[ARRAYDECAY13:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[L2]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_copy(ptr [[ARRAYDECAY12]], ptr [[ARRAYDECAY13]]) +// CHECK-NEXT: call void @llvm.va_copy.p0(ptr [[ARRAYDECAY12]], ptr [[ARRAYDECAY13]]) // CHECK-NEXT: br label [[COND_END15:%.*]] // CHECK: cond.false14: // CHECK-NEXT: br label [[COND_END15]] diff --git a/clang/test/CodeGen/varargs-with-nonzero-default-address-space.c b/clang/test/CodeGen/varargs-with-nonzero-default-address-space.c new file mode 100644 index 0000000000000000000000000000000000000000..b087da34c3dfb57bc09dead1e1d20318ceb98aa0 --- /dev/null +++ b/clang/test/CodeGen/varargs-with-nonzero-default-address-space.c @@ -0,0 +1,46 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// RUN: %clang_cc1 -triple spirv64-unknown-unknown -fcuda-is-device -emit-llvm -o - %s | FileCheck %s + +struct x { + double b; + long a; +}; + +// CHECK-LABEL: define spir_func void @testva( +// CHECK-SAME: i32 noundef [[N:%.*]], ...) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AP:%.*]] = alloca ptr addrspace(4), align 8 +// CHECK-NEXT: [[T:%.*]] = alloca [[STRUCT_X:%.*]], align 8 +// CHECK-NEXT: [[AP2:%.*]] = alloca ptr addrspace(4), align 8 +// CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[VARET:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr [[N_ADDR]] to ptr addrspace(4) +// CHECK-NEXT: [[AP_ASCAST:%.*]] = addrspacecast ptr [[AP]] to ptr addrspace(4) +// CHECK-NEXT: [[T_ASCAST:%.*]] = addrspacecast ptr [[T]] to ptr addrspace(4) +// CHECK-NEXT: [[AP2_ASCAST:%.*]] = addrspacecast ptr [[AP2]] to ptr addrspace(4) +// CHECK-NEXT: [[V_ASCAST:%.*]] = addrspacecast ptr [[V]] to ptr addrspace(4) +// CHECK-NEXT: [[VARET_ASCAST:%.*]] = addrspacecast ptr [[VARET]] to ptr addrspace(4) +// CHECK-NEXT: store i32 [[N]], ptr addrspace(4) [[N_ADDR_ASCAST]], align 4 +// CHECK-NEXT: call void @llvm.va_start.p4(ptr addrspace(4) [[AP_ASCAST]]) +// CHECK-NEXT: [[TMP0:%.*]] = va_arg ptr addrspace(4) [[AP_ASCAST]], ptr +// CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 8 [[T_ASCAST]], ptr align 8 [[TMP0]], i64 16, i1 false) +// CHECK-NEXT: call void @llvm.va_copy.p4(ptr addrspace(4) [[AP2_ASCAST]], ptr addrspace(4) [[AP_ASCAST]]) +// CHECK-NEXT: [[TMP1:%.*]] = va_arg ptr addrspace(4) [[AP2_ASCAST]], i32 +// CHECK-NEXT: store i32 [[TMP1]], ptr addrspace(4) [[VARET_ASCAST]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(4) [[VARET_ASCAST]], align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr addrspace(4) [[V_ASCAST]], align 4 +// CHECK-NEXT: call void @llvm.va_end.p4(ptr addrspace(4) [[AP2_ASCAST]]) +// CHECK-NEXT: call void @llvm.va_end.p4(ptr addrspace(4) [[AP_ASCAST]]) +// CHECK-NEXT: ret void + +void testva(int n, ...) { + __builtin_va_list ap; + __builtin_va_start(ap, n); + struct x t = __builtin_va_arg(ap, struct x); + __builtin_va_list ap2; + __builtin_va_copy(ap2, ap); + int v = __builtin_va_arg(ap2, int); + __builtin_va_end(ap2); + __builtin_va_end(ap); +} diff --git a/clang/test/CodeGen/xcore-abi.c b/clang/test/CodeGen/xcore-abi.c index 4dd0f221533b942ae58c0d108da9bd8fd2c3b9ad..bb8d2fec46bdb2faedfe8544ee607fb96ce4e231 100644 --- a/clang/test/CodeGen/xcore-abi.c +++ b/clang/test/CodeGen/xcore-abi.c @@ -28,7 +28,7 @@ void testva (int n, ...) { // CHECK: [[AP:%[a-z0-9]+]] = alloca ptr, align 4 // CHECK: [[V5:%[a-z0-9]+]] = alloca %struct.x, align 4 // CHECK: [[TMP:%[a-z0-9]+]] = alloca [4 x i32], align 4 - // CHECK: call void @llvm.va_start(ptr [[AP]]) + // CHECK: call void @llvm.va_start.p0(ptr [[AP]]) char* v1 = va_arg (ap, char*); f(v1); diff --git a/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp b/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp index 14963867798d34f1fc5a7881ba55120f66b6c1b0..7953f902bf09b2abe6281981a853c96da48466fc 100644 --- a/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp +++ b/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp @@ -56,13 +56,6 @@ void run_foo_tml() { // CHECK-NEXT: ret i32 1 // // -// CHECK-LABEL: @_Z7foo_ovli.default( -// 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: @_Z7foo_ovli.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -82,11 +75,6 @@ void run_foo_tml() { // CHECK-NEXT: ret i32 2 // // -// CHECK-LABEL: @_Z7foo_ovlv.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 -// -// // CHECK-LABEL: @_Z7foo_ovlv.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -182,6 +170,18 @@ void run_foo_tml() { // CHECK-NEXT: ret i32 4 // // +// CHECK-LABEL: @_Z7foo_ovli.default( +// 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: @_Z7foo_ovlv.default( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// // CHECK-LABEL: @_ZN7MyClassIssE7foo_tmlEv._Mfrintts( // CHECK-NEXT: entry: // CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 @@ -231,8 +231,8 @@ void run_foo_tml() { // //. // CHECK: attributes #[[ATTR0:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" } -// 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"="+ls64" } +// CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ls64" } +// CHECK: attributes #[[ATTR2:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } // CHECK: attributes #[[ATTR3:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint" } // CHECK: attributes #[[ATTR4:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme-f64f64" } //. 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/ext-int.cpp b/clang/test/CodeGenCXX/ext-int.cpp index 5a4270aef28542e74e9692005c2e77d43688ba35..a1d17c840ee46054bf791efc560cbc591fb87c78 100644 --- a/clang/test/CodeGenCXX/ext-int.cpp +++ b/clang/test/CodeGenCXX/ext-int.cpp @@ -159,9 +159,9 @@ void TakesVarargs(int i, ...) { // WIN: %[[ARGS:.+]] = alloca ptr __builtin_va_start(args, i); // LIN64: %[[STARTAD:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[ARGS]] - // LIN64: call void @llvm.va_start(ptr %[[STARTAD]]) - // LIN32: call void @llvm.va_start(ptr %[[ARGS]]) - // WIN: call void @llvm.va_start(ptr %[[ARGS]]) + // LIN64: call void @llvm.va_start.p0(ptr %[[STARTAD]]) + // LIN32: call void @llvm.va_start.p0(ptr %[[ARGS]]) + // WIN: call void @llvm.va_start.p0(ptr %[[ARGS]]) _BitInt(92) A = __builtin_va_arg(args, _BitInt(92)); // LIN64: %[[AD1:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[ARGS]] @@ -302,9 +302,9 @@ void TakesVarargs(int i, ...) { __builtin_va_end(args); // LIN64: %[[ENDAD:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[ARGS]] - // LIN64: call void @llvm.va_end(ptr %[[ENDAD]]) - // LIN32: call void @llvm.va_end(ptr %[[ARGS]]) - // WIN: call void @llvm.va_end(ptr %[[ARGS]]) + // LIN64: call void @llvm.va_end.p0(ptr %[[ENDAD]]) + // LIN32: call void @llvm.va_end.p0(ptr %[[ARGS]]) + // WIN: call void @llvm.va_end.p0(ptr %[[ARGS]]) } void typeid_tests() { // LIN: define{{.*}} void @_Z12typeid_testsv() diff --git a/clang/test/CodeGenCXX/ibm128-declarations.cpp b/clang/test/CodeGenCXX/ibm128-declarations.cpp index 5ee4f354d379570e987d0b66551bbdb7fe3760d3..e0187e20cde423edf970057b6e94f9c9d247a249 100644 --- a/clang/test/CodeGenCXX/ibm128-declarations.cpp +++ b/clang/test/CodeGenCXX/ibm128-declarations.cpp @@ -107,13 +107,13 @@ int main(void) { // CHECK: define dso_local noundef ppc_fp128 @_Z10func_vaargiz(i32 noundef signext %n, ...) // CHECK: entry: // CHECK: store i32 %n, ptr %n.addr, align 4 -// CHECK: call void @llvm.va_start(ptr %ap) +// CHECK: call void @llvm.va_start.p0(ptr %ap) // CHECK: %argp.cur = load ptr, ptr %ap, align 8 // CHECK: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i64 16 // CHECK: store ptr %argp.next, ptr %ap, align 8 // CHECK: %0 = load ppc_fp128, ptr %argp.cur, align 8 // CHECK: store ppc_fp128 %0, ptr %r, align 16 -// CHECK: call void @llvm.va_end(ptr %ap) +// CHECK: call void @llvm.va_end.p0(ptr %ap) // CHECK: %1 = load ppc_fp128, ptr %r, align 16 // CHECK: ret ppc_fp128 %1 // CHECK: } 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/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index f0177906a09a810c8fa9a226dc14f076b62248db..985a0cc41a14106f31af840f0e325343a03bfa08 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -1,10 +1,9 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -x c -o - %s | FileCheck %s typedef struct { struct {} a; } empty; -// CHECK-LABEL: @{{.*}}empty_record_test +// CHECK-LABEL: @_Z17empty_record_testiz( // CHECK-NEXT: entry: // CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1 // CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 @@ -12,12 +11,57 @@ typedef struct { struct {} a; } empty; // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_EMPTY]], align 1 // CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) // CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[RETVAL]], ptr align 1 [[TMP]], i64 {{.*}}, i1 false) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[RETVAL]], ptr align 1 [[TMP]], i64 1, i1 false) // CHECK-NEXT: ret void +// empty empty_record_test(int z, ...) { __builtin_va_list list; __builtin_va_start(list, z); return __builtin_va_arg(list, empty); } + +typedef struct { + struct{} a; + double b; +} s1; + +// CHECK-LABEL: @_Z1fiz( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 +// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT: [[FP_OFFSET_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 1 +// CHECK-NEXT: [[FP_OFFSET:%.*]] = load i32, ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT: [[FITS_IN_FP:%.*]] = icmp ule i32 [[FP_OFFSET]], 160 +// CHECK-NEXT: br i1 [[FITS_IN_FP]], label [[VAARG_IN_REG:%.*]], label [[VAARG_IN_MEM:%.*]] +// CHECK: vaarg.in_reg: +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 +// CHECK-NEXT: [[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] +// CHECK-NEXT: [[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT: br label [[VAARG_END:%.*]] +// CHECK: vaarg.in_mem: +// CHECK-NEXT: [[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2 +// CHECK-NEXT: [[OVERFLOW_ARG_AREA:%.*]] = load ptr, ptr [[OVERFLOW_ARG_AREA_P]], align 8 +// CHECK-NEXT: [[OVERFLOW_ARG_AREA_NEXT:%.*]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i32 16 +// CHECK-NEXT: store ptr [[OVERFLOW_ARG_AREA_NEXT]], ptr [[OVERFLOW_ARG_AREA_P]], align 8 +// CHECK-NEXT: br label [[VAARG_END]] +// CHECK: vaarg.end: +// CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP1]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[VAARG_ADDR]], i64 16, i1 false) +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[RETVAL]], i64 8 +// CHECK-NEXT: [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8 +// CHECK-NEXT: ret double [[TMP4]] +// +s1 f(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, s1); +} diff --git a/clang/test/CodeGenHLSL/builtins/bitreverse.hlsl b/clang/test/CodeGenHLSL/builtins/bitreverse.hlsl deleted file mode 100644 index e7609a2b61e25913ae531fd4c6745ae1694324bd..0000000000000000000000000000000000000000 --- a/clang/test/CodeGenHLSL/builtins/bitreverse.hlsl +++ /dev/null @@ -1,155 +0,0 @@ -// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s -D__HLSL_ENABLE_16_BIT \ -// RUN: -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s - -#ifdef __HLSL_ENABLE_16_BIT -// CHECK: define noundef i16 @ -// CHECK: call i16 @llvm.bitreverse.i16( -int16_t test_bitreverse_short(int16_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i16> @ -// CHECK: call <2 x i16> @llvm.bitreverse.v2i16( -int16_t2 test_bitreverse_short2(int16_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i16> @ -// CHECK: call <3 x i16> @llvm.bitreverse.v3i16 -int16_t3 test_bitreverse_short3(int16_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i16> @ -// CHECK: call <4 x i16> @llvm.bitreverse.v4i16 -int16_t4 test_bitreverse_short4(int16_t4 p0) -{ - return reversebits(p0); -} - -// CHECK: define noundef i16 @ -// CHECK: call i16 @llvm.bitreverse.i16( -uint16_t test_bitreverse_ushort(uint16_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i16> @ -// CHECK: call <2 x i16> @llvm.bitreverse.v2i16 -uint16_t2 test_bitreverse_ushort2(uint16_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i16> @ -// CHECK: call <3 x i16> @llvm.bitreverse.v3i16 -uint16_t3 test_bitreverse_ushort3(uint16_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i16> @ -// CHECK: call <4 x i16> @llvm.bitreverse.v4i16 -uint16_t4 test_bitreverse_ushort4(uint16_t4 p0) -{ - return reversebits(p0); -} -#endif - -// CHECK: define noundef i32 @ -// CHECK: call i32 @llvm.bitreverse.i32( -int test_bitreverse_int(int p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i32> @ -// CHECK: call <2 x i32> @llvm.bitreverse.v2i32 -int2 test_bitreverse_int2(int2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i32> @ -// CHECK: call <3 x i32> @llvm.bitreverse.v3i32 -int3 test_bitreverse_int3(int3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i32> @ -// CHECK: call <4 x i32> @llvm.bitreverse.v4i32 -int4 test_bitreverse_int4(int4 p0) -{ - return reversebits(p0); -} - -// CHECK: define noundef i32 @ -// CHECK: call i32 @llvm.bitreverse.i32( -int test_bitreverse_uint(uint p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i32> @ -// CHECK: call <2 x i32> @llvm.bitreverse.v2i32 -uint2 test_bitreverse_uint2(uint2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i32> @ -// CHECK: call <3 x i32> @llvm.bitreverse.v3i32 -uint3 test_bitreverse_uint3(uint3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i32> @ -// CHECK: call <4 x i32> @llvm.bitreverse.v4i32 -uint4 test_bitreverse_uint4(uint4 p0) -{ - return reversebits(p0); -} - -// CHECK: define noundef i64 @ -// CHECK: call i64 @llvm.bitreverse.i64( -int64_t test_bitreverse_long(int64_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i64> @ -// CHECK: call <2 x i64> @llvm.bitreverse.v2i64 -int64_t2 test_bitreverse_long2(int64_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i64> @ -// CHECK: call <3 x i64> @llvm.bitreverse.v3i64 -int64_t3 test_bitreverse_long3(int64_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i64> @ -// CHECK: call <4 x i64> @llvm.bitreverse.v4i64 -int64_t4 test_bitreverse_long4(int64_t4 p0) -{ - return reversebits(p0); -} - -// CHECK: define noundef i64 @ -// CHECK: call i64 @llvm.bitreverse.i64( -uint64_t test_bitreverse_long(uint64_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i64> @ -// CHECK: call <2 x i64> @llvm.bitreverse.v2i64 -uint64_t2 test_bitreverse_long2(uint64_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i64> @ -// CHECK: call <3 x i64> @llvm.bitreverse.v3i64 -uint64_t3 test_bitreverse_long3(uint64_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i64> @ -// CHECK: call <4 x i64> @llvm.bitreverse.v4i64 -uint64_t4 test_bitreverse_long4(uint64_t4 p0) -{ - return reversebits(p0); -} 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/reversebits.hlsl b/clang/test/CodeGenHLSL/builtins/reversebits.hlsl index 6da7d289f82e8044a57e454f05163fa2a38d4a85..a319417e97a436dcf52f8807c7e7e82816722599 100644 --- a/clang/test/CodeGenHLSL/builtins/reversebits.hlsl +++ b/clang/test/CodeGenHLSL/builtins/reversebits.hlsl @@ -3,31 +3,6 @@ // RUN: -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s #ifdef __HLSL_ENABLE_16_BIT -// CHECK: define noundef i16 @ -// CHECK: call i16 @llvm.bitreverse.i16( -int16_t test_bitreverse_short(int16_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i16> @ -// CHECK: call <2 x i16> @llvm.bitreverse.v2i16( -int16_t2 test_bitreverse_short2(int16_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i16> @ -// CHECK: call <3 x i16> @llvm.bitreverse.v3i16 -int16_t3 test_bitreverse_short3(int16_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i16> @ -// CHECK: call <4 x i16> @llvm.bitreverse.v4i16 -int16_t4 test_bitreverse_short4(int16_t4 p0) -{ - return reversebits(p0); -} - // CHECK: define noundef i16 @ // CHECK: call i16 @llvm.bitreverse.i16( uint16_t test_bitreverse_ushort(uint16_t p0) @@ -54,31 +29,6 @@ uint16_t4 test_bitreverse_ushort4(uint16_t4 p0) } #endif -// CHECK: define noundef i32 @ -// CHECK: call i32 @llvm.bitreverse.i32( -int test_bitreverse_int(int p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i32> @ -// CHECK: call <2 x i32> @llvm.bitreverse.v2i32 -int2 test_bitreverse_int2(int2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i32> @ -// CHECK: call <3 x i32> @llvm.bitreverse.v3i32 -int3 test_bitreverse_int3(int3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i32> @ -// CHECK: call <4 x i32> @llvm.bitreverse.v4i32 -int4 test_bitreverse_int4(int4 p0) -{ - return reversebits(p0); -} - // CHECK: define noundef i32 @ // CHECK: call i32 @llvm.bitreverse.i32( int test_bitreverse_uint(uint p0) @@ -104,31 +54,6 @@ uint4 test_bitreverse_uint4(uint4 p0) return reversebits(p0); } -// CHECK: define noundef i64 @ -// CHECK: call i64 @llvm.bitreverse.i64( -int64_t test_bitreverse_long(int64_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i64> @ -// CHECK: call <2 x i64> @llvm.bitreverse.v2i64 -int64_t2 test_bitreverse_long2(int64_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i64> @ -// CHECK: call <3 x i64> @llvm.bitreverse.v3i64 -int64_t3 test_bitreverse_long3(int64_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i64> @ -// CHECK: call <4 x i64> @llvm.bitreverse.v4i64 -int64_t4 test_bitreverse_long4(int64_t4 p0) -{ - return reversebits(p0); -} - // CHECK: define noundef i64 @ // CHECK: call i64 @llvm.bitreverse.i64( uint64_t test_bitreverse_long(uint64_t p0) 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..1e78ab283486820572ce9067f3fb9d5f45cf2824 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 @@ -4,23 +4,14 @@ // REQUIRES: amdgpu-registered-target 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 half v4h __attribute__((ext_vector_type(4))); typedef short v4s __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 int* int_inptr, global v4s* v4s_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}} - 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_3 = __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_4 = __builtin_amdgcn_global_load_tr_b128_v4i16(v4s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v4i16' 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..1acc4cd7adc9609575b528bc77cfe6378a40aa78 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 @@ -3,13 +3,10 @@ // REQUIRES: amdgpu-registered-target -typedef half v4h __attribute__((ext_vector_type(4))); typedef short v4s __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) { - 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}} } - 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..96b0e4c3993ab6ccc644692e28cf61387d607f48 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 @@ -4,13 +4,10 @@ // REQUIRES: amdgpu-registered-target typedef int v2i __attribute__((ext_vector_type(2))); -typedef half v8h __attribute__((ext_vector_type(8))); typedef short v8s __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) { - 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}} } - 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..126d7d6fb7b05323cbcf0ef73f2df6d6b254325f 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w32.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w32.cl @@ -3,46 +3,24 @@ // RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1200 -target-feature +wavefrontsize32 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-GFX1200 typedef int v2i __attribute__((ext_vector_type(2))); -typedef half v8h __attribute__((ext_vector_type(8))); typedef short v8s __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: [[TMP0:%.*]] = tail call <2 x i32> @llvm.amdgcn.global.load.tr.b64.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: [[TMP0:%.*]] = tail call <8 x i16> @llvm.amdgcn.global.load.tr.b128.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-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) -{ - return __builtin_amdgcn_global_load_tr_v8f16(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..7c70ccf73ad385e8f3dbc9411e71d7f7c545848f 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w64.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w64.cl @@ -2,46 +2,24 @@ // REQUIRES: amdgpu-registered-target // RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1200 -target-feature +wavefrontsize64 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-GFX1200 -typedef half v4h __attribute__((ext_vector_type(4))); typedef short v4s __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: [[TMP0:%.*]] = tail call i32 @llvm.amdgcn.global.load.tr.b64.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: [[TMP0:%.*]] = tail call <4 x i16> @llvm.amdgcn.global.load.tr.b128.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-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) -{ - return __builtin_amdgcn_global_load_tr_v4f16(inptr); -} - diff --git a/clang/test/Driver/aarch64-ptrauth.c b/clang/test/Driver/aarch64-ptrauth.c new file mode 100644 index 0000000000000000000000000000000000000000..1a69b2c6edfb17a93b726eccfbc2890a59c5915e --- /dev/null +++ b/clang/test/Driver/aarch64-ptrauth.c @@ -0,0 +1,5 @@ +// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-intrinsics -fptrauth-intrinsics %s 2>&1 | FileCheck %s --check-prefix=INTRIN +// INTRIN: "-cc1"{{.*}} "-fptrauth-intrinsics" + +// RUN: not %clang -### -c --target=x86_64 -fptrauth-intrinsics %s 2>&1 | FileCheck %s --check-prefix=ERR +// ERR: error: unsupported option '-fptrauth-intrinsics' for target '{{.*}}' diff --git a/clang/test/Driver/aarch64-sve.c b/clang/test/Driver/aarch64-sve.c index f34b2700deb91c34d1ad0ccd545e618523995d5a..4a33c2e3c8d3677957b4da4131320701e8640823 100644 --- a/clang/test/Driver/aarch64-sve.c +++ b/clang/test/Driver/aarch64-sve.c @@ -6,12 +6,11 @@ // RUN: %clang --target=aarch64 -march=armv8.6a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV8A-NOSVE %s // GENERICV8A-NOSVE-NOT: "-target-feature" "+sve" -// The 32-bit floating point matrix multiply extension is enabled by default -// for armv8.6-a targets (or later) with SVE, and can optionally be enabled for -// any target from armv8.2a onwards (we don't enforce not using it with earlier -// targets). +// The 32-bit floating point matrix multiply extension is an optional feature +// that can be used for any target from armv8.2a and onwards. This can be +// enabled using the `+f32mm` option.`. // RUN: %clang --target=aarch64 -march=armv8.6a -### -c %s 2>&1 | FileCheck -check-prefix=NO-F32MM %s -// RUN: %clang --target=aarch64 -march=armv8.6a+sve -### -c %s 2>&1 | FileCheck -check-prefix=F32MM %s +// RUN: %clang --target=aarch64 -march=armv8.6a+sve+f32mm -### -c %s 2>&1 | FileCheck -check-prefix=F32MM %s // RUN: %clang --target=aarch64 -march=armv8.5a+f32mm -### -c %s 2>&1 | FileCheck -check-prefix=F32MM %s // NO-F32MM-NOT: "-target-feature" "+f32mm" // F32MM: "-target-feature" "+f32mm" diff --git a/clang/test/Driver/linker-wrapper-image.c b/clang/test/Driver/linker-wrapper-image.c index 7547526413522475e5f47de5b0700b344e4e1230..d01445e3aed04ee3e35c59a69a598a724cc3a259 100644 --- a/clang/test/Driver/linker-wrapper-image.c +++ b/clang/test/Driver/linker-wrapper-image.c @@ -26,11 +26,11 @@ // OPENMP: @.omp_offloading.device_image = internal unnamed_addr constant [[[SIZE:[0-9]+]] x i8] c"\10\FF\10\AD{{.*}}", section ".llvm.offloading", align 8 // OPENMP-NEXT: @.omp_offloading.device_images = internal unnamed_addr constant [1 x %__tgt_device_image] [%__tgt_device_image { ptr getelementptr inbounds ([[[BEGIN:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 1, i64 0), ptr getelementptr inbounds ([[[END:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 1, i64 0), ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries }] // OPENMP-NEXT: @.omp_offloading.descriptor = internal constant %__tgt_bin_desc { i32 1, ptr @.omp_offloading.device_images, ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries } -// OPENMP-NEXT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.omp_offloading.descriptor_reg, ptr null }] -// OPENMP-NEXT: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.omp_offloading.descriptor_unreg, ptr null }] +// OPENMP-NEXT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.omp_offloading.descriptor_reg, ptr null }] // OPENMP: define internal void @.omp_offloading.descriptor_reg() section ".text.startup" { // OPENMP-NEXT: entry: +// OPENMP-NEXT: %0 = call i32 @atexit(ptr @.omp_offloading.descriptor_unreg) // OPENMP-NEXT: call void @__tgt_register_lib(ptr @.omp_offloading.descriptor) // OPENMP-NEXT: ret void // OPENMP-NEXT: } @@ -62,7 +62,7 @@ // CUDA-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1180844977, i32 1, ptr @.fatbin_image, ptr null }, section ".nvFatBinSegment", align 8 // CUDA-NEXT: @.cuda.binary_handle = internal global ptr null -// CUDA: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.cuda.fatbin_reg, ptr null }] +// CUDA: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.cuda.fatbin_reg, ptr null }] // CUDA: define internal void @.cuda.fatbin_reg() section ".text.startup" { // CUDA-NEXT: entry: @@ -162,7 +162,7 @@ // HIP-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1212764230, i32 1, ptr @.fatbin_image, ptr null }, section ".hipFatBinSegment", align 8 // HIP-NEXT: @.hip.binary_handle = internal global ptr null -// HIP: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.hip.fatbin_reg, ptr null }] +// HIP: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.hip.fatbin_reg, ptr null }] // HIP: define internal void @.hip.fatbin_reg() section ".text.startup" { // HIP-NEXT: entry: 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/Inputs/Umbrella/Umbrella.framework/Headers/AAA.h b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/AAA.h new file mode 100644 index 0000000000000000000000000000000000000000..993d5d4abadb8e685a2e171701ae6845623ea98b --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/AAA.h @@ -0,0 +1,3 @@ +#ifndef PUBLIC_UMBRELLA_HEADER_FIRST +#error "Public umbrella header was not included first!" +#endif diff --git a/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/SpecialUmbrella.h b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/SpecialUmbrella.h new file mode 100644 index 0000000000000000000000000000000000000000..2599ff14ae1723b0bf67790519089714c35a2a76 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/SpecialUmbrella.h @@ -0,0 +1 @@ +#define PUBLIC_UMBRELLA_HEADER_FIRST diff --git a/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/AAA_Private.h b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/AAA_Private.h new file mode 100644 index 0000000000000000000000000000000000000000..557209bfeb86993e591de3587497cf4358432ca4 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/AAA_Private.h @@ -0,0 +1,3 @@ +#ifndef PRIVATE_UMBRELLA_HEADER_FIRST +#error "Private umbrella header was not included first!" +#endif diff --git a/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h new file mode 100644 index 0000000000000000000000000000000000000000..fd5b49b943161a7d088a88b39f71a77d04453b74 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h @@ -0,0 +1 @@ +#define PRIVATE_UMBRELLA_HEADER_FIRST 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/InstallAPI/umbrella-headers-unix.test b/clang/test/InstallAPI/umbrella-headers-unix.test new file mode 100644 index 0000000000000000000000000000000000000000..46118779896cf1492a3522213d3fba93d7ded826 --- /dev/null +++ b/clang/test/InstallAPI/umbrella-headers-unix.test @@ -0,0 +1,40 @@ +// UNSUPPORTED: system-windows + +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json +; RUN: mkdir %t/Frameworks/ +; RUN: cp -r %S/Inputs/Umbrella/Umbrella.framework %t/Frameworks/ + +// Only validate path based input that rely on regex matching on unix based file systems. +; RUN: clang-installapi --target=arm64-apple-macosx13 \ +; RUN: -install_name /System/Library/Frameworks/Umbrella2.framework/Versions/A/Umbrella \ +; RUN: -ObjC -F%t/Frameworks/ %t/inputs.json \ +; RUN: --public-umbrella-header=%t/Frameworks/Umbrella.framework/Headers/SpecialUmbrella.h \ +; RUN: -private-umbrella-header \ +; RUN: %t/Frameworks/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h \ +; RUN: -o %t/output.tbd 2>&1 | FileCheck -allow-empty %s + +; CHECK-NOT: error +; CHECK-NOT: warning + +;--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/AAA.h", + "type" : "public" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/SpecialUmbrella.h", + "type" : "public" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/AAA_Private.h", + "type" : "private" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h", + "type" : "private" + }], + "version": "3" +} diff --git a/clang/test/InstallAPI/umbrella-headers.test b/clang/test/InstallAPI/umbrella-headers.test new file mode 100644 index 0000000000000000000000000000000000000000..ce9c50608c41194b648a29f1f987dfe28f6b9134 --- /dev/null +++ b/clang/test/InstallAPI/umbrella-headers.test @@ -0,0 +1,48 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json +; RUN: cp -r %S/Inputs/Umbrella/Umbrella.framework %t/Frameworks/ + +// Check base filename matches. +; RUN: clang-installapi --target=arm64-apple-macosx13 \ +; RUN: -install_name /System/Library/Frameworks/Umbrella.framework/Versions/A/Umbrella \ +; RUN: -ObjC -F%t/Frameworks/ %t/inputs.json \ +; RUN: --public-umbrella-header=SpecialUmbrella.h \ +; RUN: --private-umbrella-header=SpecialPrivateUmbrella.h \ +; RUN: -o %t/output.tbd 2>&1 | FileCheck -allow-empty %s + +// Try missing umbrella header argument. +; RUN: not clang-installapi --target=arm64-apple-macosx13 \ +; RUN: -install_name /System/Library/Frameworks/Umbrella.framework/Versions/A/Umbrella \ +; RUN: -ObjC -F%t/Frameworks/ %t/inputs.json \ +; RUN: --public-umbrella-header=Ignore.h \ +; RUN: -o %t/output.tbd 2>&1 | FileCheck %s -check-prefix=ERR + +; ERR: error: public umbrella header file not found in input: 'Ignore.h' + +; CHECK-NOT: error +; CHECK-NOT: warning + +;--- Frameworks/Umbrella.framework/Headers/Ignore.h +#error "This header should be ignored" + +;--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/AAA.h", + "type" : "public" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/SpecialUmbrella.h", + "type" : "public" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/AAA_Private.h", + "type" : "private" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h", + "type" : "private" + }], + "version": "3" +} diff --git a/clang/test/Modules/codegen.test b/clang/test/Modules/codegen.test index 77602056defd4e139a5b8e88ba2ccf9bfadc590b..0af630a754805684a68f99147f31c1768392d87a 100644 --- a/clang/test/Modules/codegen.test +++ b/clang/test/Modules/codegen.test @@ -26,7 +26,7 @@ USE: $_Z4instIiEvv = comdat any USE: $_Z10always_inlv = comdat any FOO: $_ZN13implicit_dtorD2Ev = comdat any FOO: define weak_odr void @_Z2f1PKcz(ptr noundef %fmt, ...) #{{[0-9]+}} comdat -FOO: call void @llvm.va_start(ptr %{{[a-zA-Z0-9]*}}) +FOO: call void @llvm.va_start.p0(ptr %{{[a-zA-Z0-9]*}}) Test that implicit special members are emitted into the FOO module if they're ODR used there, otherwise emit them linkonce_odr as usual in the use. diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index 9f8a8bdeeb9cb047d2bec0b1f6c346ad5ffe4ed1..85762b7fed4d719aad07a251cb8a30611290db0b 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -196,7 +196,7 @@ // CHECK-8_6-NOT: __ARM_FEATURE_SHA3 1 // CHECK-8_6-NOT: __ARM_FEATURE_SM4 1 -// RUN: %clang -target aarch64-none-linux-gnu -march=armv8.6-a+sve -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE-8_6 %s +// RUN: %clang -target aarch64-none-linux-gnu -march=armv8.6-a+sve+f32mm -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE-8_6 %s // CHECK-SVE-8_6: __ARM_FEATURE_SVE 1 // CHECK-SVE-8_6: __ARM_FEATURE_SVE_BF16 1 // CHECK-SVE-8_6: __ARM_FEATURE_SVE_MATMUL_FP32 1 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-clones-aarch64.c b/clang/test/Sema/attr-target-clones-aarch64.c index 0ce277f41884c6dffc39606fd3cae75c1046b172..bc3fceab82825bff5f20fd69aa529d5bc6b2d288 100644 --- a/clang/test/Sema/attr-target-clones-aarch64.c +++ b/clang/test/Sema/attr-target-clones-aarch64.c @@ -27,7 +27,7 @@ int __attribute__((target_clones("rng", "fp16fml+fp", "default"))) redecl4(void) int __attribute__((target_clones("dgh+memtag+rpres+ls64_v", "ebf16+dpb+sha1", "default"))) redecl4(void) { return 1; } int __attribute__((target_version("flagm2"))) redef2(void) { return 1; } -// expected-error@+2 {{multiversioning attributes cannot be combined}} +// expected-error@+2 {{multiversioned function redeclarations require identical target attributes}} // expected-note@-2 {{previous declaration is here}} int __attribute__((target_clones("flagm2", "default"))) redef2(void) { return 1; } 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/Sema/constant-builtins-2.c b/clang/test/Sema/constant-builtins-2.c index 6dd1d88759c751837e536549068279f6aab2234a..a60a1f16a458741bfdd9b2428a19459c62d0a283 100644 --- a/clang/test/Sema/constant-builtins-2.c +++ b/clang/test/Sema/constant-builtins-2.c @@ -218,6 +218,64 @@ char clz6[__builtin_clzll(0xFFLL) == BITSIZE(long long) - 8 ? 1 : -1]; char clz7[__builtin_clzs(0x1) == BITSIZE(short) - 1 ? 1 : -1]; char clz8[__builtin_clzs(0xf) == BITSIZE(short) - 4 ? 1 : -1]; char clz9[__builtin_clzs(0xfff) == BITSIZE(short) - 12 ? 1 : -1]; +int clz10 = __builtin_clzg((unsigned char)0); // expected-error {{not a compile-time constant}} +char clz11[__builtin_clzg((unsigned char)0, 42) == 42 ? 1 : -1]; +char clz12[__builtin_clzg((unsigned char)0x1) == BITSIZE(char) - 1 ? 1 : -1]; +char clz13[__builtin_clzg((unsigned char)0x1, 42) == BITSIZE(char) - 1 ? 1 : -1]; +char clz14[__builtin_clzg((unsigned char)0xf) == BITSIZE(char) - 4 ? 1 : -1]; +char clz15[__builtin_clzg((unsigned char)0xf, 42) == BITSIZE(char) - 4 ? 1 : -1]; +char clz16[__builtin_clzg((unsigned char)(1 << (BITSIZE(char) - 1))) == 0 ? 1 : -1]; +char clz17[__builtin_clzg((unsigned char)(1 << (BITSIZE(char) - 1)), 42) == 0 ? 1 : -1]; +int clz18 = __builtin_clzg((unsigned short)0); // expected-error {{not a compile-time constant}} +char clz19[__builtin_clzg((unsigned short)0, 42) == 42 ? 1 : -1]; +char clz20[__builtin_clzg((unsigned short)0x1) == BITSIZE(short) - 1 ? 1 : -1]; +char clz21[__builtin_clzg((unsigned short)0x1, 42) == BITSIZE(short) - 1 ? 1 : -1]; +char clz22[__builtin_clzg((unsigned short)0xf) == BITSIZE(short) - 4 ? 1 : -1]; +char clz23[__builtin_clzg((unsigned short)0xf, 42) == BITSIZE(short) - 4 ? 1 : -1]; +char clz24[__builtin_clzg((unsigned short)(1 << (BITSIZE(short) - 1))) == 0 ? 1 : -1]; +char clz25[__builtin_clzg((unsigned short)(1 << (BITSIZE(short) - 1)), 42) == 0 ? 1 : -1]; +int clz26 = __builtin_clzg(0U); // expected-error {{not a compile-time constant}} +char clz27[__builtin_clzg(0U, 42) == 42 ? 1 : -1]; +char clz28[__builtin_clzg(0x1U) == BITSIZE(int) - 1 ? 1 : -1]; +char clz29[__builtin_clzg(0x1U, 42) == BITSIZE(int) - 1 ? 1 : -1]; +char clz30[__builtin_clzg(0xfU) == BITSIZE(int) - 4 ? 1 : -1]; +char clz31[__builtin_clzg(0xfU, 42) == BITSIZE(int) - 4 ? 1 : -1]; +char clz32[__builtin_clzg(1U << (BITSIZE(int) - 1)) == 0 ? 1 : -1]; +char clz33[__builtin_clzg(1U << (BITSIZE(int) - 1), 42) == 0 ? 1 : -1]; +int clz34 = __builtin_clzg(0UL); // expected-error {{not a compile-time constant}} +char clz35[__builtin_clzg(0UL, 42) == 42 ? 1 : -1]; +char clz36[__builtin_clzg(0x1UL) == BITSIZE(long) - 1 ? 1 : -1]; +char clz37[__builtin_clzg(0x1UL, 42) == BITSIZE(long) - 1 ? 1 : -1]; +char clz38[__builtin_clzg(0xfUL) == BITSIZE(long) - 4 ? 1 : -1]; +char clz39[__builtin_clzg(0xfUL, 42) == BITSIZE(long) - 4 ? 1 : -1]; +char clz40[__builtin_clzg(1UL << (BITSIZE(long) - 1)) == 0 ? 1 : -1]; +char clz41[__builtin_clzg(1UL << (BITSIZE(long) - 1), 42) == 0 ? 1 : -1]; +int clz42 = __builtin_clzg(0ULL); // expected-error {{not a compile-time constant}} +char clz43[__builtin_clzg(0ULL, 42) == 42 ? 1 : -1]; +char clz44[__builtin_clzg(0x1ULL) == BITSIZE(long long) - 1 ? 1 : -1]; +char clz45[__builtin_clzg(0x1ULL, 42) == BITSIZE(long long) - 1 ? 1 : -1]; +char clz46[__builtin_clzg(0xfULL) == BITSIZE(long long) - 4 ? 1 : -1]; +char clz47[__builtin_clzg(0xfULL, 42) == BITSIZE(long long) - 4 ? 1 : -1]; +char clz48[__builtin_clzg(1ULL << (BITSIZE(long long) - 1)) == 0 ? 1 : -1]; +char clz49[__builtin_clzg(1ULL << (BITSIZE(long long) - 1), 42) == 0 ? 1 : -1]; +#ifdef __SIZEOF_INT128__ +int clz50 = __builtin_clzg((unsigned __int128)0); // expected-error {{not a compile-time constant}} +char clz51[__builtin_clzg((unsigned __int128)0, 42) == 42 ? 1 : -1]; +char clz52[__builtin_clzg((unsigned __int128)0x1) == BITSIZE(__int128) - 1 ? 1 : -1]; +char clz53[__builtin_clzg((unsigned __int128)0x1, 42) == BITSIZE(__int128) - 1 ? 1 : -1]; +char clz54[__builtin_clzg((unsigned __int128)0xf) == BITSIZE(__int128) - 4 ? 1 : -1]; +char clz55[__builtin_clzg((unsigned __int128)0xf, 42) == BITSIZE(__int128) - 4 ? 1 : -1]; +char clz56[__builtin_clzg((unsigned __int128)(1 << (BITSIZE(__int128) - 1))) == 0 ? 1 : -1]; +char clz57[__builtin_clzg((unsigned __int128)(1 << (BITSIZE(__int128) - 1)), 42) == 0 ? 1 : -1]; +#endif +int clz58 = __builtin_clzg((unsigned _BitInt(128))0); // expected-error {{not a compile-time constant}} +char clz59[__builtin_clzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1]; +char clz60[__builtin_clzg((unsigned _BitInt(128))0x1) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1]; +char clz61[__builtin_clzg((unsigned _BitInt(128))0x1, 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1]; +char clz62[__builtin_clzg((unsigned _BitInt(128))0xf) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1]; +char clz63[__builtin_clzg((unsigned _BitInt(128))0xf, 42) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1]; +char clz64[__builtin_clzg((unsigned _BitInt(128))(1 << (BITSIZE(_BitInt(128)) - 1))) == 0 ? 1 : -1]; +char clz65[__builtin_clzg((unsigned _BitInt(128))(1 << (BITSIZE(_BitInt(128)) - 1)), 42) == 0 ? 1 : -1]; char ctz1[__builtin_ctz(1) == 0 ? 1 : -1]; char ctz2[__builtin_ctz(8) == 3 ? 1 : -1]; @@ -226,6 +284,64 @@ int ctz4 = __builtin_ctz(0); // expected-error {{not a compile-time constant}} char ctz5[__builtin_ctzl(0x10L) == 4 ? 1 : -1]; char ctz6[__builtin_ctzll(0x100LL) == 8 ? 1 : -1]; char ctz7[__builtin_ctzs(1 << (BITSIZE(short) - 1)) == BITSIZE(short) - 1 ? 1 : -1]; +int ctz8 = __builtin_ctzg((unsigned char)0); // expected-error {{not a compile-time constant}} +char ctz9[__builtin_ctzg((unsigned char)0, 42) == 42 ? 1 : -1]; +char ctz10[__builtin_ctzg((unsigned char)0x1) == 0 ? 1 : -1]; +char ctz11[__builtin_ctzg((unsigned char)0x1, 42) == 0 ? 1 : -1]; +char ctz12[__builtin_ctzg((unsigned char)0x10) == 4 ? 1 : -1]; +char ctz13[__builtin_ctzg((unsigned char)0x10, 42) == 4 ? 1 : -1]; +char ctz14[__builtin_ctzg((unsigned char)(1 << (BITSIZE(char) - 1))) == BITSIZE(char) - 1 ? 1 : -1]; +char ctz15[__builtin_ctzg((unsigned char)(1 << (BITSIZE(char) - 1)), 42) == BITSIZE(char) - 1 ? 1 : -1]; +int ctz16 = __builtin_ctzg((unsigned short)0); // expected-error {{not a compile-time constant}} +char ctz17[__builtin_ctzg((unsigned short)0, 42) == 42 ? 1 : -1]; +char ctz18[__builtin_ctzg((unsigned short)0x1) == 0 ? 1 : -1]; +char ctz19[__builtin_ctzg((unsigned short)0x1, 42) == 0 ? 1 : -1]; +char ctz20[__builtin_ctzg((unsigned short)0x10) == 4 ? 1 : -1]; +char ctz21[__builtin_ctzg((unsigned short)0x10, 42) == 4 ? 1 : -1]; +char ctz22[__builtin_ctzg((unsigned short)(1 << (BITSIZE(short) - 1))) == BITSIZE(short) - 1 ? 1 : -1]; +char ctz23[__builtin_ctzg((unsigned short)(1 << (BITSIZE(short) - 1)), 42) == BITSIZE(short) - 1 ? 1 : -1]; +int ctz24 = __builtin_ctzg(0U); // expected-error {{not a compile-time constant}} +char ctz25[__builtin_ctzg(0U, 42) == 42 ? 1 : -1]; +char ctz26[__builtin_ctzg(0x1U) == 0 ? 1 : -1]; +char ctz27[__builtin_ctzg(0x1U, 42) == 0 ? 1 : -1]; +char ctz28[__builtin_ctzg(0x10U) == 4 ? 1 : -1]; +char ctz29[__builtin_ctzg(0x10U, 42) == 4 ? 1 : -1]; +char ctz30[__builtin_ctzg(1U << (BITSIZE(int) - 1)) == BITSIZE(int) - 1 ? 1 : -1]; +char ctz31[__builtin_ctzg(1U << (BITSIZE(int) - 1), 42) == BITSIZE(int) - 1 ? 1 : -1]; +int ctz32 = __builtin_ctzg(0UL); // expected-error {{not a compile-time constant}} +char ctz33[__builtin_ctzg(0UL, 42) == 42 ? 1 : -1]; +char ctz34[__builtin_ctzg(0x1UL) == 0 ? 1 : -1]; +char ctz35[__builtin_ctzg(0x1UL, 42) == 0 ? 1 : -1]; +char ctz36[__builtin_ctzg(0x10UL) == 4 ? 1 : -1]; +char ctz37[__builtin_ctzg(0x10UL, 42) == 4 ? 1 : -1]; +char ctz38[__builtin_ctzg(1UL << (BITSIZE(long) - 1)) == BITSIZE(long) - 1 ? 1 : -1]; +char ctz39[__builtin_ctzg(1UL << (BITSIZE(long) - 1), 42) == BITSIZE(long) - 1 ? 1 : -1]; +int ctz40 = __builtin_ctzg(0ULL); // expected-error {{not a compile-time constant}} +char ctz41[__builtin_ctzg(0ULL, 42) == 42 ? 1 : -1]; +char ctz42[__builtin_ctzg(0x1ULL) == 0 ? 1 : -1]; +char ctz43[__builtin_ctzg(0x1ULL, 42) == 0 ? 1 : -1]; +char ctz44[__builtin_ctzg(0x10ULL) == 4 ? 1 : -1]; +char ctz45[__builtin_ctzg(0x10ULL, 42) == 4 ? 1 : -1]; +char ctz46[__builtin_ctzg(1ULL << (BITSIZE(long long) - 1)) == BITSIZE(long long) - 1 ? 1 : -1]; +char ctz47[__builtin_ctzg(1ULL << (BITSIZE(long long) - 1), 42) == BITSIZE(long long) - 1 ? 1 : -1]; +#ifdef __SIZEOF_INT128__ +int ctz48 = __builtin_ctzg((unsigned __int128)0); // expected-error {{not a compile-time constant}} +char ctz49[__builtin_ctzg((unsigned __int128)0, 42) == 42 ? 1 : -1]; +char ctz50[__builtin_ctzg((unsigned __int128)0x1) == 0 ? 1 : -1]; +char ctz51[__builtin_ctzg((unsigned __int128)0x1, 42) == 0 ? 1 : -1]; +char ctz52[__builtin_ctzg((unsigned __int128)0x10) == 4 ? 1 : -1]; +char ctz53[__builtin_ctzg((unsigned __int128)0x10, 42) == 4 ? 1 : -1]; +char ctz54[__builtin_ctzg((unsigned __int128)1 << (BITSIZE(__int128) - 1)) == BITSIZE(__int128) - 1 ? 1 : -1]; +char ctz55[__builtin_ctzg((unsigned __int128)1 << (BITSIZE(__int128) - 1), 42) == BITSIZE(__int128) - 1 ? 1 : -1]; +#endif +int ctz56 = __builtin_ctzg((unsigned _BitInt(128))0); // expected-error {{not a compile-time constant}} +char ctz57[__builtin_ctzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1]; +char ctz58[__builtin_ctzg((unsigned _BitInt(128))0x1) == 0 ? 1 : -1]; +char ctz59[__builtin_ctzg((unsigned _BitInt(128))0x1, 42) == 0 ? 1 : -1]; +char ctz60[__builtin_ctzg((unsigned _BitInt(128))0x10) == 4 ? 1 : -1]; +char ctz61[__builtin_ctzg((unsigned _BitInt(128))0x10, 42) == 4 ? 1 : -1]; +char ctz62[__builtin_ctzg((unsigned _BitInt(128))1 << (BITSIZE(_BitInt(128)) - 1)) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1]; +char ctz63[__builtin_ctzg((unsigned _BitInt(128))1 << (BITSIZE(_BitInt(128)) - 1), 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1]; char popcount1[__builtin_popcount(0) == 0 ? 1 : -1]; char popcount2[__builtin_popcount(0xF0F0) == 8 ? 1 : -1]; diff --git a/clang/test/Sema/flexible-array-in-union.c b/clang/test/Sema/flexible-array-in-union.c index 5fabfbe0b1eaabfd6d73b5b8ab242dea45341880..dd5e8069665feabe88c56db27b6747d35fd6d4c1 100644 --- a/clang/test/Sema/flexible-array-in-union.c +++ b/clang/test/Sema/flexible-array-in-union.c @@ -1,13 +1,188 @@ -// RUN: %clang_cc1 %s -verify=c -fsyntax-only -// RUN: %clang_cc1 %s -verify -fsyntax-only -x c++ -// RUN: %clang_cc1 %s -verify -fsyntax-only -fms-compatibility -// RUN: %clang_cc1 %s -verify -fsyntax-only -fms-compatibility -x c++ +// RUN: %clang_cc1 %s -verify=stock,c -fsyntax-only +// RUN: %clang_cc1 %s -verify=stock,cpp -fsyntax-only -x c++ +// RUN: %clang_cc1 %s -verify=stock,cpp -fsyntax-only -fms-compatibility -x c++ +// RUN: %clang_cc1 %s -verify=stock,c,gnu -fsyntax-only -Wgnu-flexible-array-union-member -Wgnu-empty-struct +// RUN: %clang_cc1 %s -verify=stock,c,microsoft -fsyntax-only -fms-compatibility -Wmicrosoft // The test checks that an attempt to initialize union with flexible array // member with an initializer list doesn't crash clang. -union { char x[]; } r = {0}; // c-error {{flexible array member 'x' in a union is not allowed}} +union { char x[]; } r = {0}; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ +struct _name1 { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + }; +} name1 = { + 10, + 42, /* initializes "b" */ +}; -// expected-no-diagnostics +struct _name1i { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + }; +} name1i = { + .a = 10, + .b = 42, +}; + +/* Initialization of flexible array in a union is never allowed. */ +struct _name2 { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + }; +} name2 = { + 12, + 13, + { 'c' }, /* c-warning {{excess elements in struct initializer}} + cpp-error {{excess elements in struct initializer}} + */ +}; + +/* Initialization of flexible array in a union is never allowed. */ +struct _name2i { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + stock-note {{initialized flexible array member 'x' is here}} + */ + }; +} name2i = { + .a = 12, + .b = 13, /* stock-note {{previous initialization is here}} */ + .x = { 'c' }, /* stock-error {{initialization of flexible array member is not allowed}} + c-warning {{initializer overrides prior initialization of this subobject}} + cpp-error {{initializer partially overrides prior initialization of this subobject}} + */ +}; + +/* Flexible array initialization always allowed when not in a union, + and when struct has another member. + */ +struct _okay { + int a; + char x[]; +} okay = { + 22, + { 'x', 'y', 'z' }, +}; + +struct _okayi { + int a; + char x[]; +} okayi = { + .a = 22, + .x = { 'x', 'y', 'z' }, +}; + +struct _okay0 { + int a; + char x[]; +} okay0 = { }; + +struct _flex_extension { + char x[]; /* gnu-warning {{flexible array member 'x' in otherwise empty struct is a GNU extension}} + microsoft-warning {{flexible array member 'x' in otherwise empty struct is a Microsoft extension}} + */ +} flex_extension = { + { 'x', 'y', 'z' }, +}; + +struct _flex_extensioni { + char x[]; /* gnu-warning {{flexible array member 'x' in otherwise empty struct is a GNU extension}} + microsoft-warning {{flexible array member 'x' in otherwise empty struct is a Microsoft extension}} + */ +} flex_extensioni = { + .x = { 'x', 'y', 'z' }, +}; + +struct already_hidden { + int a; + union { + int b; + struct { + struct { } __empty; // gnu-warning {{empty struct is a GNU extension}} + char x[]; + }; + }; +}; +struct still_zero_sized { + struct { } __unused; // gnu-warning {{empty struct is a GNU extension}} + int x[]; +}; + +struct warn1 { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + }; +}; + +struct warn2 { + int x[]; /* gnu-warning {{flexible array member 'x' in otherwise empty struct is a GNU extension}} + microsoft-warning {{flexible array member 'x' in otherwise empty struct is a Microsoft extension}} + */ +}; + +union warn3 { + short x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ +}; + +struct quiet1 { + int a; + short x[]; +}; + +struct _not_at_end { + union { short x[]; }; /* stock-warning-re {{field '' with variable sized type '{{.*}}' not at the end of a struct or class is a GNU extension}} + gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + int y; +} not_at_end = {{}, 3}; + +struct _not_at_end_s { + struct { int a; short x[]; }; /* stock-warning-re {{field '' with variable sized type '{{.*}}' not at the end of a struct or class is a GNU extension}} */ + int y; +} not_at_end_s = {{}, 3}; + +struct { + int a; + union { /* stock-warning-re {{field '' with variable sized type '{{.*}}' not at the end of a struct or class is a GNU extension}} */ + short x[]; /* stock-note {{initialized flexible array member 'x' is here}} + gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + int b; + }; + int c; + int d; +} i_f = { 4, + {5}, /* stock-error {{initialization of flexible array member is not allowed}} */ + {}, + 6}; + +// expected-no-diagnostics diff --git a/clang/test/Sema/transparent-union.c b/clang/test/Sema/transparent-union.c index c134a7a9b1c4d0077d592c7a7c73eb52917604c7..f02c2298b51ce1433fecfa5709f5fad15359ee9c 100644 --- a/clang/test/Sema/transparent-union.c +++ b/clang/test/Sema/transparent-union.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wgnu-flexible-array-union-member %s typedef union { int *ip; float *fp; @@ -131,7 +131,7 @@ union pr15134v2 { union pr30520v { void b; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'void'}} -union pr30520a { int b[]; } __attribute__((transparent_union)); // expected-error {{flexible array member 'b' in a union is not allowed}} +union pr30520a { int b[]; } __attribute__((transparent_union)); // expected-warning {{flexible array member 'b' in a union is a GNU extension}} // expected-note@+1 2 {{forward declaration of 'struct stb'}} union pr30520s { struct stb b; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'struct stb'}} 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/test/SemaCXX/warn-exit-time-destructors.cpp b/clang/test/SemaCXX/warn-exit-time-destructors.cpp index 2f14243cb48c470ad86a2124eda1c7e37c09d598..55ae37d7368f884f6ce1a54a95f0d8f76927dc36 100644 --- a/clang/test/SemaCXX/warn-exit-time-destructors.cpp +++ b/clang/test/SemaCXX/warn-exit-time-destructors.cpp @@ -51,6 +51,15 @@ struct A { ~A(); }; } namespace test5 { + struct A { ~A(); }; + [[clang::always_destroy]] A a; // no warning + + void func() { + [[clang::always_destroy]] static A a; // no warning + } +} + +namespace test6 { #if __cplusplus >= 202002L #define CPP20_CONSTEXPR constexpr #else @@ -68,3 +77,4 @@ namespace test5 { T t; // expected-warning {{exit-time destructor}} #undef CPP20_CONSTEXPR } + diff --git a/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..92dd06d5a3309524616c21d549ad060ba33fe1db --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_cos +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sin +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log2 +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log10 +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sqrt +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_trunc + + +double2 test_double_builtin(double2 p0) { + return TEST_FUNC(p0); + // expected-error@-1 {{passing 'double2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..949028aacf24b610c7932f75f8a544190395d9f0 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify + +double2 test_double_builtin(double2 p0, double2 p1) { + return __builtin_elementwise_pow(p0,p1); + // expected-error@-1 {{passing 'double2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..6e66db6d1cca9e2f110980cbd88ba47d3d375e14 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify + + +double2 test_int_builtin(double2 p0) { + return __builtin_elementwise_bitreverse(p0); + // expected-error@-1 {{1st argument must be a vector of integers (was 'double2' (aka 'vector'))}} +} + +int2 test_int_builtin(int2 p0) { + return __builtin_elementwise_bitreverse(p0); + // expected-error@-1 {{passing 'int2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int' (vector of 2 'unsigned int' values)}} +} diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index b7ea0d003a52d74a3baf53292fbb505c1d63097c..787cc809e253534a3f8bfab4246920fc001ffe9c 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++20 -verify %s +// RUN: %clang_cc1 -std=c++20 -ferror-limit 0 -verify %s namespace PR47043 { template concept True = true; @@ -1114,3 +1114,11 @@ void foo() { } } // namespace GH64808 + +namespace GH86757_1 { +template concept b = false; +template concept c = b<>; +template concept f = c< d >; +template struct e; // expected-note {{}} +template struct e; // expected-error {{class template partial specialization is not more specialized than the primary template}} +} 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..71532c9cf24d17f9b19d0b0c0778d6661a9adc6c 100644 --- a/clang/tools/clang-installapi/InstallAPIOpts.td +++ b/clang/tools/clang-installapi/InstallAPIOpts.td @@ -29,3 +29,47 @@ 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; +def public_umbrella_header : Separate<["-"], "public-umbrella-header">, + MetaVarName<"">, HelpText<"Specify the public umbrella header location">; +def public_umbrella_header_EQ : Joined<["--"], "public-umbrella-header=">, + Alias; +def private_umbrella_header : Separate<["-"], "private-umbrella-header">, + MetaVarName<"">, HelpText<"Specify the private umbrella header location">; +def private_umbrella_header_EQ : Joined<["--"], "private-umbrella-header=">, + Alias; +def project_umbrella_header : Separate<["-"], "project-umbrella-header">, + MetaVarName<"">, HelpText<"Specify the project umbrella header location">; +def project_umbrella_header_EQ : Joined<["--"], "project-umbrella-header=">, + Alias; diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp index b8696bb7896d8662fec1782fcdb5ba42b1f87407..8e4a1b019fd816aa73b531ec163d2a09b3eda22e 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,45 @@ 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 {}; + + // Handle umbrella headers. + if (const Arg *A = ParsedArgs.getLastArg(OPT_public_umbrella_header)) + DriverOpts.PublicUmbrellaHeader = A->getValue(); + + if (const Arg *A = ParsedArgs.getLastArg(OPT_private_umbrella_header)) + DriverOpts.PrivateUmbrellaHeader = A->getValue(); + + if (const Arg *A = ParsedArgs.getLastArg(OPT_project_umbrella_header)) + DriverOpts.ProjectUmbrellaHeader = A->getValue(); + /// Any unclaimed arguments should be forwarded to the clang driver. std::vector ClangDriverArgs(ParsedArgs.size()); for (const Arg *A : ParsedArgs) { @@ -273,6 +333,15 @@ Options::Options(DiagnosticsEngine &Diag, FileManager *FM, } } +static const Regex Rule("(.+)/(.+)\\.framework/"); +static StringRef getFrameworkNameFromInstallName(StringRef InstallName) { + SmallVector Match; + Rule.match(InstallName, &Match); + if (Match.empty()) + return ""; + return Match.back(); +} + InstallAPIContext Options::createContext() { InstallAPIContext Ctx; Ctx.FM = FM; @@ -289,6 +358,11 @@ InstallAPIContext Options::createContext() { Ctx.OutputLoc = DriverOpts.OutputPath; Ctx.LangMode = FEOpts.LangMode; + // Attempt to find umbrella headers by capturing framework name. + StringRef FrameworkName; + if (!LinkerOpts.IsDylib) + FrameworkName = getFrameworkNameFromInstallName(LinkerOpts.InstallName); + // Process inputs. for (const std::string &ListPath : DriverOpts.FileLists) { auto Buffer = FM->getBufferForFile(ListPath); @@ -302,6 +376,128 @@ 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; + 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) { + assert(Type != HeaderType::Unknown && "Missing header 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(); + + // Mark any explicit or inferred umbrella headers. If one exists, move + // that to the beginning of the input headers. + auto MarkandMoveUmbrellaInHeaders = [&](llvm::Regex &Regex, + HeaderType Type) -> bool { + auto It = find_if(Ctx.InputHeaders, [&Regex, Type](const HeaderFile &H) { + return (H.getType() == Type) && Regex.match(H.getPath()); + }); + + if (It == Ctx.InputHeaders.end()) + return false; + It->setUmbrellaHeader(); + + // Because there can be an umbrella header per header type, + // find the first non umbrella header to swap position with. + auto BeginPos = find_if(Ctx.InputHeaders, [](const HeaderFile &H) { + return !H.isUmbrellaHeader(); + }); + if (BeginPos != Ctx.InputHeaders.end() && BeginPos < It) + std::swap(*BeginPos, *It); + return true; + }; + + auto FindUmbrellaHeader = [&](StringRef HeaderPath, HeaderType Type) -> bool { + assert(Type != HeaderType::Unknown && "Missing header type."); + if (!HeaderPath.empty()) { + auto EscapedString = Regex::escape(HeaderPath); + Regex UmbrellaRegex(EscapedString); + if (!MarkandMoveUmbrellaInHeaders(UmbrellaRegex, Type)) { + Diags->Report(diag::err_no_such_umbrella_header_file) + << HeaderPath << (unsigned)Type; + return false; + } + } else if (!FrameworkName.empty() && (Type != HeaderType::Project)) { + auto UmbrellaName = "/" + Regex::escape(FrameworkName); + if (Type == HeaderType::Public) + UmbrellaName += "\\.h"; + else + UmbrellaName += "[_]?Private\\.h"; + Regex UmbrellaRegex(UmbrellaName); + MarkandMoveUmbrellaInHeaders(UmbrellaRegex, Type); + } + return true; + }; + if (!FindUmbrellaHeader(DriverOpts.PublicUmbrellaHeader, + HeaderType::Public) || + !FindUmbrellaHeader(DriverOpts.PrivateUmbrellaHeader, + HeaderType::Private) || + !FindUmbrellaHeader(DriverOpts.ProjectUmbrellaHeader, + HeaderType::Project)) + return Ctx; // 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..3671e4c8274bd30674b9a35ae2985d9f16ba55b8 100644 --- a/clang/tools/clang-installapi/Options.h +++ b/clang/tools/clang-installapi/Options.h @@ -31,6 +31,33 @@ struct DriverOptions { /// \brief Path to input file lists (JSON). llvm::MachO::PathSeq FileLists; + /// \brief Path to public umbrella header. + std::string PublicUmbrellaHeader; + + /// \brief Path to private umbrella header. + std::string PrivateUmbrellaHeader; + + /// \brief Path to project umbrella header. + std::string ProjectUmbrellaHeader; + + /// \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 +130,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/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp index 292d524f00abd697bf1aec0822965a1c2ec00b0f..991767dc4c49c67e91e27ae474e9f6ce956c93a0 100644 --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -680,6 +680,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) { TCALLINGCONV(PreserveAll); TCALLINGCONV(M68kRTD); TCALLINGCONV(PreserveNone); + TCALLINGCONV(RISCVVectorCall); case CC_SpirFunction: return CXCallingConv_Unexposed; case CC_AMDGPUKernelCall: return CXCallingConv_Unexposed; case CC_OpenCLKernel: return CXCallingConv_Unexposed; diff --git a/clang/unittests/AST/DeclPrinterTest.cpp b/clang/unittests/AST/DeclPrinterTest.cpp index e024c41e03b48433e64501597ec4efdf10a1c02a..8a29d0544a04bfb0d3677f555290c72de16005bf 100644 --- a/clang/unittests/AST/DeclPrinterTest.cpp +++ b/clang/unittests/AST/DeclPrinterTest.cpp @@ -1386,6 +1386,75 @@ TEST(DeclPrinter, TestTemplateArgumentList16) { ASSERT_TRUE(PrintedDeclCXX11Matches(Code, "NT2", "int NT2 = 5")); } +TEST(DeclPrinter, TestCXXRecordDecl17) { + ASSERT_TRUE(PrintedDeclCXX98Matches("template struct Z {};" + "struct X {};" + "Z A;", + "A", "Z A")); + (void)[](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }; +} + +TEST(DeclPrinter, TestCXXRecordDecl18) { + ASSERT_TRUE(PrintedDeclCXX98Matches("template struct Z {};" + "struct X {};" + "Z A;" + "template " + "struct Y{};" + "Y, 2> B;", + "B", "Y, 2> B")); + (void)[](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }; +} + +TEST(DeclPrinter, TestCXXRecordDecl19) { + ASSERT_TRUE(PrintedDeclCXX98Matches("template struct Z {};" + "struct X {};" + "Z A;" + "template " + "struct Y{};" + "Y, 2> B;", + "B", "Y, 2> B")); + (void)[](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = true; }; +} +TEST(DeclPrinter, TestCXXRecordDecl20) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template class Inner;" + "template " + "class Inner{Inner(T val){}};" + "template class Outer {" + "public:" + "struct NestedStruct {" + "int nestedValue;" + "NestedStruct(int val) : nestedValue(val) {}" + "};" + "InnerClass innerInstance;" + "Outer(const InnerClass &inner) : innerInstance(inner) {}" + "};" + "Outer, 5>::NestedStruct nestedInstance(100);", + "nestedInstance", + "Outer, 5>::NestedStruct nestedInstance(100)")); + (void)[](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }; +} + +TEST(DeclPrinter, TestCXXRecordDecl21) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template class Inner;" + "template " + "class Inner{Inner(T val){}};" + "template class Outer {" + "public:" + "struct NestedStruct {" + "int nestedValue;" + "NestedStruct(int val) : nestedValue(val) {}" + "};" + "InnerClass innerInstance;" + "Outer(const InnerClass &inner) : innerInstance(inner) {}" + "};" + "Outer, 5>::NestedStruct nestedInstance(100);", + "nestedInstance", + "Outer, 5>::NestedStruct nestedInstance(100)")); + (void)[](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = true; }; +} + TEST(DeclPrinter, TestFunctionParamUglified) { llvm::StringLiteral Code = R"cpp( class __c; 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..d1e977dfa66af5d5f0b8786db30811398ba00768 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);"); @@ -19056,6 +19066,11 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { verifyFormat("int a(int x);\n" "double b();", Alignment); + verifyFormat("int a(const Test & = Test());\n" + "int a1(int &foo, const Test & = Test());\n" + "int a2(int &foo, const Test &name = Test());\n" + "double b();", + Alignment); verifyFormat("struct Test {\n" " Test(const Test &) = default;\n" " ~Test() = default;\n" @@ -19092,6 +19107,13 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { " int x,\n" " bool y);", Alignment); + // Set ColumnLimit low so that we break the argument list in multiple lines. + Alignment.ColumnLimit = 35; + verifyFormat("int a3(SomeTypeName1 &x,\n" + " SomeTypeName2 &y,\n" + " const Test & = Test());\n" + "double b();", + Alignment); Alignment.ColumnLimit = OldColumnLimit; // Ensure function pointers don't screw up recursive alignment verifyFormat("int a(int x, void (*fp)(int y));\n" @@ -19149,13 +19171,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 @@ -19277,6 +19299,10 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { "int foobar;", AlignmentLeft); + verifyFormat("int a(SomeType& foo, const Test& = Test());\n" + "double b();", + AlignmentLeft); + // PAS_Middle FormatStyle AlignmentMiddle = Alignment; AlignmentMiddle.PointerAlignment = FormatStyle::PAS_Middle; @@ -19337,6 +19363,10 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { "int foobar;", AlignmentMiddle); + verifyFormat("int a(SomeType & foo, const Test & = Test());\n" + "double b();", + AlignmentMiddle); + Alignment.AlignConsecutiveAssignments.Enabled = false; Alignment.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign; verifyFormat("#define A \\\n" @@ -21090,7 +21120,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 +21380,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/utils/TableGen/MveEmitter.cpp b/clang/utils/TableGen/MveEmitter.cpp index 3a90eee5f1c92108387b01a04bc9d8e82f4b6056..aa20c758d84a60d90160d1c995e6647c02c4044f 100644 --- a/clang/utils/TableGen/MveEmitter.cpp +++ b/clang/utils/TableGen/MveEmitter.cpp @@ -575,7 +575,7 @@ public: // Emit code to generate this result as a Value *. std::string asValue() override { if (AddressType) - return "(" + varname() + ".getPointer())"; + return "(" + varname() + ".emitRawPointer(*this))"; return Result::asValue(); } bool hasIntegerValue() const override { return Immediate; } diff --git a/clang/utils/TableGen/RISCVVEmitter.cpp b/clang/utils/TableGen/RISCVVEmitter.cpp index 8513174c88bfc3242635774806bc1fcc37293523..5e41ef9f9d2684037988014b79d87755847959d7 100644 --- a/clang/utils/TableGen/RISCVVEmitter.cpp +++ b/clang/utils/TableGen/RISCVVEmitter.cpp @@ -334,10 +334,6 @@ void RVVEmitter::createHeader(raw_ostream &OS) { OS << "#include \n"; OS << "#include \n\n"; - OS << "#ifndef __riscv_vector\n"; - OS << "#error \"Vector intrinsics require the vector extension.\"\n"; - OS << "#endif\n\n"; - OS << "#ifdef __cplusplus\n"; OS << "extern \"C\" {\n"; OS << "#endif\n\n"; diff --git a/clang/utils/analyzer/exploded-graph-rewriter.py b/clang/utils/analyzer/exploded-graph-rewriter.py index c7c6315a0a27d1912144bf8dac2a6232056bd117..5eaa7738103f795059fa5b9f913ac3cf16ef2b09 100755 --- a/clang/utils/analyzer/exploded-graph-rewriter.py +++ b/clang/utils/analyzer/exploded-graph-rewriter.py @@ -479,11 +479,19 @@ class ExplodedGraph: # A visitor that dumps the ExplodedGraph into a DOT file with fancy HTML-based # syntax highlighing. class DotDumpVisitor: - def __init__(self, do_diffs, dark_mode, gray_mode, topo_mode, dump_dot_only): + def __init__( + self, do_diffs, dark_mode, gray_mode, topo_mode, dump_html_only, dump_dot_only + ): + assert not (dump_html_only and dump_dot_only), ( + "Option dump_html_only and dump_dot_only are conflict, " + "they cannot be true at the same time." + ) + self._do_diffs = do_diffs self._dark_mode = dark_mode self._gray_mode = gray_mode self._topo_mode = topo_mode + self._dump_html_only = dump_html_only self._dump_dot_only = dump_dot_only self._output = [] @@ -998,6 +1006,8 @@ class DotDumpVisitor: '%s' % ("#1a1a1a" if self._dark_mode else "white", svg), ) + if self._dump_html_only: + return if sys.platform == "win32": os.startfile(filename) elif sys.platform == "darwin": @@ -1176,7 +1186,17 @@ def main(): default=False, help="black-and-white mode", ) - parser.add_argument( + dump_conflict = parser.add_mutually_exclusive_group() + dump_conflict.add_argument( + "--dump-html-only", + action="store_const", + dest="dump_html_only", + const=True, + default=False, + help="dump the rewritten egraph to a temporary HTML file, " + "but do not open it immediately as by default", + ) + dump_conflict.add_argument( "--dump-dot-only", action="store_const", dest="dump_dot_only", @@ -1206,7 +1226,12 @@ def main(): explorer = BasicExplorer() visitor = DotDumpVisitor( - args.diff, args.dark, args.gray, args.topology, args.dump_dot_only + args.diff, + args.dark, + args.gray, + args.topology, + args.dump_html_only, + args.dump_dot_only, ) for trimmer in trimmers: 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) { - - - -