diff --git a/.github/workflows/commit-access-review.py b/.github/workflows/commit-access-review.py index 8ea9b1fcc2fb0..91d3a61cdcb17 100644 --- a/.github/workflows/commit-access-review.py +++ b/.github/workflows/commit-access-review.py @@ -62,57 +62,9 @@ def __repr__(self): ) -def run_graphql_query( - query: str, variables: dict, token: str, retry: bool = True -) -> dict: - """ - This function submits a graphql query and returns the results as a - dictionary. - """ - s = requests.Session() - retries = requests.adapters.Retry(total=8, backoff_factor=2, status_forcelist=[504]) - s.mount("https://", requests.adapters.HTTPAdapter(max_retries=retries)) - - headers = { - "Authorization": "bearer {}".format(token), - # See - # https://github.blog/2021-11-16-graphql-global-id-migration-update/ - "X-Github-Next-Global-ID": "1", - } - request = s.post( - url="https://api.github.com/graphql", - json={"query": query, "variables": variables}, - headers=headers, - ) - - rate_limit = request.headers.get("X-RateLimit-Remaining") - print(rate_limit) - if rate_limit and int(rate_limit) < 10: - reset_time = int(request.headers["X-RateLimit-Reset"]) - while reset_time - int(time.time()) > 0: - time.sleep(60) - print( - "Waiting until rate limit reset", - reset_time - int(time.time()), - "seconds remaining", - ) - - if request.status_code == 200: - if "data" not in request.json(): - print(request.json()) - sys.exit(1) - return request.json()["data"] - elif retry: - return run_graphql_query(query, variables, token, False) - else: - raise Exception( - "Failed to run graphql query\nquery: {}\nerror: {}".format( - query, request.json() - ) - ) - - -def check_manual_requests(start_date: datetime.datetime, token: str) -> list[str]: +def check_manual_requests( + gh: github.Github, start_date: datetime.datetime +) -> list[str]: """ Return a list of users who have been asked since ``start_date`` if they want to keep their commit access. @@ -137,10 +89,13 @@ def check_manual_requests(start_date: datetime.datetime, token: str) -> list[str """ formatted_start_date = start_date.strftime("%Y-%m-%dT%H:%M:%S") variables = { - "query": f"type:issue created:>{formatted_start_date} org:llvm repo:llvm-project label:infrastructure:commit-access" + "query": f"type:issue created:>{formatted_start_date} org:llvm repo:llvm-project label:infra:commit-access" } - data = run_graphql_query(query, variables, token) + res_header, res_data = gh._Github__requester.graphql_query( + query=query, variables=variables + ) + data = res_data["data"] users = [] for issue in data["search"]["nodes"]: users.extend([user[1:] for user in re.findall("@[^ ,\n]+", issue["body"])]) @@ -148,7 +103,7 @@ def check_manual_requests(start_date: datetime.datetime, token: str) -> list[str return users -def get_num_commits(user: str, start_date: datetime.datetime, token: str) -> int: +def get_num_commits(gh: github.Github, user: str, start_date: datetime.datetime) -> int: """ Get number of commits that ``user`` has been made since ``start_date`. """ @@ -166,7 +121,10 @@ def get_num_commits(user: str, start_date: datetime.datetime, token: str) -> int } """ - data = run_graphql_query(user_query, variables, token) + res_header, res_data = gh._Github__requester.graphql_query( + query=user_query, variables=variables + ) + data = res_data["data"] variables["user_id"] = data["user"]["id"] query = """ @@ -193,7 +151,10 @@ def get_num_commits(user: str, start_date: datetime.datetime, token: str) -> int } """ count = 0 - data = run_graphql_query(query, variables, token) + res_header, res_data = gh._Github__requester.graphql_query( + query=query, variables=variables + ) + data = res_data["data"] for repo in data["organization"]["teams"]["nodes"][0]["repositories"]["nodes"]: count += int(repo["ref"]["target"]["history"]["totalCount"]) if count >= User.THRESHOLD: @@ -202,7 +163,7 @@ def get_num_commits(user: str, start_date: datetime.datetime, token: str) -> int def is_new_committer_query_repo( - user: str, start_date: datetime.datetime, token: str + gh: github.Github, user: str, start_date: datetime.datetime ) -> bool: """ Determine if ``user`` is a new committer. A new committer can keep their @@ -220,7 +181,10 @@ def is_new_committer_query_repo( } """ - data = run_graphql_query(user_query, variables, token) + res_header, res_data = gh._Github__requester.graphql_query( + query=user_query, variables=variables + ) + data = res_data["data"] variables["owner"] = "llvm" variables["user_id"] = data["user"]["id"] variables["start_date"] = start_date.strftime("%Y-%m-%dT%H:%M:%S") @@ -245,7 +209,10 @@ def is_new_committer_query_repo( } """ - data = run_graphql_query(query, variables, token) + res_header, res_data = gh._Github__requester.graphql_query( + query=query, variables=variables + ) + data = res_data["data"] repo = data["organization"]["repository"] commits = repo["ref"]["target"]["history"]["nodes"] if len(commits) == 0: @@ -256,18 +223,22 @@ def is_new_committer_query_repo( return True -def is_new_committer(user: str, start_date: datetime.datetime, token: str) -> bool: +def is_new_committer( + gh: github.Github, user: str, start_date: datetime.datetime +) -> bool: """ Wrapper around is_new_commiter_query_repo to handle exceptions. """ try: - return is_new_committer_query_repo(user, start_date, token) + return is_new_committer_query_repo(gh, user, start_date) except: pass return True -def get_review_count(user: str, start_date: datetime.datetime, token: str) -> int: +def get_review_count( + gh: github.Github, user: str, start_date: datetime.datetime +) -> int: """ Return the number of reviews that ``user`` has done since ``start_date``. """ @@ -286,11 +257,14 @@ def get_review_count(user: str, start_date: datetime.datetime, token: str) -> in "query": f"type:pr commenter:{user} -author:{user} merged:>{formatted_start_date} org:llvm", } - data = run_graphql_query(query, variables, token) + res_header, res_data = gh._Github__requester.graphql_query( + query=query, variables=variables + ) + data = res_data["data"] return int(data["search"]["issueCount"]) -def count_prs(triage_list: dict, start_date: datetime.datetime, token: str): +def count_prs(gh: github.Github, triage_list: dict, start_date: datetime.datetime): """ Fetch all the merged PRs for the project since ``start_date`` and update ``triage_list`` with the number of PRs merged for each user. @@ -329,7 +303,10 @@ def count_prs(triage_list: dict, start_date: datetime.datetime, token: str): has_next_page = True while has_next_page: print(variables) - data = run_graphql_query(query, variables, token) + res_header, res_data = gh._Github__requester.graphql_query( + query=query, variables=variables + ) + data = res_data["data"] for pr in data["search"]["nodes"]: # Users can be None if the user has been deleted. if not pr["author"]: @@ -365,14 +342,14 @@ def main(): print("Start:", len(triage_list), "triagers") # Step 0 Check if users have requested commit access in the last year. - for user in check_manual_requests(one_year_ago, token): + for user in check_manual_requests(gh, one_year_ago): if user in triage_list: print(user, "requested commit access in the last year.") del triage_list[user] print("After Request Check:", len(triage_list), "triagers") # Step 1 count all PRs authored or merged - count_prs(triage_list, one_year_ago, token) + count_prs(gh, triage_list, one_year_ago) print("After PRs:", len(triage_list), "triagers") @@ -381,7 +358,7 @@ def main(): # Step 2 check for reviews for user in list(triage_list.keys()): - review_count = get_review_count(user, one_year_ago, token) + review_count = get_review_count(gh, user, one_year_ago) triage_list[user].add_reviewed(review_count) print("After Reviews:", len(triage_list), "triagers") @@ -391,7 +368,7 @@ def main(): # Step 3 check for number of commits for user in list(triage_list.keys()): - num_commits = get_num_commits(user, one_year_ago, token) + num_commits = get_num_commits(gh, user, one_year_ago) # Override the total number of commits to not double count commits and # authored PRs. triage_list[user].set_authored(num_commits) @@ -401,7 +378,7 @@ def main(): # Step 4 check for new committers for user in list(triage_list.keys()): print("Checking", user) - if is_new_committer(user, one_year_ago, token): + if is_new_committer(gh, user, one_year_ago): print("Removing new committer: ", user) del triage_list[user] diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index fe9c70cf1f5a9..0bb018b780a2a 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -148,14 +148,14 @@ jobs: cmake -B libunwind-build -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_RUNTIMES="libunwind" -DLLVM_ENABLE_SPHINX=ON ./runtimes TZ=UTC ninja -C libunwind-build docs-libunwind-html mkdir built-docs/libunwind - cp -r libunwind-build/docs/* built-docs/libunwind + cp -r libunwind-build/libunwind/docs/* built-docs/libunwind - name: Build libcxx docs if: steps.docs-changed-subprojects.outputs.libcxx_any_changed == 'true' run: | cmake -B libcxx-build -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_RUNTIMES="libcxxabi;libcxx;libunwind" -DLLVM_ENABLE_SPHINX=ON ./runtimes TZ=UTC ninja -C libcxx-build docs-libcxx-html mkdir built-docs/libcxx - cp -r libcxx-build/docs/* built-docs/libcxx/ + cp -r libcxx-build/libcxx/docs/* built-docs/libcxx/ - name: Build libc docs if: steps.docs-changed-subprojects.outputs.libc_any_changed == 'true' run: | diff --git a/.github/workflows/libc-fullbuild-tests.yml b/.github/workflows/libc-fullbuild-tests.yml new file mode 100644 index 0000000000000..fb73aa392f343 --- /dev/null +++ b/.github/workflows/libc-fullbuild-tests.yml @@ -0,0 +1,76 @@ +# This workflow is for pre-commit testing of the LLVM-libc project. +name: LLVM-libc Pre-commit Fullbuild Tests + +on: + pull_request: + branches: [ "main" ] + paths: + - 'libc/**' + - '.github/workflows/libc-fullbuild-tests.yml' + +jobs: + build: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + include: + - c_compiler: clang + cpp_compiler: clang++ + # TODO: add back gcc build when it is fixed + # - c_compiler: gcc + # cpp_compiler: g++ + steps: + - uses: actions/checkout@v4 + + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + max-size: 1G + key: libc_fullbuild_${{ matrix.c_compiler }} + variant: sccache + + - name: Prepare dependencies (Ubuntu) + run: | + sudo apt-get update + sudo apt-get install -y libmpfr-dev libgmp-dev libmpc-dev ninja-build linux-headers-generic linux-libc-dev + sudo ln -sf /usr/include/$(uname -p)-linux-gnu/asm /usr/include/asm + + - name: Set reusable strings + id: strings + shell: bash + run: | + echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + echo "build-install-dir=${{ github.workspace }}/install" >> "$GITHUB_OUTPUT" + + - name: Configure CMake + run: > + cmake -B ${{ steps.strings.outputs.build-output-dir }} + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} + -DCMAKE_BUILD_TYPE=MinSizeRel + -DCMAKE_C_COMPILER_LAUNCHER=sccache + -DCMAKE_CXX_COMPILER_LAUNCHER=sccache + -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.build-install-dir }} + -DLLVM_ENABLE_RUNTIMES="libc;compiler-rt" + -DLLVM_LIBC_FULL_BUILD=ON + -DLLVM_LIBC_INCLUDE_SCUDO=ON + -DCOMPILER_RT_BUILD_SCUDO_STANDALONE_WITH_LLVM_LIBC=ON + -DCOMPILER_RT_BUILD_GWP_ASAN=OFF + -DCOMPILER_RT_SCUDO_STANDALONE_BUILD_SHARED=OFF + -G Ninja + -S ${{ github.workspace }}/runtimes + + - name: Build + run: > + cmake + --build ${{ steps.strings.outputs.build-output-dir }} + --parallel + --target install + + - name: Test + run: > + cmake + --build ${{ steps.strings.outputs.build-output-dir }} + --parallel + --target check-libc diff --git a/.github/workflows/libc-overlay-tests.yml b/.github/workflows/libc-overlay-tests.yml new file mode 100644 index 0000000000000..d0cdfdef99fe9 --- /dev/null +++ b/.github/workflows/libc-overlay-tests.yml @@ -0,0 +1,92 @@ +# This workflow is for pre-commit testing of the LLVM-libc project. +name: LLVM-libc Pre-commit Overlay Tests + +on: + pull_request: + branches: [ "main" ] + paths: + - 'libc/**' + - '.github/workflows/libc-overlay-tests.yml' + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. + fail-fast: false + matrix: + include: + # TODO: add linux gcc when it is fixed + - os: ubuntu-24.04 + compiler: + c_compiler: clang + cpp_compiler: clang++ + - os: windows-2022 + compiler: + c_compiler: clang-cl + cpp_compiler: clang-cl + - os: macos-14 + compiler: + c_compiler: clang + cpp_compiler: clang++ + + steps: + - uses: actions/checkout@v4 + + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1 + with: + max-size: 1G + key: libc_overlay_build_${{ matrix.os }}_${{ matrix.compiler.c_compiler }} + variant: sccache + + - name: Prepare dependencies (Ubuntu) + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install -y libmpfr-dev libgmp-dev libmpc-dev ninja-build + + - name: Prepare dependencies (Windows) + if: runner.os == 'Windows' + run: | + choco install ninja + + - name: Prepare dependencies (macOS) + if: runner.os == 'macOS' + run: | + brew install ninja + + - name: Set reusable strings + id: strings + shell: bash + run: | + echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + + - name: Configure CMake + run: > + cmake -B ${{ steps.strings.outputs.build-output-dir }} + -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cpp_compiler }} + -DCMAKE_C_COMPILER=${{ matrix.compiler.c_compiler }} + -DCMAKE_BUILD_TYPE=MinSizeRel + -DCMAKE_C_COMPILER_LAUNCHER=sccache + -DCMAKE_CXX_COMPILER_LAUNCHER=sccache + -DCMAKE_POLICY_DEFAULT_CMP0141=NEW + -DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=Embedded + -DLLVM_ENABLE_RUNTIMES=libc + -G Ninja + -S ${{ github.workspace }}/runtimes + + - name: Build + run: > + cmake + --build ${{ steps.strings.outputs.build-output-dir }} + --parallel + --config MinSizeRel + --target libc + + - name: Test + run: > + cmake + --build ${{ steps.strings.outputs.build-output-dir }} + --parallel + --target check-libc diff --git a/.github/workflows/libcxx-restart-preempted-jobs.yaml b/.github/workflows/libcxx-restart-preempted-jobs.yaml index 21879ce19c27c..82d84c01c92af 100644 --- a/.github/workflows/libcxx-restart-preempted-jobs.yaml +++ b/.github/workflows/libcxx-restart-preempted-jobs.yaml @@ -130,3 +130,91 @@ jobs: run_id: context.payload.workflow_run.id }) await create_check_run('success', 'Restarted workflow run due to preempted job') + + restart-test: + if: github.repository_owner == 'llvm' && (github.event.workflow_run.conclusion == 'failure' || github.event.workflow_run.conclusion == 'cancelled') && github.event.actor.login == 'ldionne' # TESTING ONLY + name: "Restart Job (test)" + permissions: + statuses: read + checks: write + actions: write + runs-on: ubuntu-latest + steps: + - name: "Restart Job (test)" + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 + with: + script: | + const FAILURE_REGEX = /Process completed with exit code 1./ + const PREEMPTION_REGEX = /(The runner has received a shutdown signal)|(The operation was canceled)/ + + function log(msg) { + core.notice(msg) + } + + const wf_run = context.payload.workflow_run + log(`Running on "${wf_run.display_title}" by @${wf_run.actor.login} (event: ${wf_run.event})\nWorkflow run URL: ${wf_run.html_url}`) + + log('Listing check runs for suite') + const check_suites = await github.rest.checks.listForSuite({ + owner: context.repo.owner, + repo: context.repo.repo, + check_suite_id: context.payload.workflow_run.check_suite_id, + per_page: 100 // FIXME: We don't have 100 check runs yet, but we should handle this better. + }) + + preemptions = []; + legitimate_failures = []; + for (check_run of check_suites.data.check_runs) { + log(`Checking check run: ${check_run.id}`); + if (check_run.status != 'completed') { + log('Check run was not completed. Skipping.'); + continue; + } + + if (check_run.conclusion != 'failure' && check_run.conclusion != 'cancelled') { + log(`Check run had conclusion: ${check_run.conclusion}. Skipping.`); + continue; + } + + annotations = await github.rest.checks.listAnnotations({ + owner: context.repo.owner, + repo: context.repo.repo, + check_run_id: check_run.id + }) + + preemption_annotation = annotations.data.find(function(annotation) { + return annotation.annotation_level == 'failure' && + annotation.message.match(PREEMPTION_REGEX) != null; + }); + if (preemption_annotation != null) { + log(`Found preemption message: ${preemption_annotation.message}`); + preemptions.push(check_run); + break; + } + + failure_annotation = annotations.data.find(function(annotation) { + return annotation.annotation_level == 'failure' && + annotation.message.match(FAILURE_REGEX) != null; + }); + if (failure_annotation != null) { + log(`Found legitimate failure annotation: ${failure_annotation.message}`); + legitimate_failures.push(check_run); + break; + } + } + + if (preemptions) { + log('Found some preempted jobs'); + if (legitimate_failures) { + log('Also found some legitimate failures, so not restarting the workflow.'); + } else { + log('Did not find any legitimate failures. Restarting workflow.'); + await github.rest.actions.reRunWorkflowFailedJobs({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id + }) + } + } else { + log('Did not find any preempted jobs. Not restarting the workflow.'); + } diff --git a/.gitignore b/.gitignore index 0e7c6c7900133..a84268a7f6863 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,8 @@ autoconf/autom4te.cache # VS2017 and VSCode config files. .vscode .vs +#zed config files +.zed # pythonenv for github Codespaces pythonenv* # clangd index. (".clangd" is a config file now, thus trailing slash) diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h index c9b0e103ed514..115e59ca0697e 100644 --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -28,6 +28,7 @@ #include "llvm/ADT/iterator.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/MachO.h" +#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" @@ -276,11 +277,10 @@ class BinaryContext { void deregisterSectionName(const BinarySection &Section); public: - static Expected> - createBinaryContext(Triple TheTriple, StringRef InputFileName, - SubtargetFeatures *Features, bool IsPIC, - std::unique_ptr DwCtx, - JournalingStreams Logger); + static Expected> createBinaryContext( + Triple TheTriple, std::shared_ptr SSP, + StringRef InputFileName, SubtargetFeatures *Features, bool IsPIC, + std::unique_ptr DwCtx, JournalingStreams Logger); /// Superset of compiler units that will contain overwritten code that needs /// new debug info. In a few cases, functions may end up not being @@ -372,6 +372,7 @@ class BinaryContext { bool hasSymbolsWithFileName() const { return HasSymbolsWithFileName; } void setHasSymbolsWithFileName(bool Value) { HasSymbolsWithFileName = Value; } + std::shared_ptr getSymbolStringPool() { return SSP; } /// Return true if relocations against symbol with a given name /// must be created. bool forceSymbolRelocations(StringRef SymbolName) const; @@ -631,6 +632,8 @@ class BinaryContext { std::unique_ptr TheTriple; + std::shared_ptr SSP; + const Target *TheTarget; std::string TripleName; @@ -807,8 +810,10 @@ class BinaryContext { BinaryContext(std::unique_ptr Ctx, std::unique_ptr DwCtx, - std::unique_ptr TheTriple, const Target *TheTarget, - std::string TripleName, std::unique_ptr MCE, + std::unique_ptr TheTriple, + std::shared_ptr SSP, + const Target *TheTarget, std::string TripleName, + std::unique_ptr MCE, std::unique_ptr MOFI, std::unique_ptr AsmInfo, std::unique_ptr MII, diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index a808ece12da19..ac96b836ed579 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -123,6 +123,7 @@ void BinaryContext::logBOLTErrorsAndQuitOnFatal(Error E) { BinaryContext::BinaryContext(std::unique_ptr Ctx, std::unique_ptr DwCtx, std::unique_ptr TheTriple, + std::shared_ptr SSP, const Target *TheTarget, std::string TripleName, std::unique_ptr MCE, std::unique_ptr MOFI, @@ -136,12 +137,12 @@ BinaryContext::BinaryContext(std::unique_ptr Ctx, std::unique_ptr DisAsm, JournalingStreams Logger) : Ctx(std::move(Ctx)), DwCtx(std::move(DwCtx)), - TheTriple(std::move(TheTriple)), TheTarget(TheTarget), - TripleName(TripleName), MCE(std::move(MCE)), MOFI(std::move(MOFI)), - AsmInfo(std::move(AsmInfo)), MII(std::move(MII)), STI(std::move(STI)), - InstPrinter(std::move(InstPrinter)), MIA(std::move(MIA)), - MIB(std::move(MIB)), MRI(std::move(MRI)), DisAsm(std::move(DisAsm)), - Logger(Logger), InitialDynoStats(isAArch64()) { + TheTriple(std::move(TheTriple)), SSP(std::move(SSP)), + TheTarget(TheTarget), TripleName(TripleName), MCE(std::move(MCE)), + MOFI(std::move(MOFI)), AsmInfo(std::move(AsmInfo)), MII(std::move(MII)), + STI(std::move(STI)), InstPrinter(std::move(InstPrinter)), + MIA(std::move(MIA)), MIB(std::move(MIB)), MRI(std::move(MRI)), + DisAsm(std::move(DisAsm)), Logger(Logger), InitialDynoStats(isAArch64()) { RegularPageSize = isAArch64() ? RegularPageSizeAArch64 : RegularPageSizeX86; PageAlign = opts::NoHugePages ? RegularPageSize : HugePageSize; } @@ -159,8 +160,9 @@ BinaryContext::~BinaryContext() { /// Create BinaryContext for a given architecture \p ArchName and /// triple \p TripleName. Expected> BinaryContext::createBinaryContext( - Triple TheTriple, StringRef InputFileName, SubtargetFeatures *Features, - bool IsPIC, std::unique_ptr DwCtx, JournalingStreams Logger) { + Triple TheTriple, std::shared_ptr SSP, + StringRef InputFileName, SubtargetFeatures *Features, bool IsPIC, + std::unique_ptr DwCtx, JournalingStreams Logger) { StringRef ArchName = ""; std::string FeaturesStr = ""; switch (TheTriple.getArch()) { @@ -283,8 +285,8 @@ Expected> BinaryContext::createBinaryContext( auto BC = std::make_unique( std::move(Ctx), std::move(DwCtx), std::make_unique(TheTriple), - TheTarget, std::string(TripleName), std::move(MCE), std::move(MOFI), - std::move(AsmInfo), std::move(MII), std::move(STI), + std::move(SSP), TheTarget, std::string(TripleName), std::move(MCE), + std::move(MOFI), std::move(AsmInfo), std::move(MII), std::move(STI), std::move(InstructionPrinter), std::move(MIA), nullptr, std::move(MRI), std::move(DisAsm), Logger); diff --git a/bolt/lib/Core/DebugNames.cpp b/bolt/lib/Core/DebugNames.cpp index 640b29ec36d5c..280c7c505eeda 100644 --- a/bolt/lib/Core/DebugNames.cpp +++ b/bolt/lib/Core/DebugNames.cpp @@ -161,6 +161,7 @@ bool static canProcess(const DWARFUnit &Unit, const DIE &Die, case dwarf::DW_TAG_structure_type: case dwarf::DW_TAG_typedef: case dwarf::DW_TAG_unspecified_type: + case dwarf::DW_TAG_union_type: if (TagsOnly || Die.findAttribute(dwarf::Attribute::DW_AT_name)) return true; return false; diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp index 1b5ba8b49d363..308881081321a 100644 --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -1691,7 +1691,8 @@ namespace { std::unique_ptr createDwarfOnlyBC(const object::ObjectFile &File) { return cantFail(BinaryContext::createBinaryContext( - File.makeTriple(), File.getFileName(), nullptr, false, + File.makeTriple(), std::make_shared(), + File.getFileName(), nullptr, false, DWARFContext::create(File, DWARFContext::ProcessDebugRelocations::Ignore, nullptr, "", WithColor::defaultErrorHandler, WithColor::defaultWarningHandler), diff --git a/bolt/lib/Rewrite/JITLinkLinker.cpp b/bolt/lib/Rewrite/JITLinkLinker.cpp index be8f9dd03467e..ba483ae4711df 100644 --- a/bolt/lib/Rewrite/JITLinkLinker.cpp +++ b/bolt/lib/Rewrite/JITLinkLinker.cpp @@ -122,7 +122,7 @@ struct JITLinkLinker::Context : jitlink::JITLinkContext { jitlink::AsyncLookupResult AllResults; for (const auto &Symbol : Symbols) { - std::string SymName = Symbol.first.str(); + std::string SymName = (*Symbol.first).str(); LLVM_DEBUG(dbgs() << "BOLT: looking for " << SymName << "\n"); if (auto Address = Linker.lookupSymbol(SymName)) { @@ -167,7 +167,9 @@ struct JITLinkLinker::Context : jitlink::JITLinkContext { Error notifyResolved(jitlink::LinkGraph &G) override { for (auto *Symbol : G.defined_symbols()) { SymbolInfo Info{Symbol->getAddress().getValue(), Symbol->getSize()}; - Linker.Symtab.insert({Symbol->getName().str(), Info}); + auto Name = + Symbol->hasName() ? (*Symbol->getName()).str() : std::string(); + Linker.Symtab.insert({std::move(Name), Info}); } return Error::success(); @@ -189,7 +191,7 @@ JITLinkLinker::~JITLinkLinker() { cantFail(MM->deallocate(std::move(Allocs))); } void JITLinkLinker::loadObject(MemoryBufferRef Obj, SectionsMapper MapSections) { - auto LG = jitlink::createLinkGraphFromObject(Obj); + auto LG = jitlink::createLinkGraphFromObject(Obj, BC.getSymbolStringPool()); if (auto E = LG.takeError()) { errs() << "BOLT-ERROR: JITLink failed: " << E << '\n'; exit(1); diff --git a/bolt/lib/Rewrite/MachORewriteInstance.cpp b/bolt/lib/Rewrite/MachORewriteInstance.cpp index c328232de61a3..2f05b03290ba3 100644 --- a/bolt/lib/Rewrite/MachORewriteInstance.cpp +++ b/bolt/lib/Rewrite/MachORewriteInstance.cpp @@ -74,7 +74,8 @@ MachORewriteInstance::MachORewriteInstance(object::MachOObjectFile *InputFile, ErrorAsOutParameter EAO(&Err); Relocation::Arch = InputFile->makeTriple().getArch(); auto BCOrErr = BinaryContext::createBinaryContext( - InputFile->makeTriple(), InputFile->getFileName(), nullptr, + InputFile->makeTriple(), std::make_shared(), + InputFile->getFileName(), nullptr, /* IsPIC */ true, DWARFContext::create(*InputFile), {llvm::outs(), llvm::errs()}); if (Error E = BCOrErr.takeError()) { diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 3b8baa3821459..76e1f0156f828 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -356,7 +356,8 @@ RewriteInstance::RewriteInstance(ELFObjectFileBase *File, const int Argc, Relocation::Arch = TheTriple.getArch(); auto BCOrErr = BinaryContext::createBinaryContext( - TheTriple, File->getFileName(), Features.get(), IsPIC, + TheTriple, std::make_shared(), File->getFileName(), + Features.get(), IsPIC, DWARFContext::create(*File, DWARFContext::ProcessDebugRelocations::Ignore, nullptr, opts::DWPPathName, WithColor::defaultErrorHandler, diff --git a/bolt/test/X86/dwarf5-debug-names-union.test b/bolt/test/X86/dwarf5-debug-names-union.test new file mode 100644 index 0000000000000..c6da1db684ddc --- /dev/null +++ b/bolt/test/X86/dwarf5-debug-names-union.test @@ -0,0 +1,496 @@ +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %tmain.o +# RUN: %clang %cflags -gdwarf-5 %tmain.o -o %tmain.exe +# RUN: llvm-bolt %tmain.exe -o %tmain.exe.bolt --update-debug-sections +# RUN: llvm-dwarfdump --debug-names %tmain.exe.bolt > %tlog.txt +# RUN: cat %tlog.txt | FileCheck -check-prefix=BOLT %s + +## This test checks that bolt correctly generates entry for DW_TAG_union_type for .debug_name section. + +# BOLT: Abbreviations [ +# BOLT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] { +# BOLT-NEXT: Tag: DW_TAG_subprogram +# BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present +# BOLT-NEXT: } +# BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { +# BOLT-NEXT: Tag: DW_TAG_base_type +# BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present +# BOLT-NEXT: } +# BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { +# BOLT-NEXT: Tag: DW_TAG_union_type +# BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# BOLT-NEXT: DW_IDX_parent: DW_FORM_ref4 +# BOLT-NEXT: } +# BOLT-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] { +# BOLT-NEXT: Tag: DW_TAG_structure_type +# BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# BOLT-NEXT: DW_IDX_parent: DW_FORM_ref4 +# BOLT-NEXT: } +# BOLT-NEXT: ] +# BOLT-NEXT: Bucket 0 [ +# BOLT-NEXT: EMPTY +# BOLT-NEXT: ] +# BOLT-NEXT: Bucket 1 [ +# BOLT-NEXT: Name 1 { +# BOLT-NEXT: Hash: 0x7C9A7F6A +# BOLT-NEXT: String: {{.+}} "main" +# BOLT-NEXT: Entry @ [[ENTRY:0x[0-9a-f]*]] { +# BOLT-NEXT: Abbrev: [[ABBREV1]] +# BOLT-NEXT: Tag: DW_TAG_subprogram +# BOLT-NEXT: DW_IDX_die_offset: 0x00000024 +# BOLT-NEXT: DW_IDX_parent: +# BOLT-NEXT: } +# BOLT-NEXT: } +# BOLT-NEXT: ] +# BOLT-NEXT: Bucket 2 [ +# BOLT-NEXT: EMPTY +# BOLT-NEXT: ] +# BOLT-NEXT: Bucket 3 [ +# BOLT-NEXT: Name 2 { +# BOLT-NEXT: Hash: 0xB888030 +# BOLT-NEXT: String: {{.+}} "int" +# BOLT-NEXT: Entry @ {{.+}} { +# BOLT-NEXT: Abbrev: [[ABBREV2]] +# BOLT-NEXT: Tag: DW_TAG_base_type +# BOLT-NEXT: DW_IDX_die_offset: 0x00000083 +# BOLT-NEXT: DW_IDX_parent: +# BOLT-NEXT: } +# BOLT-NEXT: } +# BOLT-NEXT: Name 3 { +# BOLT-NEXT: Hash: 0xED0F01B4 +# BOLT-NEXT: String: {{.+}} "MyUnion" +# BOLT-NEXT: Entry @ {{.+}} { +# BOLT-NEXT: Abbrev: [[ABBREV3]] +# BOLT-NEXT: Tag: DW_TAG_union_type +# BOLT-NEXT: DW_IDX_die_offset: 0x00000049 +# BOLT-NEXT: DW_IDX_parent: Entry @ [[ENTRY]] +# BOLT-NEXT: } +# BOLT-NEXT: } +# BOLT-NEXT: ] +# BOLT-NEXT: Bucket 4 [ +# BOLT-NEXT: Name 4 { +# BOLT-NEXT: Hash: 0x8AB681F0 +# BOLT-NEXT: String: {{.+}} "MyStruct" +# BOLT-NEXT: Entry @ [[ENTRY2:0x[0-9a-f]*]] { +# BOLT-NEXT: Abbrev: [[ABBREV4]] +# BOLT-NEXT: Tag: DW_TAG_structure_type +# BOLT-NEXT: DW_IDX_die_offset: 0x00000062 +# BOLT-NEXT: DW_IDX_parent: Entry @ [[ENTRY]] +# BOLT-NEXT: } +# BOLT-NEXT: } +# BOLT-NEXT: Name 5 { +# BOLT-NEXT: Hash: 0x8EEF3866 +# BOLT-NEXT: String: {{.+}} "MyUnion2" +# BOLT-NEXT: Entry @ {{.+}} { +# BOLT-NEXT: Abbrev: [[ABBREV3]] +# BOLT-NEXT: Tag: DW_TAG_union_type +# BOLT-NEXT: DW_IDX_die_offset: 0x00000071 +# BOLT-NEXT: DW_IDX_parent: Entry @ [[ENTRY2]] + + +## int main() { +## union MyUnion { +## int a; +## int b; +## }; +## struct MyStruct { +## union MyUnion2 { +## int a; +## }; +## MyUnion2 myUnion2; +## }; +## MyUnion myEnum; +## myEnum.a = 5; +## MyStruct myStruct; +## return myEnum.a + myStruct.myUnion2.a; +## } + + .text + .file "main.cpp" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 0 "union" "main.cpp" md5 0xb75b2512f2daa57bbcfe0c29f56d95f4 + .loc 0 1 0 # main.cpp:1:0 + retq +.Lfunc_end0: + .size main, .-main + # -- 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 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 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 23 # DW_TAG_union_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # 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 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:0x7b 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:0x5f 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 3 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 130 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x32:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .byte 5 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 12 # DW_AT_decl_line + .long 72 # DW_AT_type + .byte 3 # Abbrev [3] 0x3d:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 116 + .byte 9 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 14 # DW_AT_decl_line + .long 97 # DW_AT_type + .byte 4 # Abbrev [4] 0x48:0x19 DW_TAG_union_type + .byte 5 # DW_AT_calling_convention + .byte 8 # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 5 # Abbrev [5] 0x4e:0x9 DW_TAG_member + .byte 6 # DW_AT_name + .long 130 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 5 # Abbrev [5] 0x57:0x9 DW_TAG_member + .byte 7 # DW_AT_name + .long 130 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 6 # Abbrev [6] 0x61:0x20 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 12 # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .byte 5 # Abbrev [5] 0x67:0x9 DW_TAG_member + .byte 10 # DW_AT_name + .long 112 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 4 # Abbrev [4] 0x70:0x10 DW_TAG_union_type + .byte 5 # DW_AT_calling_convention + .byte 11 # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 5 # Abbrev [5] 0x76:0x9 DW_TAG_member + .byte 6 # DW_AT_name + .long 130 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark + .byte 7 # Abbrev [7] 0x82:0x4 DW_TAG_base_type + .byte 4 # 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_offsets,"",@progbits + .long 56 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 20.0.0git" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=24 +.Linfo_string2: + .asciz "union" # string offset=33 +.Linfo_string3: + .asciz "main" # string offset=77 +.Linfo_string4: + .asciz "int" # string offset=82 +.Linfo_string5: + .asciz "myEnum" # string offset=86 +.Linfo_string6: + .asciz "MyUnion" # string offset=93 +.Linfo_string7: + .asciz "a" # string offset=101 +.Linfo_string8: + .asciz "b" # string offset=103 +.Linfo_string9: + .asciz "myStruct" # string offset=105 +.Linfo_string10: + .asciz "MyStruct" # string offset=114 +.Linfo_string11: + .asciz "myUnion2" # string offset=123 +.Linfo_string12: + .asciz "MyUnion2" # string offset=132 + .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_string7 + .long .Linfo_string8 + .long .Linfo_string6 + .long .Linfo_string9 + .long .Linfo_string11 + .long .Linfo_string12 + .long .Linfo_string10 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 +.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 1 # 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 0 # Bucket 0 + .long 1 # Bucket 1 + .long 0 # Bucket 2 + .long 2 # Bucket 3 + .long 4 # Bucket 4 + .long 2090499946 # Hash in Bucket 1 + .long 193495088 # Hash in Bucket 3 + .long -317783628 # Hash in Bucket 3 + .long -1967750672 # Hash in Bucket 4 + .long -1896925082 # Hash in Bucket 4 + .long .Linfo_string3 # String in Bucket 1: main + .long .Linfo_string4 # String in Bucket 3: int + .long .Linfo_string6 # String in Bucket 3: MyUnion + .long .Linfo_string10 # String in Bucket 4: MyStruct + .long .Linfo_string12 # String in Bucket 4: MyUnion2 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1 + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 3 + .long .Lnames2-.Lnames_entries0 # Offset in Bucket 3 + .long .Lnames3-.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 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 36 # DW_TAG_base_type + .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 3 # Abbrev code + .byte 23 # DW_TAG_union_type + .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 4 # Abbrev code + .byte 19 # DW_TAG_structure_type + .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 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames0: +.L3: + .byte 1 # Abbreviation code + .long 35 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: main +.Lnames1: +.L1: + .byte 2 # Abbreviation code + .long 130 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: int +.Lnames2: +.L4: + .byte 3 # Abbreviation code + .long 72 # DW_IDX_die_offset + .long .L3-.Lnames_entries0 # DW_IDX_parent + .byte 0 # End of list: MyUnion +.Lnames3: +.L2: + .byte 4 # Abbreviation code + .long 97 # DW_IDX_die_offset + .long .L3-.Lnames_entries0 # DW_IDX_parent + .byte 0 # End of list: MyStruct +.Lnames4: +.L0: + .byte 3 # Abbreviation code + .long 112 # DW_IDX_die_offset + .long .L2-.Lnames_entries0 # DW_IDX_parent + .byte 0 # End of list: MyUnion2 + .p2align 2, 0x0 +.Lnames_end0: + .ident "clang version 20.0.0git" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/unittests/Core/BinaryContext.cpp b/bolt/unittests/Core/BinaryContext.cpp index 05b898d34af56..9819a8c2b777b 100644 --- a/bolt/unittests/Core/BinaryContext.cpp +++ b/bolt/unittests/Core/BinaryContext.cpp @@ -48,7 +48,8 @@ struct BinaryContextTester : public testing::TestWithParam { void initializeBOLT() { Relocation::Arch = ObjFile->makeTriple().getArch(); BC = cantFail(BinaryContext::createBinaryContext( - ObjFile->makeTriple(), ObjFile->getFileName(), nullptr, true, + ObjFile->makeTriple(), std::make_shared(), + ObjFile->getFileName(), nullptr, true, DWARFContext::create(*ObjFile.get()), {llvm::outs(), llvm::errs()})); ASSERT_FALSE(!BC); } @@ -216,4 +217,4 @@ TEST_P(BinaryContextTester, BaseAddressSegmentsSmallerThanAlignment) { BC->getBaseAddressForMapping(0xaaaaaaab1000, 0x1000); ASSERT_TRUE(BaseAddress.has_value()); ASSERT_EQ(*BaseAddress, 0xaaaaaaaa0000ULL); -} \ No newline at end of file +} diff --git a/bolt/unittests/Core/MCPlusBuilder.cpp b/bolt/unittests/Core/MCPlusBuilder.cpp index cd6f24c4570a7..5488cae366284 100644 --- a/bolt/unittests/Core/MCPlusBuilder.cpp +++ b/bolt/unittests/Core/MCPlusBuilder.cpp @@ -58,7 +58,8 @@ struct MCPlusBuilderTester : public testing::TestWithParam { void initializeBolt() { Relocation::Arch = ObjFile->makeTriple().getArch(); BC = cantFail(BinaryContext::createBinaryContext( - ObjFile->makeTriple(), ObjFile->getFileName(), nullptr, true, + ObjFile->makeTriple(), std::make_shared(), + ObjFile->getFileName(), nullptr, true, DWARFContext::create(*ObjFile.get()), {llvm::outs(), llvm::errs()})); ASSERT_FALSE(!BC); BC->initializeTarget(std::unique_ptr( diff --git a/bolt/unittests/Core/MemoryMaps.cpp b/bolt/unittests/Core/MemoryMaps.cpp index 230fd314142e8..06073d0a82e14 100644 --- a/bolt/unittests/Core/MemoryMaps.cpp +++ b/bolt/unittests/Core/MemoryMaps.cpp @@ -59,7 +59,8 @@ struct MemoryMapsTester : public testing::TestWithParam { void initializeBOLT() { Relocation::Arch = ObjFile->makeTriple().getArch(); BC = cantFail(BinaryContext::createBinaryContext( - ObjFile->makeTriple(), ObjFile->getFileName(), nullptr, true, + ObjFile->makeTriple(), std::make_shared(), + ObjFile->getFileName(), nullptr, true, DWARFContext::create(*ObjFile.get()), {llvm::outs(), llvm::errs()})); ASSERT_FALSE(!BC); } diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h index 97e16a12febd0..ff42f96a0477b 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h @@ -81,6 +81,9 @@ class ClangTidyContext { ~ClangTidyContext(); + ClangTidyContext(const ClangTidyContext &) = delete; + ClangTidyContext &operator=(const ClangTidyContext &) = delete; + /// Report any errors detected using this method. /// /// This is still under heavy development and will likely change towards using diff --git a/clang-tools-extra/clang-tidy/NoLintDirectiveHandler.h b/clang-tools-extra/clang-tidy/NoLintDirectiveHandler.h index e862195abaabb..f66285672d04a 100644 --- a/clang-tools-extra/clang-tidy/NoLintDirectiveHandler.h +++ b/clang-tools-extra/clang-tidy/NoLintDirectiveHandler.h @@ -31,6 +31,8 @@ class NoLintDirectiveHandler { public: NoLintDirectiveHandler(); ~NoLintDirectiveHandler(); + NoLintDirectiveHandler(const NoLintDirectiveHandler &) = delete; + NoLintDirectiveHandler &operator=(const NoLintDirectiveHandler &) = delete; bool shouldSuppress(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Diag, llvm::StringRef DiagName, diff --git a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp index 2b2d80ea9346b..b7f0c08b2a7d4 100644 --- a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp @@ -13,13 +13,15 @@ #include "clang/Analysis/Analyses/ExprMutationAnalyzer.h" #include "clang/Analysis/CallGraph.h" #include "llvm/ADT/SCCIterator.h" -#include "llvm/ADT/SmallVector.h" using namespace clang::ast_matchers; +using clang::ast_matchers::internal::Matcher; using clang::tidy::utils::hasPtrOrReferenceInFunc; namespace clang { -namespace ast_matchers { +namespace tidy::bugprone { + +namespace { /// matches a Decl if it has a "no return" attribute of any kind AST_MATCHER(Decl, declHasNoReturnAttr) { return Node.hasAttr() || Node.hasAttr() || @@ -30,23 +32,21 @@ AST_MATCHER(Decl, declHasNoReturnAttr) { AST_MATCHER(FunctionType, typeHasNoReturnAttr) { return Node.getNoReturnAttr(); } -} // namespace ast_matchers -namespace tidy::bugprone { +} // namespace -static internal::Matcher -loopEndingStmt(internal::Matcher Internal) { - internal::Matcher isNoReturnFunType = +static Matcher loopEndingStmt(Matcher Internal) { + Matcher IsNoReturnFunType = ignoringParens(functionType(typeHasNoReturnAttr())); - internal::Matcher isNoReturnDecl = - anyOf(declHasNoReturnAttr(), functionDecl(hasType(isNoReturnFunType)), - varDecl(hasType(blockPointerType(pointee(isNoReturnFunType))))); + Matcher IsNoReturnDecl = + anyOf(declHasNoReturnAttr(), functionDecl(hasType(IsNoReturnFunType)), + varDecl(hasType(blockPointerType(pointee(IsNoReturnFunType))))); return stmt(anyOf( mapAnyOf(breakStmt, returnStmt, gotoStmt, cxxThrowExpr).with(Internal), callExpr(Internal, callee(mapAnyOf(functionDecl, /* block callee */ varDecl) - .with(isNoReturnDecl))), - objcMessageExpr(Internal, callee(isNoReturnDecl)))); + .with(IsNoReturnDecl))), + objcMessageExpr(Internal, callee(IsNoReturnDecl)))); } /// Return whether `Var` was changed in `LoopStmt`. diff --git a/clang-tools-extra/clang-tidy/bugprone/ReturnConstRefFromParameterCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ReturnConstRefFromParameterCheck.cpp index 1bd7abbad66d2..295955a971d7e 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ReturnConstRefFromParameterCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ReturnConstRefFromParameterCheck.cpp @@ -31,21 +31,20 @@ void ReturnConstRefFromParameterCheck::registerMatchers(MatchFinder *Finder) { qualType(lValueReferenceType(pointee( qualType(isConstQualified())))) .bind("type"))), - hasDeclContext(functionDecl().bind("owner")), + hasDeclContext(functionDecl( + equalsBoundNode("func"), + hasReturnTypeLoc(loc(qualType( + hasCanonicalType(equalsBoundNode("type"))))))), unless(hasLifetimeBoundAttr())) .bind("param"))) .bind("dref")); - const auto Func = - functionDecl(equalsBoundNode("owner"), - hasReturnTypeLoc(loc( - qualType(hasCanonicalType(equalsBoundNode("type")))))) - .bind("func"); - Finder->addMatcher(returnStmt(hasReturnValue(DRef), hasAncestor(Func)), this); Finder->addMatcher( - returnStmt(hasReturnValue(ignoringParens(conditionalOperator( - eachOf(hasTrueExpression(DRef), hasFalseExpression(DRef)), - hasAncestor(Func))))), + returnStmt( + hasAncestor(functionDecl().bind("func")), + hasReturnValue(anyOf( + DRef, ignoringParens(conditionalOperator(eachOf( + hasTrueExpression(DRef), hasFalseExpression(DRef))))))), this); } diff --git a/clang-tools-extra/clangd/ClangdLSPServer.h b/clang-tools-extra/clangd/ClangdLSPServer.h index 597fd9de7ff68..f43734ec1ede3 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.h +++ b/clang-tools-extra/clangd/ClangdLSPServer.h @@ -73,6 +73,9 @@ class ClangdLSPServer : private ClangdServer::Callbacks, /// The destructor blocks on any outstanding background tasks. ~ClangdLSPServer(); + ClangdLSPServer(const ClangdLSPServer &other) = delete; + ClangdLSPServer &operator=(const ClangdLSPServer &other) = delete; + /// Run LSP server loop, communicating with the Transport provided in the /// constructor. This method must not be executed more than once. /// diff --git a/clang-tools-extra/clangd/HeuristicResolver.cpp b/clang-tools-extra/clangd/HeuristicResolver.cpp index 26d54200eeffd..9eb892e8e4a8e 100644 --- a/clang-tools-extra/clangd/HeuristicResolver.cpp +++ b/clang-tools-extra/clangd/HeuristicResolver.cpp @@ -118,6 +118,16 @@ const Type *resolveDeclsToType(const std::vector &Decls, return nullptr; } +TemplateName getReferencedTemplateName(const Type *T) { + if (const auto *TST = T->getAs()) { + return TST->getTemplateName(); + } + if (const auto *DTST = T->getAs()) { + return DTST->getTemplateName(); + } + return TemplateName(); +} + // Helper function for HeuristicResolver::resolveDependentMember() // which takes a possibly-dependent type `T` and heuristically // resolves it to a CXXRecordDecl in which we can try name lookup. @@ -142,12 +152,12 @@ CXXRecordDecl *HeuristicResolverImpl::resolveTypeToRecordDecl(const Type *T) { if (!T) return nullptr; - const auto *TST = T->getAs(); - if (!TST) + TemplateName TN = getReferencedTemplateName(T); + if (TN.isNull()) return nullptr; - const ClassTemplateDecl *TD = dyn_cast_or_null( - TST->getTemplateName().getAsTemplateDecl()); + const ClassTemplateDecl *TD = + dyn_cast_or_null(TN.getAsTemplateDecl()); if (!TD) return nullptr; diff --git a/clang-tools-extra/clangd/ModulesBuilder.cpp b/clang-tools-extra/clangd/ModulesBuilder.cpp index 29508901f85bb..bee31fe51555e 100644 --- a/clang-tools-extra/clangd/ModulesBuilder.cpp +++ b/clang-tools-extra/clangd/ModulesBuilder.cpp @@ -199,7 +199,7 @@ bool IsModuleFileUpToDate(PathRef ModuleFilePath, SourceManager SourceMgr(*Diags, FileMgr); - HeaderSearch HeaderInfo(HSOpts, SourceMgr, *Diags, LangOpts, + HeaderSearch HeaderInfo(std::move(HSOpts), SourceMgr, *Diags, LangOpts, /*Target=*/nullptr); TrivialModuleLoader ModuleLoader; diff --git a/clang-tools-extra/clangd/ParsedAST.h b/clang-tools-extra/clangd/ParsedAST.h index 63e564bd68a78..8d9d1e6456926 100644 --- a/clang-tools-extra/clangd/ParsedAST.h +++ b/clang-tools-extra/clangd/ParsedAST.h @@ -59,6 +59,9 @@ class ParsedAST { ~ParsedAST(); + ParsedAST(const ParsedAST &Other) = delete; + ParsedAST &operator=(const ParsedAST &Other) = delete; + /// Note that the returned ast will not contain decls from the preamble that /// were not deserialized during parsing. Clients should expect only decls /// from the main file to be in the AST. diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp index 71548b59cc308..035e5e63d8fbb 100644 --- a/clang-tools-extra/clangd/TUScheduler.cpp +++ b/clang-tools-extra/clangd/TUScheduler.cpp @@ -411,6 +411,9 @@ class PreambleThrottlerRequest { if (Throttler) Throttler->release(ID); } + PreambleThrottlerRequest(const PreambleThrottlerRequest &) = delete; + PreambleThrottlerRequest & + operator=(const PreambleThrottlerRequest &) = delete; private: PreambleThrottler::RequestID ID; @@ -621,7 +624,8 @@ class ASTWorker { AsyncTaskRunner *Tasks, Semaphore &Barrier, const TUScheduler::Options &Opts, ParsingCallbacks &Callbacks); ~ASTWorker(); - + ASTWorker(const ASTWorker &other) = delete; + ASTWorker &operator=(const ASTWorker &other) = delete; void update(ParseInputs Inputs, WantDiagnostics, bool ContentChanged); void runWithAST(llvm::StringRef Name, diff --git a/clang-tools-extra/clangd/TUScheduler.h b/clang-tools-extra/clangd/TUScheduler.h index fb936d46bbcf7..d0da20310a8b2 100644 --- a/clang-tools-extra/clangd/TUScheduler.h +++ b/clang-tools-extra/clangd/TUScheduler.h @@ -242,6 +242,9 @@ class TUScheduler { std::unique_ptr ASTCallbacks = nullptr); ~TUScheduler(); + TUScheduler(const TUScheduler &other) = delete; + TUScheduler &operator=(const TUScheduler &other) = delete; + struct FileStats { std::size_t UsedBytesAST = 0; std::size_t UsedBytesPreamble = 0; diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index 8295b9d541f7e..8d5ab2e491a40 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -121,31 +121,17 @@ void logIfOverflow(const SymbolLocation &Loc) { // Convert a SymbolLocation to LSP's Location. // TUPath is used to resolve the path of URI. -// FIXME: figure out a good home for it, and share the implementation with -// FindSymbols. std::optional toLSPLocation(const SymbolLocation &Loc, llvm::StringRef TUPath) { if (!Loc) return std::nullopt; - auto Uri = URI::parse(Loc.FileURI); - if (!Uri) { - elog("Could not parse URI {0}: {1}", Loc.FileURI, Uri.takeError()); + auto LSPLoc = indexToLSPLocation(Loc, TUPath); + if (!LSPLoc) { + elog("{0}", LSPLoc.takeError()); return std::nullopt; } - auto U = URIForFile::fromURI(*Uri, TUPath); - if (!U) { - elog("Could not resolve URI {0}: {1}", Loc.FileURI, U.takeError()); - return std::nullopt; - } - - Location LSPLoc; - LSPLoc.uri = std::move(*U); - LSPLoc.range.start.line = Loc.Start.line(); - LSPLoc.range.start.character = Loc.Start.column(); - LSPLoc.range.end.line = Loc.End.line(); - LSPLoc.range.end.character = Loc.End.column(); logIfOverflow(Loc); - return LSPLoc; + return *LSPLoc; } SymbolLocation toIndexLocation(const Location &Loc, std::string &URIStorage) { diff --git a/clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp b/clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp index bd32041bbe1fc..354e75d6e1559 100644 --- a/clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp +++ b/clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp @@ -24,12 +24,12 @@ namespace { std::unique_ptr buildMem() { return loadIndex(IndexFilename, clang::clangd::SymbolOrigin::Static, - /*UseDex=*/false); + /*UseDex=*/false, /*SupportContainedRefs=*/true); } std::unique_ptr buildDex() { return loadIndex(IndexFilename, clang::clangd::SymbolOrigin::Static, - /*UseDex=*/true); + /*UseDex=*/true, /*SupportContainedRefs=*/true); } // Reads JSON array of serialized FuzzyFindRequest's from user-provided file. diff --git a/clang-tools-extra/clangd/index/MemIndex.h b/clang-tools-extra/clangd/index/MemIndex.h index 8f390c5028dc4..fb1052b0c7ca8 100644 --- a/clang-tools-extra/clangd/index/MemIndex.h +++ b/clang-tools-extra/clangd/index/MemIndex.h @@ -97,7 +97,7 @@ class MemIndex : public SymbolIndex { // Set of files which were used during this index build. llvm::StringSet<> Files; // Contents of the index (symbols, references, etc.) - IndexContents IdxContents; + IndexContents IdxContents = IndexContents::None; std::shared_ptr KeepAlive; // poor man's move-only std::any // Size of memory retained by KeepAlive. size_t BackingDataSize = 0; diff --git a/clang-tools-extra/clangd/index/dex/Dex.h b/clang-tools-extra/clangd/index/dex/Dex.h index 20c0503d19b97..502f597d81ef0 100644 --- a/clang-tools-extra/clangd/index/dex/Dex.h +++ b/clang-tools-extra/clangd/index/dex/Dex.h @@ -146,7 +146,9 @@ class Dex : public SymbolIndex { // Set of files which were used during this index build. llvm::StringSet<> Files; // Contents of the index (symbols, references, etc.) - IndexContents IdxContents; + // This is only populated if `Files` is, which applies to some but not all + // consumers of this class. + IndexContents IdxContents = IndexContents::None; // Size of memory retained by KeepAlive. size_t BackingDataSize = 0; }; diff --git a/clang-tools-extra/clangd/index/remote/Index.proto b/clang-tools-extra/clangd/index/remote/Index.proto index 689ef9d44ee40..3e39724e32086 100644 --- a/clang-tools-extra/clangd/index/remote/Index.proto +++ b/clang-tools-extra/clangd/index/remote/Index.proto @@ -133,7 +133,7 @@ message Relation { } message ContainedRefsRequest { - required string id = 1; + optional string id = 1; optional uint32 limit = 2; } @@ -145,7 +145,7 @@ message ContainedRefsReply { } message ContainedRef { - required SymbolLocation location = 1; - required uint32 kind = 2; - required string symbol = 3; + optional SymbolLocation location = 1; + optional uint32 kind = 2; + optional string symbol = 3; } diff --git a/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp b/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp index a80d12347d48d..d8d3b64a5ac18 100644 --- a/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp +++ b/clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp @@ -129,6 +129,8 @@ Marshaller::fromProtobuf(const RefsRequest *Message) { llvm::Expected Marshaller::fromProtobuf(const ContainedRefsRequest *Message) { clangd::ContainedRefsRequest Req; + if (!Message->has_id()) + return error("ContainedRefsRequest requires an id."); auto ID = SymbolID::fromStr(Message->id()); if (!ID) return ID.takeError(); @@ -207,6 +209,12 @@ llvm::Expected Marshaller::fromProtobuf(const Ref &Message) { llvm::Expected Marshaller::fromProtobuf(const ContainedRef &Message) { clangd::ContainedRefsResult Result; + if (!Message.has_location()) + return error("ContainedRef must have a location."); + if (!Message.has_kind()) + return error("ContainedRef must have a kind."); + if (!Message.has_symbol()) + return error("ContainedRef must have a symbol."); auto Location = fromProtobuf(Message.location()); if (!Location) return Location.takeError(); diff --git a/clang-tools-extra/clangd/support/DirectiveTree.cpp b/clang-tools-extra/clangd/support/DirectiveTree.cpp index d25da111681af..7ea08add7a107 100644 --- a/clang-tools-extra/clangd/support/DirectiveTree.cpp +++ b/clang-tools-extra/clangd/support/DirectiveTree.cpp @@ -328,6 +328,9 @@ class Preprocessor { Preprocessor(const TokenStream &In, TokenStream &Out) : In(In), Out(Out) {} ~Preprocessor() { Out.finalize(); } + Preprocessor(const Preprocessor &other) = delete; + Preprocessor &operator=(const Preprocessor &other) = delete; + void walk(const DirectiveTree &T) { for (const auto &C : T.Chunks) std::visit(*this, C); diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp index 3220a5a6a9825..fc54f89f4941e 100644 --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -842,6 +842,8 @@ TEST_F(TargetDeclTest, OverloadExpr) { } TEST_F(TargetDeclTest, DependentExprs) { + Flags.push_back("--std=c++20"); + // Heuristic resolution of method of dependent field Code = R"cpp( struct A { void foo() {} }; @@ -962,6 +964,21 @@ TEST_F(TargetDeclTest, DependentExprs) { }; )cpp"; EXPECT_DECLS("MemberExpr", "void find()"); + + // Base expression is the type of a non-type template parameter + // which is deduced using CTAD. + Code = R"cpp( + template + struct Waldo { + const int found = N; + }; + + template + int test() { + return W.[[found]]; + } + )cpp"; + EXPECT_DECLS("CXXDependentScopeMemberExpr", "const int found = N"); } TEST_F(TargetDeclTest, DependentTypes) { diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp index 30b9b1902aa9c..1ec51d862d0a6 100644 --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -1092,6 +1092,13 @@ sizeof...($TemplateParameter[[Elements]]); $Field_dependentName[[waldo]]; } }; + )cpp", + // Pointer-to-member with nested-name-specifiers + R"cpp( + struct $Class_def[[Outer]] { + struct $Class_def[[Inner]] {}; + }; + using $Typedef_decl[[Alias]] = void ($Class[[Outer]]::$Class[[Inner]]:: *)(); )cpp"}; for (const auto &TestCase : TestCases) // Mask off scope modifiers to keep the tests manageable. diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp index d393c72974d44..7d824d659ad2c 100644 --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -1019,6 +1019,15 @@ TEST(LocateSymbol, All) { void *Value; void *getPointer() const { return Info::get^Pointer(Value); } }; + )cpp", + R"cpp(// Deducing this + struct S { + int bar(this S&); + }; + void foo() { + S [[waldo]]; + int x = wa^ldo.bar(); + } )cpp"}; for (const char *Test : Tests) { Annotations T(Test); @@ -1035,6 +1044,7 @@ TEST(LocateSymbol, All) { TU.Code = std::string(T.code()); TU.ExtraArgs.push_back("-xobjective-c++"); + TU.ExtraArgs.push_back("-std=c++23"); auto AST = TU.build(); auto Results = locateSymbolAt(AST, T.point()); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index e00f86f7d0144..b2b66dca6ccf8 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -183,8 +183,8 @@ Changes in existing checks - Improved :doc:`bugprone-return-const-ref-from-parameter ` check to diagnose potential dangling references when returning a ``const &`` parameter - by using the conditional operator ``cond ? var1 : var2`` and no longer giving - false positives for functions which contain lambda and ignore parameters + by using the conditional operator ``cond ? var1 : var2`` and fixing false + positives for functions which contain lambda and ignore parameters with ``[[clang::lifetimebound]]`` attribute. - Improved :doc:`bugprone-sizeof-expression diff --git a/clang-tools-extra/modularize/ModuleAssistant.cpp b/clang-tools-extra/modularize/ModuleAssistant.cpp index 5c11ffdb8589d..c7259d70bd58f 100644 --- a/clang-tools-extra/modularize/ModuleAssistant.cpp +++ b/clang-tools-extra/modularize/ModuleAssistant.cpp @@ -46,6 +46,8 @@ class Module { public: Module(llvm::StringRef Name, bool Problem); ~Module(); + Module(const Module &other) = delete; + Module &operator=(const Module &other) = delete; bool output(llvm::raw_fd_ostream &OS, int Indent); Module *findSubModule(llvm::StringRef SubName); diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/return-const-ref-from-parameter.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/return-const-ref-from-parameter.cpp index 46cb9063beda9..a3297ca0f8084 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/return-const-ref-from-parameter.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/return-const-ref-from-parameter.cpp @@ -203,3 +203,26 @@ namespace use_lifetime_bound_attr { int const &f(int const &a [[clang::lifetimebound]]) { return a; } } // namespace use_lifetime_bound_attr } // namespace gh117696 + + +namespace lambda { +using T = const int &; +using K = const float &; +T inner_valid_lambda(T a) { + [&]() -> T { return a; }; + return a; + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: returning a constant reference parameter +} +T inner_invalid_lambda(T a) { + [&](T a) -> T { return a; }; + // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: returning a constant reference parameter + return a; + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: returning a constant reference parameter +} +T inner_invalid_lambda2(T a) { + [&](K a) -> K { return a; }; + // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: returning a constant reference parameter + return a; + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: returning a constant reference parameter +} +} // namespace lambda diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp index 1b271630e0d19..7396d2dce76c4 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -fno-delayed-template-parsing +// RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -fno-delayed-template-parsing -Wno-array-compare-cxx26 typedef __INT64_TYPE__ I64; diff --git a/clang/cmake/caches/CrossWinToARMLinux.cmake b/clang/cmake/caches/CrossWinToARMLinux.cmake index 853217c6db61a..c47c4ac3bb73e 100644 --- a/clang/cmake/caches/CrossWinToARMLinux.cmake +++ b/clang/cmake/caches/CrossWinToARMLinux.cmake @@ -96,7 +96,11 @@ endif() if (NOT DEFINED TOOLCHAIN_SHARED_LIBS) set(TOOLCHAIN_SHARED_LIBS OFF) endif() - +# Enable usage of the static libunwind and libc++abi libraries. +if (NOT DEFINED TOOLCHAIN_USE_STATIC_LIBS) + set(TOOLCHAIN_USE_STATIC_LIBS ON) +endif() + if (NOT DEFINED LLVM_TARGETS_TO_BUILD) if ("${TOOLCHAIN_TARGET_TRIPLE}" MATCHES "^(armv|arm32)+") set(LLVM_TARGETS_TO_BUILD "ARM" CACHE STRING "") @@ -206,7 +210,7 @@ set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBUNWIND_USE_COMPILER_RT set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBUNWIND_ENABLE_SHARED ${TOOLCHAIN_SHARED_LIBS} CACHE BOOL "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") -set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "") +set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_ENABLE_STATIC_UNWINDER ${TOOLCHAIN_USE_STATIC_LIBS} CACHE BOOL "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS OFF CACHE BOOL "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_ENABLE_SHARED ${TOOLCHAIN_SHARED_LIBS} CACHE BOOL "") @@ -217,7 +221,7 @@ set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ABI_VERSION set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_CXX_ABI "libcxxabi" CACHE STRING "") #!!! set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON CACHE BOOL "") # Merge libc++ and libc++abi libraries into the single libc++ library file. -set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "") +set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ${TOOLCHAIN_USE_STATIC_LIBS} CACHE BOOL "") # Forcely disable the libc++ benchmarks on Windows build hosts # (current benchmark test configuration does not support the cross builds there). if (WIN32) diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake b/clang/cmake/caches/Fuchsia-stage2.cmake index 304e7833699a7..784a883a3bf91 100644 --- a/clang/cmake/caches/Fuchsia-stage2.cmake +++ b/clang/cmake/caches/Fuchsia-stage2.cmake @@ -6,7 +6,7 @@ set(LLVM_TARGETS_TO_BUILD X86;ARM;AArch64;RISCV CACHE STRING "") set(PACKAGE_VENDOR Fuchsia CACHE STRING "") -set(_FUCHSIA_ENABLE_PROJECTS "bolt;clang;clang-tools-extra;libc;lld;llvm;polly") +set(_FUCHSIA_ENABLE_PROJECTS "bolt;clang;clang-tools-extra;lld;llvm;polly") set(LLVM_ENABLE_RUNTIMES "compiler-rt;libcxx;libcxxabi;libunwind" CACHE STRING "") set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "") @@ -25,8 +25,6 @@ set(LLVM_ENABLE_ZLIB ON CACHE BOOL "") set(LLVM_FORCE_BUILD_RUNTIME ON CACHE BOOL "") set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "") set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "") -set(LLVM_LIBC_FULL_BUILD ON CACHE BOOL "") -set(LIBC_HDRGEN_ONLY ON CACHE BOOL "") set(LLVM_STATIC_LINK_CXX_STDLIB ON CACHE BOOL "") set(LLVM_USE_RELATIVE_PATHS_IN_FILES ON CACHE BOOL "") set(LLDB_ENABLE_CURSES OFF CACHE BOOL "") diff --git a/clang/cmake/caches/Fuchsia.cmake b/clang/cmake/caches/Fuchsia.cmake index 2d2dcb9ae6798..07637cd0ed08f 100644 --- a/clang/cmake/caches/Fuchsia.cmake +++ b/clang/cmake/caches/Fuchsia.cmake @@ -6,7 +6,7 @@ set(LLVM_TARGETS_TO_BUILD X86;ARM;AArch64;RISCV CACHE STRING "") set(PACKAGE_VENDOR Fuchsia CACHE STRING "") -set(_FUCHSIA_ENABLE_PROJECTS "bolt;clang;clang-tools-extra;libc;lld;llvm;polly") +set(_FUCHSIA_ENABLE_PROJECTS "bolt;clang;clang-tools-extra;lld;llvm;polly") set(LLVM_ENABLE_DIA_SDK OFF CACHE BOOL "") set(LLVM_ENABLE_LIBEDIT OFF CACHE BOOL "") @@ -17,7 +17,6 @@ set(LLVM_ENABLE_Z3_SOLVER OFF CACHE BOOL "") set(LLVM_ENABLE_ZLIB OFF CACHE BOOL "") set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "") set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "") -set(LIBC_HDRGEN_ONLY ON CACHE BOOL "") set(LLVM_USE_RELATIVE_PATHS_IN_FILES ON CACHE BOOL "") set(LLDB_ENABLE_CURSES OFF CACHE BOOL "") set(LLDB_ENABLE_LIBEDIT OFF CACHE BOOL "") diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 6b950d05fb9bf..6a886a49ea076 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -648,7 +648,8 @@ elementwise to the input. Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±infinity The integer elementwise intrinsics, including ``__builtin_elementwise_popcount``, -``__builtin_elementwise_bitreverse``, can be called in a ``constexpr`` context. +``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``, +``__builtin_elementwise_sub_sat`` can be called in a ``constexpr`` context. ============================================== ====================================================================== ========================================= Name Operation Supported element types diff --git a/clang/docs/RealtimeSanitizer.rst b/clang/docs/RealtimeSanitizer.rst index 233a91f668416..f5d29af2bef3c 100644 --- a/clang/docs/RealtimeSanitizer.rst +++ b/clang/docs/RealtimeSanitizer.rst @@ -187,16 +187,19 @@ A **partial** list of flags RealtimeSanitizer respects: * - ``abort_on_error`` - OS dependent - boolean - - If true, the tool calls abort() instead of _exit() after printing the error report. On some OSes (OSX, for exmple) this is beneficial because a better stack trace is emitted on crash. + - If true, the tool calls ``abort()`` instead of ``_exit()`` after printing the error report. On some OSes (MacOS, for exmple) this is beneficial because a better stack trace is emitted on crash. * - ``symbolize`` - ``true`` - boolean - If set, use the symbolizer to turn virtual addresses to file/line locations. If false, can greatly speed up the error reporting. * - ``suppressions`` - - "" + - ``""`` - path - - If set to a valid suppressions file, will suppress issue reporting. See details in "Disabling", below. - + - If set to a valid suppressions file, will suppress issue reporting. See details in `Disabling and Suppressing`_. + * - ``verify_interceptors`` + - ``true`` + - boolean + - If true, verifies interceptors are working at initialization. The program will abort with error ``==ERROR: Interceptors are not working. This may be because RealtimeSanitizer is loaded too late (e.g. via dlopen)`` if an issue is detected. Some issues with flags can be debugged using the ``verbosity=$NUM`` flag: @@ -244,6 +247,7 @@ To register a callback which will be invoked before a RTSan kills the process: ... } +.. _disabling-and-suppressing: Disabling and suppressing ------------------------- diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 755418e9550cf..c040a0d80d0df 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -52,6 +52,12 @@ code bases. `migrate to Vulkan `_ or other options. +- Clang now emits distinct type-based alias analysis tags for incompatible + pointers by default, enabling more powerful alias analysis when accessing + pointer types. This change may silently change code behavior for code + containing strict-aliasing violations. The new default behavior can be + disabled using ``-fno-pointer-tbaa``. + C/C++ Language Potentially Breaking Changes ------------------------------------------- @@ -381,7 +387,7 @@ Non-comprehensive list of changes in this release - The new builtin ``__builtin_counted_by_ref`` was added. In contexts where the programmer needs access to the ``counted_by`` attribute's field, but it's not - available --- e.g. in macros. For instace, it can be used to automatically + available --- e.g. in macros. For instance, it can be used to automatically set the counter during allocation in the Linux kernel: .. code-block:: c @@ -402,12 +408,11 @@ Non-comprehensive list of changes in this release The flexible array member (FAM) can now be accessed immediately without causing issues with the sanitizer because the counter is automatically set. -- ``__builtin_reduce_add`` function can now be used in constant expressions. -- ``__builtin_reduce_mul`` function can now be used in constant expressions. -- ``__builtin_reduce_and`` function can now be used in constant expressions. -- ``__builtin_reduce_or`` and ``__builtin_reduce_xor`` functions can now be used in constant expressions. -- ``__builtin_elementwise_popcount`` function can now be used in constant expressions. -- ``__builtin_elementwise_bitreverse`` function can now be used in constant expressions. +- The following builtins can now be used in constant expressions: ``__builtin_reduce_add``, + ``__builtin_reduce_mul``, ``__builtin_reduce_and``, ``__builtin_reduce_or``, + ``__builtin_reduce_xor``, ``__builtin_elementwise_popcount``, + ``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``, + ``__builtin_elementwise_sub_sat``. New Compiler Flags ------------------ @@ -419,6 +424,12 @@ New Compiler Flags existing ``-fno-c++-static-destructors`` flag) skips all static destructors registration. +- The ``-Warray-compare`` warning has been added to warn about array comparison + on versions older than C++20. + +- The ``-Warray-compare-cxx26`` warning has been added to warn about array comparison + starting from C++26, this warning is enabled as an error by default. + Deprecated Compiler Flags ------------------------- @@ -443,7 +454,7 @@ Modified Compiler Flags libraries remains unchanged. - The ``-Wnontrivial-memcall`` warning has been added to warn about - passing non-trivially-copyable destrination parameter to ``memcpy``, + passing non-trivially-copyable destination parameter to ``memcpy``, ``memset`` and similar functions for which it is a documented undefined behavior. It is implied by ``-Wnontrivial-memaccess`` @@ -516,6 +527,9 @@ Attribute Changes in Clang - The ``target_version`` attribute is now only supported for AArch64 and RISC-V architectures. +- Clang now permits the usage of the placement new operator in ``[[msvc::constexpr]]`` + context outside of the std namespace. (#GH74924) + Improvements to Clang's diagnostics ----------------------------------- @@ -632,6 +646,20 @@ Improvements to Clang's diagnostics - Clang now diagnoses dangling references for C++20's parenthesized aggregate initialization (#101957). +- Fixed a bug where Clang would not emit ``-Wunused-private-field`` warnings when an unrelated class + defined a defaulted comparison operator (#GH116270). + + .. code-block:: c++ + + class A { + private: + int a; // warning: private field 'a' is not used, no diagnostic previously + }; + + class C { + bool operator==(const C&) = default; + }; + Improvements to Clang's time-trace ---------------------------------- @@ -654,6 +682,9 @@ Bug Fixes in This Version - Fixed a crash when GNU statement expression contains invalid statement (#GH113468). - Fixed a failed assertion when using ``__attribute__((noderef))`` on an ``_Atomic``-qualified type (#GH116124). +- No longer return ``false`` for ``noexcept`` expressions involving a + ``delete`` which resolves to a destroying delete but the type of the object + being deleted has a potentially throwing destructor (#GH118660). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -678,7 +709,7 @@ Bug Fixes to C++ Support - Fixed a failed assertion when checking invalid delete operator declaration. (#GH96191) - Fix a crash when checking destructor reference with an invalid initializer. (#GH97230) - Clang now correctly parses potentially declarative nested-name-specifiers in pointer-to-member declarators. -- Fix a crash when checking the initialzier of an object that was initialized +- Fix a crash when checking the initializer of an object that was initialized with a string literal. (#GH82167) - Fix a crash when matching template template parameters with templates which have parameters of different class type. (#GH101394) @@ -722,7 +753,7 @@ Bug Fixes to C++ Support - Fix a crash when using ``source_location`` in the trailing return type of a lambda expression. (#GH67134) - A follow-up fix was added for (#GH61460), as the previous fix was not entirely correct. (#GH86361), (#GH112352) - Fixed a crash in the typo correction of an invalid CTAD guide. (#GH107887) -- Fixed a crash when clang tries to subtitute parameter pack while retaining the parameter +- Fixed a crash when clang tries to substitute parameter pack while retaining the parameter pack. (#GH63819), (#GH107560) - Fix a crash when a static assert declaration has an invalid close location. (#GH108687) - Avoided a redundant friend declaration instantiation under a certain ``consteval`` context. (#GH107175) @@ -767,9 +798,11 @@ Bug Fixes to C++ Support - Fixed a bug where bounds of partially expanded pack indexing expressions were checked too early. (#GH116105) - Fixed an assertion failure caused by using ``consteval`` in condition in consumed analyses. (#GH117385) - Fix a crash caused by incorrect argument position in merging deduced template arguments. (#GH113659) +- Fixed a parser crash when using pack indexing as a nested name specifier. (#GH119072) - Fixed an assertion failure caused by mangled names with invalid identifiers. (#GH112205) - Fixed an incorrect lambda scope of generic lambdas that caused Clang to crash when computing potential lambda captures at the end of a full expression. (#GH115931) +- Clang no longer rejects deleting a pointer of incomplete enumeration type. (#GH99278) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1042,7 +1075,7 @@ Moved checkers ``bugprone-branch-clone``. - The checker ``alpha.security.MallocOverflow`` was deleted because it was - badly implemented and its agressive logic produced too many false positives. + badly implemented and its aggressive logic produced too many false positives. To detect too large arguments passed to malloc, consider using the checker ``alpha.taint.TaintedAlloc``. diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 43b41a2a82689..8af9f5be644a0 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1059,6 +1059,17 @@ In this way, the user may only need to specify a root configuration file with -L /lib -T /ldscripts/link.ld +Usually, config file options are placed before command-line options, regardless +of the actual operation to be performed. The exception is being made for the +options prefixed with the ``$`` character. These will be used only when linker +is being invoked, and added after all of the command-line specified linker +inputs. Here is some example of ``$``-prefixed options: + +:: + + $-Wl,-Bstatic $-lm + $-Wl,-Bshared + Language and Target-Independent Features ======================================== diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index d99d4035a57ac..29d5e1f92a69c 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -3438,6 +3438,31 @@ alpha.WebKit .. _alpha-webkit-NoUncheckedPtrMemberChecker: +alpha.webkit.MemoryUnsafeCastChecker +"""""""""""""""""""""""""""""""""""""" +Check for all casts from a base type to its derived type as these might be memory-unsafe. + +Example: + +.. code-block:: cpp + + class Base { }; + class Derived : public Base { }; + + void f(Base* base) { + Derived* derived = static_cast(base); // ERROR + } + +For all cast operations (C-style casts, static_cast, reinterpret_cast, dynamic_cast), if the source type a `Base*` and the destination type is `Derived*`, where `Derived` inherits from `Base`, the static analyzer should signal an error. + +This applies to: + +- C structs, C++ structs and classes, and Objective-C classes and protocols. +- Pointers and references. +- Inside template instantiations and macro expansions that are visible to the compiler. + +For types like this, instead of using built in casts, the programmer will use helper functions that internally perform the appropriate type check and disable static analysis. + alpha.webkit.NoUncheckedPtrMemberChecker """""""""""""""""""""""""""""""""""""""" Raw pointers and references to an object which supports CheckedPtr or CheckedRef can't be used as class members. Only CheckedPtr, CheckedRef, RefPtr, or Ref are allowed. diff --git a/clang/docs/tools/dump_format_help.py b/clang/docs/tools/dump_format_help.py index 1a9afde1b9db9..baf90048ee135 100755 --- a/clang/docs/tools/dump_format_help.py +++ b/clang/docs/tools/dump_format_help.py @@ -2,6 +2,7 @@ # A tool to parse the output of `clang-format --help` and update the # documentation in ../ClangFormat.rst automatically. +import argparse import os import re import subprocess @@ -26,7 +27,7 @@ def indent(text, columns, indent_first_line=True): def get_help_output(): - args = ["clang-format", "--help"] + args = [binary, "--help"] cmd = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) out, _ = cmd.communicate() out = out.decode(sys.stdout.encoding) @@ -54,13 +55,22 @@ def validate(text, columns): print("warning: line too long:\n", line, file=sys.stderr) +p = argparse.ArgumentParser() +p.add_argument("-d", "--directory", help="directory of clang-format") +p.add_argument("-o", "--output", help="path of output file") +opts = p.parse_args() + +binary = "clang-format" +if opts.directory: + binary = opts.directory + "/" + binary + help_text = get_help_text() validate(help_text, 100) -with open(DOC_FILE) as f: +with open(DOC_FILE, encoding="utf-8") as f: contents = f.read() contents = substitute(contents, "FORMAT_HELP", help_text) -with open(DOC_FILE, "wb") as output: +with open(opts.output if opts.output else DOC_FILE, "wb") as output: output.write(contents.encode()) diff --git a/clang/docs/tools/dump_format_style.py b/clang/docs/tools/dump_format_style.py index af0e658fcdc55..f00f3ee8b20e8 100755 --- a/clang/docs/tools/dump_format_style.py +++ b/clang/docs/tools/dump_format_style.py @@ -3,6 +3,7 @@ # documentation in ../ClangFormatStyleOptions.rst automatically. # Run from the directory in which this file is located to update the docs. +import argparse import inspect import os import re @@ -20,7 +21,7 @@ PLURALS_FILE = os.path.join(os.path.dirname(__file__), "plurals.txt") plurals: Set[str] = set() -with open(PLURALS_FILE, "a+") as f: +with open(PLURALS_FILE) as f: f.seek(0) plurals = set(f.read().splitlines()) @@ -474,6 +475,10 @@ class State: return options +p = argparse.ArgumentParser() +p.add_argument("-o", "--output", help="path of output file") +args = p.parse_args() + with open(FORMAT_STYLE_FILE) as f: opts = OptionsReader(f).read_options() with open(INCLUDE_STYLE_FILE) as f: @@ -487,5 +492,5 @@ class State: contents = substitute(contents, "FORMAT_STYLE_OPTIONS", options_text) -with open(DOC_FILE, "wb") as output: +with open(args.output if args.output else DOC_FILE, "wb") as output: output.write(contents.encode()) diff --git a/clang/include/clang/AST/AttrIterator.h b/clang/include/clang/AST/AttrIterator.h index 66571e1cf0b8e..7e2bb0381d4c8 100644 --- a/clang/include/clang/AST/AttrIterator.h +++ b/clang/include/clang/AST/AttrIterator.h @@ -14,11 +14,13 @@ #define LLVM_CLANG_AST_ATTRITERATOR_H #include "clang/Basic/LLVM.h" +#include "llvm/ADT/ADL.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" #include #include #include +#include namespace clang { @@ -113,13 +115,13 @@ inline bool hasSpecificAttr(const Container& container) { specific_attr_end(container); } template -inline SpecificAttr *getSpecificAttr(const Container& container) { - specific_attr_iterator i = - specific_attr_begin(container); - if (i != specific_attr_end(container)) - return *i; - else - return nullptr; +inline auto *getSpecificAttr(const Container &container) { + using ValueTy = llvm::detail::ValueOfRange; + using ValuePointeeTy = std::remove_pointer_t; + using IterTy = std::conditional_t, + const SpecificAttr, SpecificAttr>; + auto It = specific_attr_begin(container); + return It != specific_attr_end(container) ? *It : nullptr; } } // namespace clang diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 5ad4c336b6c53..2588c3f645c02 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -483,6 +483,14 @@ class OpenACCGangClause final return {getGangKind(I), getExprs()[I]}; } + bool hasExprOfKind(OpenACCGangKind GK) const { + for (unsigned I = 0; I < getNumExprs(); ++I) { + if (getGangKind(I) == GK) + return true; + } + return false; + } + static OpenACCGangClause * Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef GangKinds, diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 618252f3e7524..17fc36fbe2ac8 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -55,6 +55,9 @@ class Documentation { // When set, specifies that the attribute is deprecated and can optionally // specify a replacement attribute. DocDeprecated Deprecated; + + // When set, specifies a label that can be used to reference the documentation. + string Label = ""; } // Specifies that the attribute is explicitly omitted from the documentation, diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 5de39be480560..7a82b8fa32059 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3360,9 +3360,8 @@ def NoSanitizeAddressDocs : Documentation { // This function has multiple distinct spellings, and so it requires a custom // heading to be specified. The most common spelling is sufficient. let Heading = "no_sanitize_address, no_address_safety_analysis"; + let Label = "langext-address_sanitizer"; let Content = [{ -.. _langext-address_sanitizer: - Use ``__attribute__((no_sanitize_address))`` on a function or a global variable declaration to specify that address safety instrumentation (e.g. AddressSanitizer) should not be applied. @@ -3372,9 +3371,8 @@ variable declaration to specify that address safety instrumentation def NoSanitizeThreadDocs : Documentation { let Category = DocCatFunction; let Heading = "no_sanitize_thread"; + let Label = "langext-thread_sanitizer"; let Content = [{ -.. _langext-thread_sanitizer: - Use ``__attribute__((no_sanitize_thread))`` on a function declaration to specify that checks for data races on plain (non-atomic) memory accesses should not be inserted by ThreadSanitizer. The function is still instrumented by the @@ -3385,9 +3383,8 @@ tool to avoid false positives and provide meaningful stack traces. def NoSanitizeMemoryDocs : Documentation { let Category = DocCatFunction; let Heading = "no_sanitize_memory"; + let Label = "langext-memory_sanitizer"; let Content = [{ -.. _langext-memory_sanitizer: - Use ``__attribute__((no_sanitize_memory))`` on a function declaration to specify that checks for uninitialized memory should not be inserted (e.g. by MemorySanitizer). The function may still be instrumented by the tool @@ -3398,9 +3395,8 @@ to avoid false positives in other places. def CFICanonicalJumpTableDocs : Documentation { let Category = DocCatFunction; let Heading = "cfi_canonical_jump_table"; + let Label = "langext-cfi_canonical_jump_table"; let Content = [{ -.. _langext-cfi_canonical_jump_table: - Use ``__attribute__((cfi_canonical_jump_table))`` on a function declaration to make the function's CFI jump table canonical. See :ref:`the CFI documentation ` for more details. diff --git a/clang/include/clang/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h index 89f65682ae5b4..a9bb6efe850cc 100644 --- a/clang/include/clang/Basic/Builtins.h +++ b/clang/include/clang/Basic/Builtins.h @@ -55,6 +55,7 @@ struct HeaderDesc { #undef HEADER } ID; + constexpr HeaderDesc() : ID() {} constexpr HeaderDesc(HeaderID ID) : ID(ID) {} const char *getName() const; @@ -68,14 +69,140 @@ enum ID { FirstTSBuiltin }; +// The info used to represent each builtin. struct Info { - llvm::StringLiteral Name; - const char *Type, *Attributes; - const char *Features; + // Rather than store pointers to the string literals describing these four + // aspects of builtins, we store offsets into a common string table. + struct StrOffsets { + int Name; + int Type; + int Attributes; + int Features; + } Offsets; + HeaderDesc Header; LanguageID Langs; }; +// The storage for `N` builtins. This contains a single pointer to the string +// table used for these builtins and an array of metadata for each builtin. +template struct Storage { + const char *StringTable; + + std::array Infos; + + // A constexpr function to construct the storage for a a given string table in + // the first argument and an array in the second argument. This is *only* + // expected to be used at compile time, we should mark it `consteval` when + // available. + // + // The `Infos` array is particularly special. This function expects an array + // of `Info` structs, where the string offsets of each entry refer to the + // *sizes* of those strings rather than their offsets, and for the target + // string to be in the provided string table at an offset the sum of all + // previous string sizes. This function walks the `Infos` array computing the + // running sum and replacing the sizes with the actual offsets in the string + // table that should be used. This arrangement is designed to make it easy to + // expand `.def` and `.inc` files with X-macros to construct both the string + // table and the `Info` structs in the arguments to this function. + static constexpr Storage Make(const char *Strings, + std::array Infos) { + // Translate lengths to offsets. + int Offset = 0; + for (auto &I : Infos) { + Info::StrOffsets NewOffsets = {}; + NewOffsets.Name = Offset; + Offset += I.Offsets.Name; + NewOffsets.Type = Offset; + Offset += I.Offsets.Type; + NewOffsets.Attributes = Offset; + Offset += I.Offsets.Attributes; + NewOffsets.Features = Offset; + Offset += I.Offsets.Features; + I.Offsets = NewOffsets; + } + return {Strings, Infos}; + } +}; + +// A detail macro used below to emit a string literal that, after string literal +// concatenation, ends up triggering the `-Woverlength-strings` warning. While +// the warning is useful in general to catch accidentally excessive strings, +// here we are creating them intentionally. +// +// This relies on a subtle aspect of `_Pragma`: that the *diagnostic* ones don't +// turn into actual tokens that would disrupt string literal concatenation. +#ifdef __clang__ +#define CLANG_BUILTIN_DETAIL_STR_TABLE(S) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Woverlength-strings\"") \ + S _Pragma("clang diagnostic pop") +#else +#define CLANG_BUILTIN_DETAIL_STR_TABLE(S) S +#endif + +// A macro that can be used with `Builtins.def` and similar files as an X-macro +// to add the string arguments to a builtin string table. This is typically the +// target for the `BUILTIN`, `LANGBUILTIN`, or `LIBBUILTIN` macros in those +// files. +#define CLANG_BUILTIN_STR_TABLE(ID, TYPE, ATTRS) \ + CLANG_BUILTIN_DETAIL_STR_TABLE(#ID "\0" TYPE "\0" ATTRS "\0" /*FEATURE*/ "\0") + +// A macro that can be used with target builtin `.def` and `.inc` files as an +// X-macro to add the string arguments to a builtin string table. this is +// typically the target for the `TARGET_BUILTIN` macro. +#define CLANG_TARGET_BUILTIN_STR_TABLE(ID, TYPE, ATTRS, FEATURE) \ + CLANG_BUILTIN_DETAIL_STR_TABLE(#ID "\0" TYPE "\0" ATTRS "\0" FEATURE "\0") + +// A macro that can be used with target builtin `.def` and `.inc` files as an +// X-macro to add the string arguments to a builtin string table. this is +// typically the target for the `TARGET_HEADER_BUILTIN` macro. We can't delegate +// to `TARGET_BUILTIN` because the `FEATURE` string changes position. +#define CLANG_TARGET_HEADER_BUILTIN_STR_TABLE(ID, TYPE, ATTRS, HEADER, LANGS, \ + FEATURE) \ + CLANG_BUILTIN_DETAIL_STR_TABLE(#ID "\0" TYPE "\0" ATTRS "\0" FEATURE "\0") + +// A detail macro used internally to compute the desired string table +// `StrOffsets` struct for arguments to `Storage::Make`. +#define CLANG_BUILTIN_DETAIL_STR_OFFSETS(ID, TYPE, ATTRS) \ + Builtin::Info::StrOffsets { \ + sizeof(#ID), sizeof(TYPE), sizeof(ATTRS), sizeof("") \ + } + +// A detail macro used internally to compute the desired string table +// `StrOffsets` struct for arguments to `Storage::Make`. +#define CLANG_TARGET_BUILTIN_DETAIL_STR_OFFSETS(ID, TYPE, ATTRS, FEATURE) \ + Builtin::Info::StrOffsets { \ + sizeof(#ID), sizeof(TYPE), sizeof(ATTRS), sizeof(FEATURE) \ + } + +// A set of macros that can be used with builtin `.def' files as an X-macro to +// create an `Info` struct for a particular builtin. It both computes the +// `StrOffsets` value for the string table (the lengths here, translated to +// offsets by the Storage::Make function), and the other metadata for each +// builtin. +// +// There is a corresponding macro for each of `BUILTIN`, `LANGBUILTIN`, +// `LIBBUILTIN`, `TARGET_BUILTIN`, and `TARGET_HEADER_BUILTIN`. +#define CLANG_BUILTIN_ENTRY(ID, TYPE, ATTRS) \ + Builtin::Info{CLANG_BUILTIN_DETAIL_STR_OFFSETS(ID, TYPE, ATTRS), \ + HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +#define CLANG_LANGBUILTIN_ENTRY(ID, TYPE, ATTRS, LANG) \ + Builtin::Info{CLANG_BUILTIN_DETAIL_STR_OFFSETS(ID, TYPE, ATTRS), \ + HeaderDesc::NO_HEADER, LANG}, +#define CLANG_LIBBUILTIN_ENTRY(ID, TYPE, ATTRS, HEADER, LANG) \ + Builtin::Info{CLANG_BUILTIN_DETAIL_STR_OFFSETS(ID, TYPE, ATTRS), \ + HeaderDesc::HEADER, LANG}, +#define CLANG_TARGET_BUILTIN_ENTRY(ID, TYPE, ATTRS, FEATURE) \ + Builtin::Info{ \ + CLANG_TARGET_BUILTIN_DETAIL_STR_OFFSETS(ID, TYPE, ATTRS, FEATURE), \ + HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +#define CLANG_TARGET_HEADER_BUILTIN_ENTRY(ID, TYPE, ATTRS, HEADER, LANG, \ + FEATURE) \ + Builtin::Info{ \ + CLANG_TARGET_BUILTIN_DETAIL_STR_OFFSETS(ID, TYPE, ATTRS, FEATURE), \ + HeaderDesc::HEADER, LANG}, + /// Holds information about both target-independent and /// target-specific builtins, allowing easy queries by clients. /// @@ -83,8 +210,11 @@ struct Info { /// AuxTSRecords. Their IDs are shifted up by TSRecords.size() and need to /// be translated back with getAuxBuiltinID() before use. class Context { - llvm::ArrayRef TSRecords; - llvm::ArrayRef AuxTSRecords; + const char *TSStrTable = nullptr; + const char *AuxTSStrTable = nullptr; + + llvm::ArrayRef TSInfos; + llvm::ArrayRef AuxTSInfos; public: Context() = default; @@ -100,12 +230,13 @@ class Context { /// Return the identifier name for the specified builtin, /// e.g. "__builtin_abs". - llvm::StringRef getName(unsigned ID) const { return getRecord(ID).Name; } + llvm::StringRef getName(unsigned ID) const; /// Get the type descriptor string for the specified builtin. - const char *getTypeString(unsigned ID) const { - return getRecord(ID).Type; - } + const char *getTypeString(unsigned ID) const; + + /// Get the attributes descriptor string for the specified builtin. + const char *getAttributesString(unsigned ID) const; /// Return true if this function is a target-specific builtin. bool isTSBuiltin(unsigned ID) const { @@ -114,40 +245,40 @@ class Context { /// Return true if this function has no side effects. bool isPure(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'U') != nullptr; + return strchr(getAttributesString(ID), 'U') != nullptr; } /// Return true if this function has no side effects and doesn't /// read memory. bool isConst(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'c') != nullptr; + return strchr(getAttributesString(ID), 'c') != nullptr; } /// Return true if we know this builtin never throws an exception. bool isNoThrow(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'n') != nullptr; + return strchr(getAttributesString(ID), 'n') != nullptr; } /// Return true if we know this builtin never returns. bool isNoReturn(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'r') != nullptr; + return strchr(getAttributesString(ID), 'r') != nullptr; } /// Return true if we know this builtin can return twice. bool isReturnsTwice(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'j') != nullptr; + return strchr(getAttributesString(ID), 'j') != nullptr; } /// Returns true if this builtin does not perform the side-effects /// of its arguments. bool isUnevaluated(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'u') != nullptr; + return strchr(getAttributesString(ID), 'u') != nullptr; } /// Return true if this is a builtin for a libc/libm function, /// with a "__builtin_" prefix (e.g. __builtin_abs). bool isLibFunction(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'F') != nullptr; + return strchr(getAttributesString(ID), 'F') != nullptr; } /// Determines whether this builtin is a predefined libc/libm @@ -158,21 +289,21 @@ class Context { /// they do not, but they are recognized as builtins once we see /// a declaration. bool isPredefinedLibFunction(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'f') != nullptr; + return strchr(getAttributesString(ID), 'f') != nullptr; } /// Returns true if this builtin requires appropriate header in other /// compilers. In Clang it will work even without including it, but we can emit /// a warning about missing header. bool isHeaderDependentFunction(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'h') != nullptr; + return strchr(getAttributesString(ID), 'h') != nullptr; } /// Determines whether this builtin is a predefined compiler-rt/libgcc /// function, such as "__clear_cache", where we know the signature a /// priori. bool isPredefinedRuntimeFunction(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'i') != nullptr; + return strchr(getAttributesString(ID), 'i') != nullptr; } /// Determines whether this builtin is a C++ standard library function @@ -180,7 +311,7 @@ class Context { /// specialization, where the signature is determined by the standard library /// declaration. bool isInStdNamespace(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'z') != nullptr; + return strchr(getAttributesString(ID), 'z') != nullptr; } /// Determines whether this builtin can have its address taken with no @@ -194,33 +325,33 @@ class Context { /// Determines whether this builtin has custom typechecking. bool hasCustomTypechecking(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 't') != nullptr; + return strchr(getAttributesString(ID), 't') != nullptr; } /// Determines whether a declaration of this builtin should be recognized /// even if the type doesn't match the specified signature. bool allowTypeMismatch(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'T') != nullptr || + return strchr(getAttributesString(ID), 'T') != nullptr || hasCustomTypechecking(ID); } /// Determines whether this builtin has a result or any arguments which /// are pointer types. bool hasPtrArgsOrResult(unsigned ID) const { - return strchr(getRecord(ID).Type, '*') != nullptr; + return strchr(getTypeString(ID), '*') != nullptr; } /// Return true if this builtin has a result or any arguments which are /// reference types. bool hasReferenceArgsOrResult(unsigned ID) const { - return strchr(getRecord(ID).Type, '&') != nullptr || - strchr(getRecord(ID).Type, 'A') != nullptr; + return strchr(getTypeString(ID), '&') != nullptr || + strchr(getTypeString(ID), 'A') != nullptr; } /// If this is a library function that comes from a specific /// header, retrieve that header name. const char *getHeaderName(unsigned ID) const { - return getRecord(ID).Header.getName(); + return getInfo(ID).Header.getName(); } /// Determine whether this builtin is like printf in its @@ -245,27 +376,25 @@ class Context { /// Such functions can be const when the MathErrno lang option and FP /// exceptions are disabled. bool isConstWithoutErrnoAndExceptions(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'e') != nullptr; + return strchr(getAttributesString(ID), 'e') != nullptr; } bool isConstWithoutExceptions(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'g') != nullptr; + return strchr(getAttributesString(ID), 'g') != nullptr; } - const char *getRequiredFeatures(unsigned ID) const { - return getRecord(ID).Features; - } + const char *getRequiredFeatures(unsigned ID) const; unsigned getRequiredVectorWidth(unsigned ID) const; /// Return true if builtin ID belongs to AuxTarget. bool isAuxBuiltinID(unsigned ID) const { - return ID >= (Builtin::FirstTSBuiltin + TSRecords.size()); + return ID >= (Builtin::FirstTSBuiltin + TSInfos.size()); } /// Return real builtin ID (i.e. ID it would have during compilation /// for AuxTarget). - unsigned getAuxBuiltinID(unsigned ID) const { return ID - TSRecords.size(); } + unsigned getAuxBuiltinID(unsigned ID) const { return ID - TSInfos.size(); } /// Returns true if this is a libc/libm function without the '__builtin_' /// prefix. @@ -277,16 +406,20 @@ class Context { /// Return true if this function can be constant evaluated by Clang frontend. bool isConstantEvaluated(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'E') != nullptr; + return strchr(getAttributesString(ID), 'E') != nullptr; } /// Returns true if this is an immediate (consteval) function bool isImmediate(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'G') != nullptr; + return strchr(getAttributesString(ID), 'G') != nullptr; } private: - const Info &getRecord(unsigned ID) const; + std::pair getStrTableAndInfo(unsigned ID) const; + + const Info &getInfo(unsigned ID) const { + return getStrTableAndInfo(ID).second; + } /// Helper function for isPrintfLike and isScanfLike. bool isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg, diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index e2c3d3c535571..32a09e2ceb385 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -1450,13 +1450,13 @@ def ElementwiseFma : Builtin { def ElementwiseAddSat : Builtin { let Spellings = ["__builtin_elementwise_add_sat"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr]; let Prototype = "void(...)"; } def ElementwiseSubSat : Builtin { let Spellings = ["__builtin_elementwise_sub_sat"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr]; let Prototype = "void(...)"; } diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def index 473b1d4698f04..7933686ffe84e 100644 --- a/clang/include/clang/Basic/BuiltinsAArch64.def +++ b/clang/include/clang/Basic/BuiltinsAArch64.def @@ -182,6 +182,9 @@ TARGET_HEADER_BUILTIN(_InterlockedExchange_rel, "NiNiD*Ni", "nh", INTRIN_H, TARGET_HEADER_BUILTIN(_InterlockedExchange64_acq, "LLiLLiD*LLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedExchange64_nf, "LLiLLiD*LLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedExchange64_rel, "LLiLLiD*LLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedExchangePointer_acq, "v*v*D*v*","nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedExchangePointer_nf, "v*v*D*v*","nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedExchangePointer_rel, "v*v*D*v*","nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_acq, "ccD*cc", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_nf, "ccD*cc", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") @@ -195,6 +198,8 @@ TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_rel, "NiNiD*NiNi", "nh", TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_acq, "LLiLLiD*LLiLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_nf, "LLiLLiD*LLiLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_rel, "LLiLLiD*LLiLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedCompareExchangePointer_acq, "v*v*D*v*v*","nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedCompareExchangePointer_rel, "v*v*D*v*v*","nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedCompareExchange128, "UcLLiD*LLiLLiLLi*", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedCompareExchange128_acq,"UcLLiD*LLiLLiLLi*", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") @@ -281,6 +286,16 @@ TARGET_HEADER_BUILTIN(__readx18word, "UsUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, TARGET_HEADER_BUILTIN(__readx18dword, "UNiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(__readx18qword, "ULLiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__addx18byte, "vUNiUc", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__addx18word, "vUNiUs", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__addx18dword, "vUNiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__addx18qword, "vUNiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") + +TARGET_HEADER_BUILTIN(__incx18byte, "vUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__incx18word, "vUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__incx18dword, "vUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__incx18qword, "vUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") + TARGET_HEADER_BUILTIN(_CopyDoubleFromInt64, "dSLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_CopyFloatFromInt32, "fSi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_CopyInt32FromFloat, "Sif", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def index 4758f6053ccb6..14c1746716cdd 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -616,8 +616,8 @@ TARGET_BUILTIN(__builtin_amdgcn_cvt_scalef32_sr_pk32_bf6_f32, "V6UiV32fUif", "nc TARGET_BUILTIN(__builtin_amdgcn_cvt_scalef32_sr_pk32_fp6_bf16, "V6UiV32yUif", "nc", "f16bf16-to-fp6bf6-cvt-scale-insts") TARGET_BUILTIN(__builtin_amdgcn_cvt_scalef32_sr_pk32_fp6_f16, "V6UiV32hUif", "nc", "f16bf16-to-fp6bf6-cvt-scale-insts") TARGET_BUILTIN(__builtin_amdgcn_cvt_scalef32_sr_pk32_fp6_f32, "V6UiV32fUif", "nc", "f16bf16-to-fp6bf6-cvt-scale-insts") -TARGET_BUILTIN(__builtin_amdgcn_bitop3_b32, "iiiiIUc", "nc", "bitop3-insts") -TARGET_BUILTIN(__builtin_amdgcn_bitop3_b16, "ssssIUc", "nc", "bitop3-insts") +TARGET_BUILTIN(__builtin_amdgcn_bitop3_b32, "iiiiIUi", "nc", "bitop3-insts") +TARGET_BUILTIN(__builtin_amdgcn_bitop3_b16, "ssssIUi", "nc", "bitop3-insts") TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_bf16_f32, "V2yV2yfUiIb", "nc", "f32-to-f16bf16-cvt-sr-insts") TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_f16_f32, "V2hV2hfUiIb", "nc", "f32-to-f16bf16-cvt-sr-insts") diff --git a/clang/include/clang/Basic/BuiltinsARM.def b/clang/include/clang/Basic/BuiltinsARM.def index 9ee918cb21475..5a7064a98045e 100644 --- a/clang/include/clang/Basic/BuiltinsARM.def +++ b/clang/include/clang/Basic/BuiltinsARM.def @@ -270,6 +270,9 @@ TARGET_HEADER_BUILTIN(_InterlockedExchange_rel, "NiNiD*Ni", "nh", INTRIN_H, TARGET_HEADER_BUILTIN(_InterlockedExchange64_acq, "LLiLLiD*LLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedExchange64_nf, "LLiLLiD*LLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedExchange64_rel, "LLiLLiD*LLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedExchangePointer_acq, "v*v*D*v*","nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedExchangePointer_nf, "v*v*D*v*","nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedExchangePointer_rel, "v*v*D*v*","nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_acq, "ccD*cc", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_nf, "ccD*cc", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") @@ -283,6 +286,8 @@ TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_rel, "NiNiD*NiNi", "nh", TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_acq, "LLiLLiD*LLiLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_nf, "LLiLLiD*LLiLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_rel, "LLiLLiD*LLiLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedCompareExchangePointer_acq, "v*v*D*v*v*","nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedCompareExchangePointer_rel, "v*v*D*v*v*","nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedOr8_acq, "ccD*c", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedOr8_nf, "ccD*c", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def index 161df386f00f0..bb7d54bbb793e 100644 --- a/clang/include/clang/Basic/BuiltinsPPC.def +++ b/clang/include/clang/Basic/BuiltinsPPC.def @@ -1138,5 +1138,6 @@ UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2nn, "vW512*VVi15i15i3", true, // FIXME: Obviously incomplete. #undef BUILTIN +#undef TARGET_BUILTIN #undef CUSTOM_BUILTIN #undef UNALIASED_CUSTOM_BUILTIN diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 4cf22c4ee08ce..0f4ed13d5f3d8 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -242,7 +242,7 @@ ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Defa CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. -CODEGENOPT(PointerTBAA, 1, 0) ///< Whether or not to use distinct TBAA tags for pointers. +CODEGENOPT(PointerTBAA , 1, 1) ///< Whether or not to use distinct TBAA tags for pointers. CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA. CODEGENOPT(NewStructPathTBAA , 1, 0) ///< Whether or not to use enhanced struct-path TBAA. CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h index d271accca3d3b..510b782e35d06 100644 --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -560,7 +560,8 @@ class DiagnosticsEngine : public RefCountedBase { ArgToStringFnTy ArgToStringFn; /// Whether the diagnostic should be suppressed in FilePath. - llvm::unique_function + llvm::unique_function DiagSuppressionMapping; public: @@ -972,7 +973,7 @@ class DiagnosticsEngine : public RefCountedBase { /// These take presumed locations into account, and can still be overriden by /// clang-diagnostics pragmas. void setDiagSuppressionMapping(llvm::MemoryBuffer &Input); - bool isSuppressedViaMapping(diag::kind DiagId, StringRef FilePath) const; + bool isSuppressedViaMapping(diag::kind DiagId, SourceLocation DiagLoc) const; /// Issue the message to the client. /// diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8020be6c57bcf..f185a98720f5b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10269,6 +10269,16 @@ def warn_depr_array_comparison : Warning< "to compare array addresses, use unary '+' to decay operands to pointers">, InGroup; +def warn_array_comparison : Warning< + "comparison between two arrays compare their addresses and will be deprecated in c++20; " + "to compare array addresses, use unary '+' to decay operands to pointers">, + InGroup>; + +def warn_array_comparison_cxx26 : Warning< + "comparison between two arrays is ill-formed in C++26; " + "to compare array addresses, use unary '+' to decay operands to pointers">, + InGroup>, DefaultError; + def warn_stringcompare : Warning< "result of comparison against %select{a string literal|@encode}0 is " "unspecified (use an explicit string comparison function instead)">, @@ -12750,21 +12760,22 @@ def err_acc_gang_multiple_elt : Error<"OpenACC 'gang' clause may have at most one %select{unnamed or " "'num'|'dim'|'static'}0 argument">; def err_acc_int_arg_invalid - : Error<"'%1' argument on '%0' clause is not permitted on a%select{n " - "orphaned|||}2 'loop' construct %select{|associated with a " - "'parallel' compute construct|associated with a 'kernels' compute " - "construct|associated with a 'serial' compute construct}2">; + : Error<"'%0' argument on '%1' clause is not permitted on a%select{|n " + "orphaned}2 '%3' construct%select{| associated with a '%5' compute " + "construct}4">; def err_acc_gang_dim_value : Error<"argument to 'gang' clause dimension must be %select{a constant " "expression|1, 2, or 3: evaluated to %1}0">; def err_acc_num_arg_conflict - : Error<"'num' argument to '%0' clause not allowed on a 'loop' construct " - "associated with a 'kernels' construct that has a " - "'%select{num_gangs|num_workers|vector_length}1' " - "clause">; + : Error<"'%0' argument to '%1' clause not allowed on a '%2' " + "construct%select{| associated with a '%4' construct}3 that has a " + "'%5' clause">; +def err_acc_num_arg_conflict_reverse + : Error<"'%0' clause not allowed on a 'kernels loop' construct that " + "has a '%1' clause with a%select{n| 'num'}2 argument">; def err_acc_clause_in_clause_region : Error<"loop with a '%0' clause may not exist in the region of a '%1' " - "clause%select{| on a 'kernels' compute construct}2">; + "clause%select{| on a '%3' construct}2">; def err_acc_gang_reduction_conflict : Error<"%select{OpenACC 'gang' clause with a 'dim' value greater than " "1|OpenACC 'reduction' clause}0 cannot " diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 39e4851dd3814..3b833240e5b68 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -178,6 +178,7 @@ LANGOPT(PointerAuthInitFini, 1, 0, "sign function pointers in init/fini arrays") LANGOPT(PointerAuthInitFiniAddressDiscrimination, 1, 0, "incorporate address discrimination in authenticated function pointers in init/fini arrays") LANGOPT(PointerAuthELFGOT, 1, 0, "authenticate pointers from GOT") +LANGOPT(AArch64JumpTableHardening, 1, 0, "use hardened lowering for jump-table dispatch") LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes") LANGOPT(ExperimentalLateParseAttributes, 1, 0, "experimental late parsing of attributes") diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h index 3deb666b37513..a3a3e50bcde5d 100644 --- a/clang/include/clang/Basic/PointerAuthOptions.h +++ b/clang/include/clang/Basic/PointerAuthOptions.h @@ -172,6 +172,9 @@ struct PointerAuthOptions { /// Do indirect goto label addresses need to be authenticated? bool IndirectGotos = false; + /// Use hardened lowering for jump-table dispatch? + bool AArch64JumpTableHardening = false; + /// The ABI for C function pointers. PointerAuthSchema FunctionPointers; diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 4420228793e95..52a1ac9781395 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -16,6 +16,7 @@ #include "clang/Basic/AddressSpaces.h" #include "clang/Basic/BitmaskEnum.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/CFProtectionOptions.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/LLVM.h" @@ -1009,11 +1010,11 @@ class TargetInfo : public TransferrableTargetInfo, virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const = 0; - - /// Return information about target-specific builtins for - /// the current primary target, and info about which builtins are non-portable - /// across the current set of primary and secondary targets. - virtual ArrayRef getTargetBuiltins() const = 0; + /// Return information about target-specific builtins for the current primary + /// target, and info about which builtins are non-portable across the current + /// set of primary and secondary targets. + virtual std::pair> + getTargetBuiltinStorage() const = 0; /// Returns target-specific min and max values VScale_Range. virtual std::optional> diff --git a/clang/include/clang/Basic/arm_mve.td b/clang/include/clang/Basic/arm_mve.td index 93abbc47c54dd..6dd8c52ddfd77 100644 --- a/clang/include/clang/Basic/arm_mve.td +++ b/clang/include/clang/Basic/arm_mve.td @@ -1270,13 +1270,13 @@ defm sqrshr: ScalarSaturatingShiftReg; def lsll: LongScalarShift $lo, $hi, $sh)>; def asrl: LongScalarShift $lo, $hi, $sh)>; -multiclass vadcsbc { +multiclass vadcsbc { def q: Intrinsic:$carry), (seq (IRInt $a, $b, (shl (load $carry), 29)):$pair, (store (and 1, (lshr (xval $pair, 1), 29)), $carry), (xval $pair, 0))>; def iq: Intrinsic:$carry), - (seq (IRInt $a, $b, 0):$pair, + (seq (IRInt $a, $b, initial_carry_in):$pair, (store (and 1, (lshr (xval $pair, 1), 29)), $carry), (xval $pair, 0))>; def q_m: Intrinsic:$carry, Predicate:$pred), (seq (IRInt $inactive, $a, $b, - 0, $pred):$pair, + initial_carry_in, $pred):$pair, (store (and 1, (lshr (xval $pair, 1), 29)), $carry), (xval $pair, 0))>; } let params = T.Int32 in { - defm vadc: vadcsbc; - defm vsbc: vadcsbc; + defm vadc: vadcsbc<(u32 0)>; + defm vsbc: vadcsbc<(shl 1, 29)>; } let params = T.Int in { diff --git a/clang/include/clang/Basic/arm_sme.td b/clang/include/clang/Basic/arm_sme.td index 0f689e82bdb74..71b2c7cdd04f9 100644 --- a/clang/include/clang/Basic/arm_sme.td +++ b/clang/include/clang/Basic/arm_sme.td @@ -824,4 +824,14 @@ let SMETargetGuard = "sme-lutv2" in { def SVLUTI4_ZT_X4 : SInst<"svluti4_zt_{d}_x4", "4i2.u", "cUc", MergeNone, "aarch64_sme_luti4_zt_x4", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>]>; } +let SMETargetGuard = "sme-f8f32" in { + def SVMOPA_FP8_ZA32 : Inst<"svmopa_za32[_mf8]_m_fpm", "viPPdd>", "m", MergeNone, "aarch64_sme_fp8_fmopa_za32", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<0, ImmCheck0_3>]>; +} + +let SMETargetGuard = "sme-f8f16" in { + def SVMOPA_FP8_ZA16 : Inst<"svmopa_za16[_mf8]_m_fpm", "viPPdd>", "m", MergeNone, "aarch64_sme_fp8_fmopa_za16", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<0, ImmCheck0_1>]>; +} + } // let SVETargetGuard = InvalidMode diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td index e551d6e46b8f3..9b8a8546b072c 100644 --- a/clang/include/clang/Basic/arm_sve.td +++ b/clang/include/clang/Basic/arm_sve.td @@ -2429,6 +2429,10 @@ let SVETargetGuard = InvalidMode, SMETargetGuard = "sme2,fp8" in { def FSCALE_X2 : Inst<"svscale[_{d}_x2]", "222.x", "fhd", MergeNone, "aarch64_sme_fp8_scale_x2", [IsStreaming],[]>; def FSCALE_X4 : Inst<"svscale[_{d}_x4]", "444.x", "fhd", MergeNone, "aarch64_sme_fp8_scale_x4", [IsStreaming],[]>; + // Convert from FP8 to half-precision/BFloat16 multi-vector + def SVF1CVT : Inst<"svcvt1_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvt1_x2", [IsStreaming, SetsFPMR], []>; + def SVF2CVT : Inst<"svcvt2_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvt2_x2", [IsStreaming, SetsFPMR], []>; + // Convert from FP8 to deinterleaved half-precision/BFloat16 multi-vector def SVF1CVTL : Inst<"svcvtl1_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvtl1_x2", [IsStreaming, SetsFPMR], []>; def SVF2CVTL : Inst<"svcvtl2_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvtl2_x2", [IsStreaming, SetsFPMR], []>; diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 4462eb6fc00ba..0d6c65ecf4102 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -15,6 +15,7 @@ #define LLVM_CLANG_CIR_DIALECT_IR_CIROPS include "clang/CIR/Dialect/IR/CIRDialect.td" +include "clang/CIR/Dialect/IR/CIRTypes.td" include "mlir/IR/BuiltinAttributeInterfaces.td" include "mlir/IR/EnumAttr.td" @@ -74,6 +75,35 @@ class LLVMLoweringInfo { class CIR_Op traits = []> : Op, LLVMLoweringInfo; +//===----------------------------------------------------------------------===// +// GlobalOp +//===----------------------------------------------------------------------===// + +// TODO(CIR): For starters, cir.global has only name and type. The other +// properties of a global variable will be added over time as more of ClangIR +// is upstreamed. + +def GlobalOp : CIR_Op<"global"> { + let summary = "Declare or define a global variable"; + let description = [{ + The `cir.global` operation declares or defines a named global variable. + + The backing memory for the variable is allocated statically and is + described by the type of the variable. + }]; + + let arguments = (ins SymbolNameAttr:$sym_name, TypeAttr:$sym_type); + + let assemblyFormat = [{ $sym_name `:` $sym_type attr-dict }]; + + let skipDefaultBuilders = 1; + + let builders = [OpBuilder<(ins "llvm::StringRef":$sym_name, + "mlir::Type":$sym_type)>]; + + let hasVerifier = 1; +} + //===----------------------------------------------------------------------===// // FuncOp //===----------------------------------------------------------------------===// @@ -85,14 +115,15 @@ class CIR_Op traits = []> : def FuncOp : CIR_Op<"func"> { let summary = "Declare or define a function"; let description = [{ - ... lots of text to be added later ... + The `cir.func` operation defines a function, similar to the `mlir::FuncOp` + built-in. }]; let arguments = (ins SymbolNameAttr:$sym_name); let skipDefaultBuilders = 1; - let builders = [OpBuilder<(ins "llvm::StringRef":$name)>]; + let builders = [OpBuilder<(ins "llvm::StringRef":$sym_name)>]; let hasCustomAssemblyFormat = 1; let hasVerifier = 1; diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h new file mode 100644 index 0000000000000..2bc7d77b2bc8a --- /dev/null +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the types in the CIR dialect. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_CIR_IR_CIRTYPES_H_ +#define MLIR_DIALECT_CIR_IR_CIRTYPES_H_ + +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/Types.h" +#include "mlir/Interfaces/DataLayoutInterfaces.h" + +//===----------------------------------------------------------------------===// +// CIR Dialect Tablegen'd Types +//===----------------------------------------------------------------------===// + +#define GET_TYPEDEF_CLASSES +#include "clang/CIR/Dialect/IR/CIROpsTypes.h.inc" + +#endif // MLIR_DIALECT_CIR_IR_CIRTYPES_H_ diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td new file mode 100644 index 0000000000000..ce0b6ba1d68c5 --- /dev/null +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -0,0 +1,132 @@ +//===- CIRTypes.td - CIR dialect types ---------------------*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the CIR dialect types. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_CIR_DIALECT_CIR_TYPES +#define MLIR_CIR_DIALECT_CIR_TYPES + +include "clang/CIR/Dialect/IR/CIRDialect.td" +include "mlir/Interfaces/DataLayoutInterfaces.td" +include "mlir/IR/AttrTypeBase.td" + +//===----------------------------------------------------------------------===// +// CIR Types +//===----------------------------------------------------------------------===// + +class CIR_Type traits = [], + string baseCppClass = "::mlir::Type"> + : TypeDef { + let mnemonic = typeMnemonic; +} + +//===----------------------------------------------------------------------===// +// IntType +//===----------------------------------------------------------------------===// + +def CIR_IntType : CIR_Type<"Int", "int", + [DeclareTypeInterfaceMethods]> { + let summary = "Integer type with arbitrary precision up to a fixed limit"; + let description = [{ + CIR type that represents integer types with arbitrary precision, including + standard integral types such as `int` and `long`, extended integral types + such as `__int128`, and arbitrary width types such as `_BitInt(n)`. + + Those integer types that are directly available in C/C++ standard are called + primitive integer types. Said types are: `signed char`, `short`, `int`, + `long`, `long long`, and their unsigned variations. + }]; + let parameters = (ins "unsigned":$width, "bool":$isSigned); + let hasCustomAssemblyFormat = 1; + let extraClassDeclaration = [{ + /// Return true if this is a signed integer type. + bool isSigned() const { return getIsSigned(); } + /// Return true if this is an unsigned integer type. + bool isUnsigned() const { return !getIsSigned(); } + /// Return type alias. + std::string getAlias() const { + return (isSigned() ? 's' : 'u') + std::to_string(getWidth()) + 'i'; + } + /// Return true if this is a primitive integer type (i.e. signed or unsigned + /// integer types whose bit width is 8, 16, 32, or 64). + bool isPrimitive() const { + return isValidPrimitiveIntBitwidth(getWidth()); + } + bool isSignedPrimitive() const { + return isPrimitive() && isSigned(); + } + + /// Returns a minimum bitwidth of cir::IntType + static unsigned minBitwidth() { return 1; } + /// Returns a maximum bitwidth of cir::IntType + static unsigned maxBitwidth() { return 128; } + + /// Returns true if cir::IntType that represents a primitive integer type + /// can be constructed from the provided bitwidth. + static bool isValidPrimitiveIntBitwidth(unsigned width) { + return width == 8 || width == 16 || width == 32 || width == 64; + } + }]; + let genVerifyDecl = 1; +} + +// Constraints + +// Unsigned integer type of a specific width. +class UInt + : Type($_self)">, + CPred<"::mlir::cast<::cir::IntType>($_self).isUnsigned()">, + CPred<"::mlir::cast<::cir::IntType>($_self).getWidth() == " # width> + ]>, width # "-bit unsigned integer", "::cir::IntType">, + BuildableType< + "cir::IntType::get($_builder.getContext(), " + # width # ", /*isSigned=*/false)"> { + int bitwidth = width; +} + +def UInt1 : UInt<1>; +def UInt8 : UInt<8>; +def UInt16 : UInt<16>; +def UInt32 : UInt<32>; +def UInt64 : UInt<64>; + +// Signed integer type of a specific width. +class SInt + : Type($_self)">, + CPred<"::mlir::cast<::cir::IntType>($_self).isSigned()">, + CPred<"::mlir::cast<::cir::IntType>($_self).getWidth() == " # width> + ]>, width # "-bit signed integer", "::cir::IntType">, + BuildableType< + "cir::IntType::get($_builder.getContext(), " + # width # ", /*isSigned=*/true)"> { + int bitwidth = width; +} + +def SInt1 : SInt<1>; +def SInt8 : SInt<8>; +def SInt16 : SInt<16>; +def SInt32 : SInt<32>; +def SInt64 : SInt<64>; + +def PrimitiveUInt + : AnyTypeOf<[UInt8, UInt16, UInt32, UInt64], "primitive unsigned int", + "::cir::IntType">; + +def PrimitiveSInt + : AnyTypeOf<[SInt8, SInt16, SInt32, SInt64], "primitive signed int", + "::cir::IntType">; + +def PrimitiveInt + : AnyTypeOf<[UInt8, UInt16, UInt32, UInt64, SInt8, SInt16, SInt32, SInt64], + "primitive int", "::cir::IntType">; + +#endif // MLIR_CIR_DIALECT_CIR_TYPES diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index 9177d56718ee7..c23d037e725bb 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -297,8 +297,11 @@ class Driver { /// Object that stores strings read from configuration file. llvm::StringSaver Saver; - /// Arguments originated from configuration file. - std::unique_ptr CfgOptions; + /// Arguments originated from configuration file (head part). + std::unique_ptr CfgOptionsHead; + + /// Arguments originated from configuration file (tail part). + std::unique_ptr CfgOptionsTail; /// Arguments originated from command line. std::unique_ptr CLOptions; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 4bc0b97ea68f2..bd5e35c677b44 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -240,7 +240,8 @@ def m_riscv_Features_Group : OptionGroup<"">, def m_ve_Features_Group : OptionGroup<"">, Group, DocName<"VE">; def m_loongarch_Features_Group : OptionGroup<"">, - Group, DocName<"LoongArch">; + Group, DocName<"LoongArch">, + Visibility<[ClangOption, CLOption, FlangOption]>; def m_libc_Group : OptionGroup<"">, Group, Flags<[HelpHidden]>; @@ -4353,6 +4354,7 @@ defm ptrauth_init_fini : OptInCC1FFlag<"ptrauth-init-fini", "Enable signing of f defm ptrauth_init_fini_address_discrimination : OptInCC1FFlag<"ptrauth-init-fini-address-discrimination", "Enable address discrimination of function pointers in init/fini arrays">; defm ptrauth_elf_got : OptInCC1FFlag<"ptrauth-elf-got", "Enable authentication of pointers from GOT (ELF only)">; +defm aarch64_jump_table_hardening: OptInCC1FFlag<"aarch64-jump-table-hardening", "Use hardened lowering for jump-table dispatch">; } def fenable_matrix : Flag<["-"], "fenable-matrix">, Group, @@ -7387,9 +7389,12 @@ def fuse_register_sized_bitfield_access: Flag<["-"], "fuse-register-sized-bitfie def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">, HelpText<"Turn off Type Based Alias Analysis">, MarshallingInfoFlag>; -def pointer_tbaa: Flag<["-"], "pointer-tbaa">, - HelpText<"Turn on Type Based Alias Analysis for pointer accesses">, - MarshallingInfoFlag>; +defm pointer_tbaa: BoolOption<"", "pointer-tbaa", CodeGenOpts<"PointerTBAA">, +DefaultTrue, + PosFlag, + NegFlag, + BothFlags<[], [ClangOption], " that single precision floating-point divide and sqrt used in ">> + ; def no_struct_path_tbaa : Flag<["-"], "no-struct-path-tbaa">, HelpText<"Turn off struct-path aware Type Based Alias Analysis">, MarshallingInfoNegativeFlag>; diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index d720cf3c74d87..a4132534686a8 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -164,9 +164,14 @@ class SemaOpenACC : public SemaBase { } /// If there is a current 'active' loop construct with a 'gang' clause on a - /// 'kernel' construct, this will have the source location for it. This - /// permits us to implement the restriction of no further 'gang' clauses. - SourceLocation LoopGangClauseOnKernelLoc; + /// 'kernel' construct, this will have the source location for it, and the + /// 'kernel kind'. This permits us to implement the restriction of no further + /// 'gang' clauses. + struct LoopGangOnKernelTy { + SourceLocation Loc; + OpenACCDirectiveKind DirKind = OpenACCDirectiveKind::Invalid; + } LoopGangClauseOnKernel; + /// If there is a current 'active' loop construct with a 'worker' clause on it /// (on any sort of construct), this has the source location for it. This /// permits us to implement the restriction of no further 'gang' or 'worker' @@ -705,7 +710,9 @@ class SemaOpenACC : public SemaBase { ExprResult CheckTileSizeExpr(Expr *SizeExpr); // Check a single expression on a gang clause. - ExprResult CheckGangExpr(OpenACCGangKind GK, Expr *E); + ExprResult CheckGangExpr(ArrayRef ExistingClauses, + OpenACCDirectiveKind DK, OpenACCGangKind GK, + Expr *E); // Does the checking for a 'gang' clause that needs to be done in dependent // and not dependent cases. @@ -771,7 +778,7 @@ class SemaOpenACC : public SemaBase { SemaOpenACC &SemaRef; ComputeConstructInfo OldActiveComputeConstructInfo; OpenACCDirectiveKind DirKind; - SourceLocation OldLoopGangClauseOnKernelLoc; + LoopGangOnKernelTy OldLoopGangClauseOnKernel; SourceLocation OldLoopWorkerClauseLoc; SourceLocation OldLoopVectorClauseLoc; LoopWithoutSeqCheckingInfo OldLoopWithoutSeqInfo; diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 9be82622f264c..b34e940682fc5 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -1749,6 +1749,10 @@ def UncountedLambdaCapturesChecker : Checker<"UncountedLambdaCapturesChecker">, let ParentPackage = WebKitAlpha in { +def MemoryUnsafeCastChecker : Checker<"MemoryUnsafeCastChecker">, + HelpText<"Check for memory unsafe casts from base type to derived type.">, + Documentation; + def NoUncheckedPtrMemberChecker : Checker<"NoUncheckedPtrMemberChecker">, HelpText<"Check for no unchecked member variables.">, Documentation; diff --git a/clang/lib/AST/ByteCode/BitcastBuffer.cpp b/clang/lib/AST/ByteCode/BitcastBuffer.cpp new file mode 100644 index 0000000000000..fbd500fd8f5f4 --- /dev/null +++ b/clang/lib/AST/ByteCode/BitcastBuffer.cpp @@ -0,0 +1,170 @@ +//===-------------------- Bitcastbuffer.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 "BitcastBuffer.h" +#include "llvm/ADT/STLExtras.h" + +using namespace clang; +using namespace clang::interp; + +/// Returns the value of the bit in the given sequence of bytes. +static inline bool bitof(const std::byte *B, Bits BitIndex) { + return (B[BitIndex.roundToBytes()] & + (std::byte{1} << BitIndex.getOffsetInByte())) != std::byte{0}; +} + +void BitcastBuffer::pushData(const std::byte *In, Bits BitOffset, Bits BitWidth, + Endian TargetEndianness) { + for (unsigned It = 0; It != BitWidth.getQuantity(); ++It) { + bool BitValue = bitof(In, Bits(It)); + if (!BitValue) + continue; + + Bits DstBit; + if (TargetEndianness == Endian::Little) + DstBit = BitOffset + Bits(It); + else + DstBit = size() - BitOffset - BitWidth + Bits(It); + + size_t DstByte = DstBit.roundToBytes(); + Data[DstByte] |= std::byte{1} << DstBit.getOffsetInByte(); + } +} + +std::unique_ptr +BitcastBuffer::copyBits(Bits BitOffset, Bits BitWidth, Bits FullBitWidth, + Endian TargetEndianness) const { + assert(BitWidth.getQuantity() <= FullBitWidth.getQuantity()); + assert(FullBitWidth.isFullByte()); + auto Out = std::make_unique(FullBitWidth.roundToBytes()); + + for (unsigned It = 0; It != BitWidth.getQuantity(); ++It) { + Bits BitIndex; + if (TargetEndianness == Endian::Little) + BitIndex = BitOffset + Bits(It); + else + BitIndex = size() - BitWidth - BitOffset + Bits(It); + + bool BitValue = bitof(Data.get(), BitIndex); + if (!BitValue) + continue; + + Bits DstBit = Bits(It); + size_t DstByte = DstBit.roundToBytes(); + Out[DstByte] |= std::byte{1} << DstBit.getOffsetInByte(); + } + + return Out; +} + +bool BitcastBuffer::allInitialized() const { + return rangeInitialized(Bits::zero(), FinalBitSize); +} + +void BitcastBuffer::markInitialized(Bits Offset, Bits Length) { + if (Length.isZero()) + return; + + BitRange Element(Offset, Offset + Length - Bits(1)); + if (InitializedBits.empty()) { + InitializedBits.push_back(Element); + return; + } + + assert(InitializedBits.size() >= 1); + // Common case of just appending. + Bits End = InitializedBits.back().End; + if (End <= Offset) { + // Merge this range with the last one. + // In the best-case scenario, this means we only ever have + // one single bit range covering all bits. + if (End == (Offset - Bits(1))) { + InitializedBits.back().End = Element.End; + return; + } + + // Otherwise, we can simply append. + InitializedBits.push_back(Element); + } else { + // Insert sorted. + auto It = std::upper_bound(InitializedBits.begin(), InitializedBits.end(), + Element); + InitializedBits.insert(It, Element); + } + +#ifndef NDEBUG + // Ensure ranges are sorted and non-overlapping. + assert(llvm::is_sorted(InitializedBits)); + for (unsigned I = 1; I != InitializedBits.size(); ++I) { + [[maybe_unused]] auto Prev = InitializedBits[I - 1]; + [[maybe_unused]] auto Cur = InitializedBits[I]; + assert(Prev.End.N < Cur.Start.N); + } +#endif +} + +bool BitcastBuffer::rangeInitialized(Bits Offset, Bits Length) const { + if (Length.isZero()) + return true; + + BitRange Range(Offset, Offset + Length - Bits(1)); + Bits Sum; + bool FoundStart = false; + for (BitRange BR : InitializedBits) { + if (FoundStart) { + if (BR.contains(Range.End)) { + Sum += (Range.End - BR.Start + Bits(1)); + break; + } + + // Else, BR is completely inside Range. + Sum += BR.size(); + } + if (BR.contains(Range.Start)) { + Sum += (BR.End - Range.Start + Bits(1)); + FoundStart = true; + } + } + + // Note that Sum can be larger than Range, e.g. when Range is fully + // contained in one range. + return Sum >= Range.size(); +} + +#if 0 + template + static std::string hex(T t) { + std::stringstream stream; + stream << std::hex << (int)t; + return std::string(stream.str()); + } + + + void BitcastBuffer::dump(bool AsHex = true) const { + llvm::errs() << "LSB\n "; + unsigned LineLength = 0; + for (unsigned I = 0; I != (FinalBitSize / 8); ++I) { + std::byte B = Data[I]; + if (AsHex) { + std::stringstream stream; + stream << std::hex << (int)B; + llvm::errs() << stream.str(); + LineLength += stream.str().size() + 1; + } else { + llvm::errs() << std::bitset<8>((int)B).to_string(); + LineLength += 8 + 1; + // llvm::errs() << (int)B; + } + llvm::errs() << ' '; + } + llvm::errs() << '\n'; + + for (unsigned I = 0; I != LineLength; ++I) + llvm::errs() << ' '; + llvm::errs() << "MSB\n"; + } +#endif diff --git a/clang/lib/AST/ByteCode/BitcastBuffer.h b/clang/lib/AST/ByteCode/BitcastBuffer.h new file mode 100644 index 0000000000000..b1b6b9e5173a7 --- /dev/null +++ b/clang/lib/AST/ByteCode/BitcastBuffer.h @@ -0,0 +1,111 @@ +//===--------------------- BitcastBuffer.h ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_INTERP_BITCAST_BUFFER_H +#define LLVM_CLANG_AST_INTERP_BITCAST_BUFFER_H + +#include "llvm/ADT/SmallVector.h" +#include +#include +#include + +namespace clang { +namespace interp { + +enum class Endian { Little, Big }; + +/// A quantity in bits. +struct Bits { + size_t N = 0; + Bits() = default; + static Bits zero() { return Bits(0); } + explicit Bits(size_t Quantity) : N(Quantity) {} + size_t getQuantity() const { return N; } + size_t roundToBytes() const { return N / 8; } + size_t getOffsetInByte() const { return N % 8; } + bool isFullByte() const { return N % 8 == 0; } + bool nonZero() const { return N != 0; } + bool isZero() const { return N == 0; } + + Bits operator-(Bits Other) const { return Bits(N - Other.N); } + Bits operator+(Bits Other) const { return Bits(N + Other.N); } + Bits operator+=(size_t O) { + N += O; + return *this; + } + Bits operator+=(Bits O) { + N += O.N; + return *this; + } + + bool operator>=(Bits Other) const { return N >= Other.N; } + bool operator<=(Bits Other) const { return N <= Other.N; } + bool operator==(Bits Other) const { return N == Other.N; } + bool operator!=(Bits Other) const { return N != Other.N; } +}; + +/// A quantity in bytes. +struct Bytes { + size_t N; + explicit Bytes(size_t Quantity) : N(Quantity) {} + size_t getQuantity() const { return N; } + Bits toBits() const { return Bits(N * 8); } +}; + +/// A bit range. Both Start and End are inclusive. +struct BitRange { + Bits Start; + Bits End; + + BitRange(Bits Start, Bits End) : Start(Start), End(End) {} + Bits size() const { return End - Start + Bits(1); } + bool operator<(BitRange Other) const { return Start.N < Other.Start.N; } + + bool contains(Bits B) { return Start <= B && End >= B; } +}; + +/// Track what bits have been initialized to known values and which ones +/// have indeterminate value. +struct BitcastBuffer { + Bits FinalBitSize; + std::unique_ptr Data; + llvm::SmallVector InitializedBits; + + BitcastBuffer(Bits FinalBitSize) : FinalBitSize(FinalBitSize) { + assert(FinalBitSize.isFullByte()); + unsigned ByteSize = FinalBitSize.roundToBytes(); + Data = std::make_unique(ByteSize); + } + + /// Returns the buffer size in bits. + Bits size() const { return FinalBitSize; } + + /// Returns \c true if all bits in the buffer have been initialized. + bool allInitialized() const; + /// Marks the bits in the given range as initialized. + /// FIXME: Can we do this automatically in pushData()? + void markInitialized(Bits Start, Bits Length); + bool rangeInitialized(Bits Offset, Bits Length) const; + + /// Push \p BitWidth bits at \p BitOffset from \p In into the buffer. + /// \p TargetEndianness is the endianness of the target we're compiling for. + /// \p In must hold at least \p BitWidth many bits. + void pushData(const std::byte *In, Bits BitOffset, Bits BitWidth, + Endian TargetEndianness); + + /// Copy \p BitWidth bits at offset \p BitOffset from the buffer. + /// \p TargetEndianness is the endianness of the target we're compiling for. + /// + /// The returned output holds exactly (\p FullBitWidth / 8) bytes. + std::unique_ptr copyBits(Bits BitOffset, Bits BitWidth, + Bits FullBitWidth, + Endian TargetEndianness) const; +}; + +} // namespace interp +} // namespace clang +#endif diff --git a/clang/lib/AST/ByteCode/Boolean.h b/clang/lib/AST/ByteCode/Boolean.h index 78d75e75c7531..8380e85865ac5 100644 --- a/clang/lib/AST/ByteCode/Boolean.h +++ b/clang/lib/AST/ByteCode/Boolean.h @@ -82,9 +82,7 @@ class Boolean final { Boolean truncate(unsigned TruncBits) const { return *this; } static Boolean bitcastFromMemory(const std::byte *Buff, unsigned BitWidth) { - // Boolean width is currently always 8 for all supported targets. If this - // changes we need to get the bool width from the target info. - assert(BitWidth == 8); + // Just load the first byte. bool Val = static_cast(*Buff); return Boolean(Val); } diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index eb102f1e5c7f2..7f6295e126dcf 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -355,7 +355,9 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { std::nullopt, true, false, /*IsMutable=*/false, nullptr); } - return this->emitNull(classifyPrim(CE->getType()), Desc, CE); + + uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(CE->getType()); + return this->emitNull(classifyPrim(CE->getType()), Val, Desc, CE); } case CK_PointerToIntegral: { @@ -3817,7 +3819,7 @@ template bool Compiler::visitBool(const Expr *E) { // Convert pointers to bool. if (T == PT_Ptr || T == PT_FnPtr) { - if (!this->emitNull(*T, nullptr, E)) + if (!this->emitNull(*T, 0, nullptr, E)) return false; return this->emitNE(*T, E); } @@ -3857,11 +3859,12 @@ bool Compiler::visitZeroInitializer(PrimType T, QualType QT, case PT_IntAPS: return this->emitZeroIntAPS(Ctx.getBitWidth(QT), E); case PT_Ptr: - return this->emitNullPtr(nullptr, E); + return this->emitNullPtr(Ctx.getASTContext().getTargetNullPointerValue(QT), + nullptr, E); case PT_FnPtr: - return this->emitNullFnPtr(nullptr, E); + return this->emitNullFnPtr(0, nullptr, E); case PT_MemberPtr: - return this->emitNullMemberPtr(nullptr, E); + return this->emitNullMemberPtr(0, nullptr, E); case PT_Float: return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E); case PT_FixedPoint: { @@ -4421,7 +4424,7 @@ bool Compiler::visitAPValue(const APValue &Val, PrimType ValType, if (Val.isLValue()) { if (Val.isNullPointer()) - return this->emitNull(ValType, nullptr, E); + return this->emitNull(ValType, 0, nullptr, E); APValue::LValueBase Base = Val.getLValueBase(); if (const Expr *BaseExpr = Base.dyn_cast()) return this->visit(BaseExpr); @@ -4431,7 +4434,7 @@ bool Compiler::visitAPValue(const APValue &Val, PrimType ValType, } else if (Val.isMemberPointer()) { if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl()) return this->emitGetMemberPtr(MemberDecl, E); - return this->emitNullMemberPtr(nullptr, E); + return this->emitNullMemberPtr(0, nullptr, E); } return false; @@ -4783,7 +4786,8 @@ bool Compiler::VisitCXXNullPtrLiteralExpr( if (DiscardResult) return true; - return this->emitNullPtr(nullptr, E); + uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(E->getType()); + return this->emitNullPtr(Val, nullptr, E); } template @@ -5333,7 +5337,7 @@ bool Compiler::emitLambdaStaticInvokerBody(const CXXMethodDecl *MD) { // one here, and we don't need one either because the lambda cannot have // any captures, as verified above. Emit a null pointer. This is then // special-cased when interpreting to not emit any misleading diagnostics. - if (!this->emitNullPtr(nullptr, MD)) + if (!this->emitNullPtr(0, nullptr, MD)) return false; // Forward all arguments from the static invoker to the lambda call operator. @@ -6479,19 +6483,14 @@ bool Compiler::emitBuiltinBitCast(const CastExpr *E) { QualType ToType = E->getType(); std::optional ToT = classify(ToType); + // Bitcasting TO nullptr_t is always fine. if (ToType->isNullPtrType()) { if (!this->discard(SubExpr)) return false; - return this->emitNullPtr(nullptr, E); + return this->emitNullPtr(0, nullptr, E); } - if (FromType->isNullPtrType() && ToT) { - if (!this->discard(SubExpr)) - return false; - - return visitZeroInitializer(*ToT, ToType, E); - } assert(!ToType->isReferenceType()); // Prepare storage for the result in case we discard. diff --git a/clang/lib/AST/ByteCode/Integral.h b/clang/lib/AST/ByteCode/Integral.h index cb81b5a698924..26585799e5ead 100644 --- a/clang/lib/AST/ByteCode/Integral.h +++ b/clang/lib/AST/ByteCode/Integral.h @@ -183,6 +183,7 @@ template class Integral final { } Integral truncate(unsigned TruncBits) const { + assert(TruncBits >= 1); if (TruncBits >= Bits) return *this; const ReprT BitMask = (ReprT(1) << ReprT(TruncBits)) - 1; diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 25740c90d240a..cdf05e36304ac 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_AST_INTERP_INTERP_H #include "../ExprConstShared.h" +#include "BitcastBuffer.h" #include "Boolean.h" #include "DynamicAllocator.h" #include "FixedPoint.h" @@ -2432,9 +2433,11 @@ static inline bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) { } template ::T> -inline bool Null(InterpState &S, CodePtr OpPC, const Descriptor *Desc) { - // Note: Desc can be null. - S.Stk.push(0, Desc); +inline bool Null(InterpState &S, CodePtr OpPC, uint64_t Value, + const Descriptor *Desc) { + // FIXME(perf): This is a somewhat often-used function and the value of a + // null pointer is almost always 0. + S.Stk.push(Value, Desc); return true; } @@ -3048,7 +3051,16 @@ inline bool BitCast(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte, llvm::SmallVector Buff(BuffSize); bool HasIndeterminateBits = false; - if (!DoBitCast(S, OpPC, FromPtr, Buff.data(), BuffSize, HasIndeterminateBits)) + Bits FullBitWidth(ResultBitWidth); + Bits BitWidth = FullBitWidth; + + if constexpr (std::is_same_v) { + assert(Sem); + BitWidth = Bits(llvm::APFloatBase::getSizeInBits(*Sem)); + } + + if (!DoBitCast(S, OpPC, FromPtr, Buff.data(), BitWidth, FullBitWidth, + HasIndeterminateBits)) return false; if (!CheckBitCast(S, OpPC, HasIndeterminateBits, TargetIsUCharOrByte)) @@ -3056,16 +3068,7 @@ inline bool BitCast(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte, if constexpr (std::is_same_v) { assert(Sem); - ptrdiff_t Offset = 0; - - if (llvm::sys::IsBigEndianHost) { - unsigned NumBits = llvm::APFloatBase::getSizeInBits(*Sem); - assert(NumBits % 8 == 0); - assert(NumBits <= ResultBitWidth); - Offset = (ResultBitWidth - NumBits) / 8; - } - - S.Stk.push(T::bitcastFromMemory(Buff.data() + Offset, *Sem)); + S.Stk.push(T::bitcastFromMemory(Buff.data(), *Sem)); } else { assert(!Sem); S.Stk.push(T::bitcastFromMemory(Buff.data(), ResultBitWidth)); diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 85cffb0c4332d..a0de193ec32a2 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -197,9 +197,19 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, const Pointer &A = getParam(Frame, 0); const Pointer &B = getParam(Frame, 1); - if (ID == Builtin::BIstrcmp) + if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp) diagnoseNonConstexprBuiltin(S, OpPC, ID); + uint64_t Limit = ~static_cast(0); + if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp) + Limit = peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2))) + .getZExtValue(); + + if (Limit == 0) { + pushInteger(S, 0, Call->getType()); + return true; + } + if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read)) return false; @@ -212,7 +222,11 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, unsigned IndexA = A.getIndex(); unsigned IndexB = B.getIndex(); int32_t Result = 0; - for (;; ++IndexA, ++IndexB) { + uint64_t Steps = 0; + for (;; ++IndexA, ++IndexB, ++Steps) { + + if (Steps >= Limit) + break; const Pointer &PA = A.atIndex(IndexA); const Pointer &PB = B.atIndex(IndexB); if (!CheckRange(S, OpPC, PA, AK_Read) || @@ -243,7 +257,7 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, unsigned ID = Func->getBuiltinID(); const Pointer &StrPtr = getParam(Frame, 0); - if (ID == Builtin::BIstrlen) + if (ID == Builtin::BIstrlen || ID == Builtin::BIwcslen) diagnoseNonConstexprBuiltin(S, OpPC, ID); if (!CheckArray(S, OpPC, StrPtr)) @@ -256,6 +270,12 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, return false; assert(StrPtr.getFieldDesc()->isPrimitiveArray()); + unsigned ElemSize = StrPtr.getFieldDesc()->getElemSize(); + + if (ID == Builtin::BI__builtin_wcslen || ID == Builtin::BIwcslen) { + [[maybe_unused]] const ASTContext &AC = S.getASTContext(); + assert(ElemSize == AC.getTypeSizeInChars(AC.getWCharType()).getQuantity()); + } size_t Len = 0; for (size_t I = StrPtr.getIndex();; ++I, ++Len) { @@ -264,7 +284,20 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, if (!CheckRange(S, OpPC, ElemPtr, AK_Read)) return false; - uint8_t Val = ElemPtr.deref(); + uint32_t Val; + switch (ElemSize) { + case 1: + Val = ElemPtr.deref(); + break; + case 2: + Val = ElemPtr.deref(); + break; + case 4: + Val = ElemPtr.deref(); + break; + default: + llvm_unreachable("Unsupported char size"); + } if (Val == 0) break; } @@ -1827,11 +1860,26 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC, return false; } + QualType ElemType; + if (SrcPtr.getFieldDesc()->isArray()) + ElemType = SrcPtr.getFieldDesc()->getElemQualType(); + else + ElemType = SrcPtr.getType(); + + unsigned ElemSize = + S.getASTContext().getTypeSizeInChars(ElemType).getQuantity(); + if (Size.urem(ElemSize) != 0) { + S.FFDiag(S.Current->getSource(OpPC), + diag::note_constexpr_memcpy_unsupported) + << Move << /*IsWchar=*/false << 0 << ElemType << Size << ElemSize; + return false; + } + // As a last resort, reject dummy pointers. if (DestPtr.isDummy() || SrcPtr.isDummy()) return false; - if (!DoBitCastPtr(S, OpPC, SrcPtr, DestPtr)) + if (!DoBitCastPtr(S, OpPC, SrcPtr, DestPtr, Size.getZExtValue())) return false; S.Stk.push(DestPtr); @@ -1854,11 +1902,15 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, break; case Builtin::BI__builtin_strcmp: case Builtin::BIstrcmp: + case Builtin::BI__builtin_strncmp: + case Builtin::BIstrncmp: if (!interp__builtin_strcmp(S, OpPC, Frame, F, Call)) return false; break; case Builtin::BI__builtin_strlen: case Builtin::BIstrlen: + case Builtin::BI__builtin_wcslen: + case Builtin::BIwcslen: if (!interp__builtin_strlen(S, OpPC, Frame, F, Call)) return false; break; diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp index b1230f92ddf1d..c9cd113287557 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// #include "InterpBuiltinBitCast.h" +#include "BitcastBuffer.h" #include "Boolean.h" #include "Context.h" #include "Floating.h" @@ -21,9 +22,19 @@ using namespace clang; using namespace clang::interp; +/// Implement __builtin_bit_cast and related operations. +/// Since our internal representation for data is more complex than +/// something we can simply memcpy or memcmp, we first bitcast all the data +/// into a buffer, which we then later use to copy the data into the target. + +// TODO: +// - Try to minimize heap allocations. +// - Optimize the common case of only pushing and pulling full +// bytes to/from the buffer. + /// Used to iterate over pointer fields. using DataFunc = llvm::function_ref; + Bits BitOffset, bool PackedBools)>; #define BITCAST_TYPE_SWITCH(Expr, B) \ do { \ @@ -61,156 +72,78 @@ using DataFunc = llvm::function_ref Data; - - BitcastBuffer() = default; - - size_t size() const { return SizeInBits; } - - const std::byte *data() const { return Data.data(); } - - std::byte *getBytes(unsigned BitOffset) const { - assert(BitOffset % 8 == 0); - assert(BitOffset < SizeInBits); - return const_cast(data() + (BitOffset / 8)); - } - - bool allInitialized() const { - // FIXME: Implement. - return true; - } - - bool atByteBoundary() const { return (Data.size() * 8) == SizeInBits; } - - void pushBit(bool Value) { - if (atByteBoundary()) - Data.push_back(std::byte{0}); - - if (Value) - Data.back() |= (std::byte{1} << (SizeInBits % 8)); - ++SizeInBits; - } - - void pushData(const std::byte *data, size_t BitWidth, bool BigEndianTarget) { - bool OnlyFullBytes = BitWidth % 8 == 0; - unsigned NBytes = BitWidth / 8; - - size_t BitsHandled = 0; - // Read all full bytes first - for (size_t I = 0; I != NBytes; ++I) { - std::byte B = - BigEndianTarget ? data[NBytes - OnlyFullBytes - I] : data[I]; - for (unsigned X = 0; X != 8; ++X) { - pushBit(bitof(B, X)); - ++BitsHandled; - } - } - - if (BitsHandled == BitWidth) - return; - - // Rest of the bits. - assert((BitWidth - BitsHandled) < 8); - std::byte B = BigEndianTarget ? data[0] : data[NBytes]; - for (size_t I = 0, E = (BitWidth - BitsHandled); I != E; ++I) { - pushBit(bitof(B, I)); - ++BitsHandled; - } - - assert(BitsHandled == BitWidth); - } -}; - -/// We use this to recursively iterate over all fields and elemends of a pointer +/// We use this to recursively iterate over all fields and elements of a pointer /// and extract relevant data for a bitcast. -static bool enumerateData(const Pointer &P, const Context &Ctx, size_t Offset, - DataFunc F) { +static bool enumerateData(const Pointer &P, const Context &Ctx, Bits Offset, + Bits BitsToRead, DataFunc F) { const Descriptor *FieldDesc = P.getFieldDesc(); assert(FieldDesc); // Primitives. if (FieldDesc->isPrimitive()) - return F(P, FieldDesc->getPrimType(), Offset, false); + return F(P, FieldDesc->getPrimType(), Offset, /*PackedBools=*/false); // Primitive arrays. if (FieldDesc->isPrimitiveArray()) { - bool BigEndianTarget = Ctx.getASTContext().getTargetInfo().isBigEndian(); QualType ElemType = FieldDesc->getElemQualType(); size_t ElemSizeInBits = Ctx.getASTContext().getTypeSize(ElemType); PrimType ElemT = *Ctx.classify(ElemType); // Special case, since the bools here are packed. bool PackedBools = FieldDesc->getType()->isExtVectorBoolType(); + unsigned NumElems = FieldDesc->getNumElems(); bool Ok = true; - for (unsigned I = 0; I != FieldDesc->getNumElems(); ++I) { - unsigned Index = BigEndianTarget ? (FieldDesc->getNumElems() - 1 - I) : I; - Ok = Ok && F(P.atIndex(Index), ElemT, Offset, PackedBools); - Offset += ElemSizeInBits; + for (unsigned I = P.getIndex(); I != NumElems; ++I) { + Ok = Ok && F(P.atIndex(I), ElemT, Offset, PackedBools); + Offset += PackedBools ? 1 : ElemSizeInBits; + if (Offset >= BitsToRead) + break; } return Ok; } // Composite arrays. if (FieldDesc->isCompositeArray()) { - bool BigEndianTarget = Ctx.getASTContext().getTargetInfo().isBigEndian(); QualType ElemType = FieldDesc->getElemQualType(); size_t ElemSizeInBits = Ctx.getASTContext().getTypeSize(ElemType); for (unsigned I = 0; I != FieldDesc->getNumElems(); ++I) { - unsigned Index = BigEndianTarget ? (FieldDesc->getNumElems() - 1 - I) : I; - enumerateData(P.atIndex(Index).narrow(), Ctx, Offset, F); + enumerateData(P.atIndex(I).narrow(), Ctx, Offset, BitsToRead, F); Offset += ElemSizeInBits; + if (Offset >= BitsToRead) + break; } return true; } // Records. if (FieldDesc->isRecord()) { - bool BigEndianTarget = Ctx.getASTContext().getTargetInfo().isBigEndian(); const Record *R = FieldDesc->ElemRecord; const ASTRecordLayout &Layout = Ctx.getASTContext().getASTRecordLayout(R->getDecl()); bool Ok = true; - auto enumerateFields = [&]() -> void { - for (unsigned I = 0, N = R->getNumFields(); I != N; ++I) { - const Record::Field *Fi = - R->getField(BigEndianTarget ? (N - 1 - I) : I); - Pointer Elem = P.atField(Fi->Offset); - size_t BitOffset = - Offset + Layout.getFieldOffset(Fi->Decl->getFieldIndex()); - Ok = Ok && enumerateData(Elem, Ctx, BitOffset, F); - } - }; - auto enumerateBases = [&]() -> void { - for (unsigned I = 0, N = R->getNumBases(); I != N; ++I) { - const Record::Base *B = R->getBase(BigEndianTarget ? (N - 1 - I) : I); - Pointer Elem = P.atField(B->Offset); - CharUnits ByteOffset = - Layout.getBaseClassOffset(cast(B->Decl)); - size_t BitOffset = Offset + Ctx.getASTContext().toBits(ByteOffset); - Ok = Ok && enumerateData(Elem, Ctx, BitOffset, F); - } - }; - - if (BigEndianTarget) { - enumerateFields(); - enumerateBases(); - } else { - enumerateBases(); - enumerateFields(); + for (const Record::Field &Fi : R->fields()) { + if (Fi.isUnnamedBitField()) + continue; + Pointer Elem = P.atField(Fi.Offset); + Bits BitOffset = + Offset + Bits(Layout.getFieldOffset(Fi.Decl->getFieldIndex())); + Ok = Ok && enumerateData(Elem, Ctx, BitOffset, BitsToRead, F); + } + for (const Record::Base &B : R->bases()) { + Pointer Elem = P.atField(B.Offset); + CharUnits ByteOffset = + Layout.getBaseClassOffset(cast(B.Decl)); + Bits BitOffset = Offset + Bits(Ctx.getASTContext().toBits(ByteOffset)); + Ok = Ok && enumerateData(Elem, Ctx, BitOffset, BitsToRead, F); + // FIXME: We should only (need to) do this when bitcasting OUT of the + // buffer, not when copying data into it. + if (Ok) + Elem.initialize(); } return Ok; @@ -220,8 +153,8 @@ static bool enumerateData(const Pointer &P, const Context &Ctx, size_t Offset, } static bool enumeratePointerFields(const Pointer &P, const Context &Ctx, - DataFunc F) { - return enumerateData(P, Ctx, 0, F); + Bits BitsToRead, DataFunc F) { + return enumerateData(P, Ctx, Bits::zero(), BitsToRead, F); } // This function is constexpr if and only if To, From, and the types of @@ -295,92 +228,113 @@ static bool CheckBitcastType(InterpState &S, CodePtr OpPC, QualType T, static bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr, BitcastBuffer &Buffer, bool ReturnOnUninit) { const ASTContext &ASTCtx = Ctx.getASTContext(); - bool SwapData = (ASTCtx.getTargetInfo().isLittleEndian() != - llvm::sys::IsLittleEndianHost); - bool BigEndianTarget = ASTCtx.getTargetInfo().isBigEndian(); + Endian TargetEndianness = + ASTCtx.getTargetInfo().isLittleEndian() ? Endian::Little : Endian::Big; return enumeratePointerFields( - FromPtr, Ctx, - [&](const Pointer &P, PrimType T, size_t BitOffset, + FromPtr, Ctx, Buffer.size(), + [&](const Pointer &P, PrimType T, Bits BitOffset, bool PackedBools) -> bool { - if (!P.isInitialized()) { - assert(false && "Implement uninitialized value tracking"); - return ReturnOnUninit; + CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(P.getType()); + Bits BitWidth = Bits(ASTCtx.toBits(ObjectReprChars)); + Bits FullBitWidth = BitWidth; + + if (const FieldDecl *FD = P.getField(); FD && FD->isBitField()) { + BitWidth = Bits(std::min(FD->getBitWidthValue(ASTCtx), + (unsigned)FullBitWidth.getQuantity())); + } else if (T == PT_Bool && PackedBools) + BitWidth = Bits(1); + + if (BitWidth.isZero()) + return true; + + // Bits will be left uninitialized and diagnosed when reading. + if (!P.isInitialized()) + return true; + + if (T == PT_Ptr) { + assert(P.getType()->isNullPtrType()); + // Clang treats nullptr_t has having NO bits in its value + // representation. So, we accept it here and leave its bits + // uninitialized. + return true; } assert(P.isInitialized()); - // nullptr_t is a PT_Ptr for us, but it's still not std::is_pointer_v. - if (T == PT_Ptr) - assert(false && "Implement casting to pointer types"); - - CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(P.getType()); - unsigned BitWidth = ASTCtx.toBits(ObjectReprChars); - llvm::SmallVector Buff(ObjectReprChars.getQuantity()); + auto Buff = + std::make_unique(ObjectReprChars.getQuantity()); // Work around floating point types that contain unused padding bytes. // This is really just `long double` on x86, which is the only // fundamental type with padding bytes. if (T == PT_Float) { const Floating &F = P.deref(); - unsigned NumBits = - llvm::APFloatBase::getSizeInBits(F.getAPFloat().getSemantics()); - assert(NumBits % 8 == 0); - assert(NumBits <= (ObjectReprChars.getQuantity() * 8)); - F.bitcastToMemory(Buff.data()); + Bits NumBits = Bits( + llvm::APFloatBase::getSizeInBits(F.getAPFloat().getSemantics())); + assert(NumBits.isFullByte()); + assert(NumBits.getQuantity() <= FullBitWidth.getQuantity()); + F.bitcastToMemory(Buff.get()); // Now, only (maybe) swap the actual size of the float, excluding the // padding bits. - if (SwapData) - swapBytes(Buff.data(), NumBits / 8); + if (llvm::sys::IsBigEndianHost) + swapBytes(Buff.get(), NumBits.roundToBytes()); + Buffer.markInitialized(BitOffset, NumBits); } else { - if (const FieldDecl *FD = P.getField(); FD && FD->isBitField()) - BitWidth = FD->getBitWidthValue(ASTCtx); - else if (T == PT_Bool && PackedBools) - BitWidth = 1; - - BITCAST_TYPE_SWITCH(T, { - T Val = P.deref(); - Val.bitcastToMemory(Buff.data()); - }); - if (SwapData) - swapBytes(Buff.data(), ObjectReprChars.getQuantity()); - } + BITCAST_TYPE_SWITCH(T, { P.deref().bitcastToMemory(Buff.get()); }); - if (BitWidth != (Buff.size() * 8) && BigEndianTarget) { - Buffer.pushData(Buff.data() + (Buff.size() - 1 - (BitWidth / 8)), - BitWidth, BigEndianTarget); - } else { - Buffer.pushData(Buff.data(), BitWidth, BigEndianTarget); + if (llvm::sys::IsBigEndianHost) + swapBytes(Buff.get(), FullBitWidth.roundToBytes()); + Buffer.markInitialized(BitOffset, BitWidth); } + + Buffer.pushData(Buff.get(), BitOffset, BitWidth, TargetEndianness); return true; }); } bool clang::interp::DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, - std::byte *Buff, size_t BuffSize, + std::byte *Buff, Bits BitWidth, Bits FullBitWidth, bool &HasIndeterminateBits) { assert(Ptr.isLive()); assert(Ptr.isBlockPointer()); assert(Buff); + assert(BitWidth <= FullBitWidth); + assert(FullBitWidth.isFullByte()); + assert(BitWidth.isFullByte()); - BitcastBuffer Buffer; + BitcastBuffer Buffer(FullBitWidth); + size_t BuffSize = FullBitWidth.roundToBytes(); if (!CheckBitcastType(S, OpPC, Ptr.getType(), /*IsToType=*/false)) return false; bool Success = readPointerToBuffer(S.getContext(), Ptr, Buffer, /*ReturnOnUninit=*/false); - assert(Buffer.size() == BuffSize * 8); + HasIndeterminateBits = !Buffer.rangeInitialized(Bits::zero(), BitWidth); + + const ASTContext &ASTCtx = S.getASTContext(); + Endian TargetEndianness = + ASTCtx.getTargetInfo().isLittleEndian() ? Endian::Little : Endian::Big; + auto B = + Buffer.copyBits(Bits::zero(), BitWidth, FullBitWidth, TargetEndianness); - HasIndeterminateBits = !Buffer.allInitialized(); - std::memcpy(Buff, Buffer.data(), BuffSize); + std::memcpy(Buff, B.get(), BuffSize); if (llvm::sys::IsBigEndianHost) - swapBytes(Buff, BuffSize); + swapBytes(Buff, BitWidth.roundToBytes()); return Success; } - bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC, const Pointer &FromPtr, Pointer &ToPtr) { + const ASTContext &ASTCtx = S.getASTContext(); + CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(ToPtr.getType()); + + return DoBitCastPtr(S, OpPC, FromPtr, ToPtr, ObjectReprChars.getQuantity()); +} + +bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC, + const Pointer &FromPtr, Pointer &ToPtr, + size_t Size) { assert(FromPtr.isLive()); assert(FromPtr.isBlockPointer()); assert(ToPtr.isBlockPointer()); @@ -393,43 +347,76 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC, if (!CheckBitcastType(S, OpPC, FromType, /*IsToType=*/false)) return false; - BitcastBuffer Buffer; + const ASTContext &ASTCtx = S.getASTContext(); + BitcastBuffer Buffer(Bytes(Size).toBits()); readPointerToBuffer(S.getContext(), FromPtr, Buffer, /*ReturnOnUninit=*/false); // Now read the values out of the buffer again and into ToPtr. - const ASTContext &ASTCtx = S.getASTContext(); - size_t BitOffset = 0; + Endian TargetEndianness = + ASTCtx.getTargetInfo().isLittleEndian() ? Endian::Little : Endian::Big; bool Success = enumeratePointerFields( - ToPtr, S.getContext(), - [&](const Pointer &P, PrimType T, size_t _, bool PackedBools) -> bool { + ToPtr, S.getContext(), Buffer.size(), + [&](const Pointer &P, PrimType T, Bits BitOffset, + bool PackedBools) -> bool { + QualType PtrType = P.getType(); + CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(PtrType); + Bits FullBitWidth = Bits(ASTCtx.toBits(ObjectReprChars)); if (T == PT_Float) { - CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(P.getType()); - const auto &Semantics = ASTCtx.getFloatTypeSemantics(P.getType()); - unsigned NumBits = llvm::APFloatBase::getSizeInBits(Semantics); - assert(NumBits % 8 == 0); - assert(NumBits <= ASTCtx.toBits(ObjectReprChars)); - std::byte *M = Buffer.getBytes(BitOffset); + const auto &Semantics = ASTCtx.getFloatTypeSemantics(PtrType); + Bits NumBits = Bits(llvm::APFloatBase::getSizeInBits(Semantics)); + assert(NumBits.isFullByte()); + assert(NumBits.getQuantity() <= FullBitWidth.getQuantity()); + auto M = Buffer.copyBits(BitOffset, NumBits, FullBitWidth, + TargetEndianness); if (llvm::sys::IsBigEndianHost) - swapBytes(M, NumBits / 8); + swapBytes(M.get(), NumBits.roundToBytes()); - P.deref() = Floating::bitcastFromMemory(M, Semantics); + P.deref() = Floating::bitcastFromMemory(M.get(), Semantics); P.initialize(); - BitOffset += ASTCtx.toBits(ObjectReprChars); return true; } - BITCAST_TYPE_SWITCH_FIXED_SIZE(T, { - std::byte *M = Buffer.getBytes(BitOffset); + Bits BitWidth; + if (const FieldDecl *FD = P.getField(); FD && FD->isBitField()) + BitWidth = Bits(std::min(FD->getBitWidthValue(ASTCtx), + (unsigned)FullBitWidth.getQuantity())); + else if (T == PT_Bool && PackedBools) + BitWidth = Bits(1); + else + BitWidth = FullBitWidth; + + // If any of the bits are uninitialized, we need to abort unless the + // target type is std::byte or unsigned char. + bool Initialized = Buffer.rangeInitialized(BitOffset, BitWidth); + if (!Initialized) { + if (!PtrType->isStdByteType() && + !PtrType->isSpecificBuiltinType(BuiltinType::UChar) && + !PtrType->isSpecificBuiltinType(BuiltinType::Char_U)) { + const Expr *E = S.Current->getExpr(OpPC); + S.FFDiag(E, diag::note_constexpr_bit_cast_indet_dest) + << PtrType << S.getLangOpts().CharIsSigned + << E->getSourceRange(); + + return false; + } + return true; + } - if (llvm::sys::IsBigEndianHost) - swapBytes(M, T::bitWidth() / 8); + auto Memory = Buffer.copyBits(BitOffset, BitWidth, FullBitWidth, + TargetEndianness); + if (llvm::sys::IsBigEndianHost) + swapBytes(Memory.get(), FullBitWidth.roundToBytes()); - P.deref() = T::bitcastFromMemory(M, T::bitWidth()); - P.initialize(); - BitOffset += T::bitWidth(); + BITCAST_TYPE_SWITCH_FIXED_SIZE(T, { + if (BitWidth.nonZero()) + P.deref() = T::bitcastFromMemory(Memory.get(), T::bitWidth()) + .truncate(BitWidth.getQuantity()); + else + P.deref() = T::zero(); }); + P.initialize(); return true; }); diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h index 494c0880a9c45..92e6ffc79fc4f 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h +++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_AST_INTERP_BUILITN_BIT_CAST_H #define LLVM_CLANG_AST_INTERP_BUILITN_BIT_CAST_H +#include "BitcastBuffer.h" #include namespace clang { @@ -18,9 +19,12 @@ class InterpState; class CodePtr; bool DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, - std::byte *Buff, size_t BuffSize, bool &HasIndeterminateBits); + std::byte *Buff, Bits BitWidth, Bits FullBitWidth, + bool &HasIndeterminateBits); bool DoBitCastPtr(InterpState &S, CodePtr OpPC, const Pointer &FromPtr, Pointer &ToPtr); +bool DoBitCastPtr(InterpState &S, CodePtr OpPC, const Pointer &FromPtr, + Pointer &ToPtr, size_t Size); } // namespace interp } // namespace clang diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index 26d5f70b44396..0638f8249805f 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -281,7 +281,7 @@ def ZeroIntAPS : Opcode { // [] -> [Pointer] def Null : Opcode { let Types = [PtrTypeClass]; - let Args = [ArgDesc]; + let Args = [ArgUint64, ArgDesc]; let HasGroup = 1; } diff --git a/clang/lib/AST/ByteCode/Record.h b/clang/lib/AST/ByteCode/Record.h index 7a5c482e4efcc..686b5dbc431d9 100644 --- a/clang/lib/AST/ByteCode/Record.h +++ b/clang/lib/AST/ByteCode/Record.h @@ -30,6 +30,7 @@ class Record final { unsigned Offset; const Descriptor *Desc; bool isBitField() const { return Decl->isBitField(); } + bool isUnnamedBitField() const { return Decl->isUnnamedBitField(); } }; /// Describes a base class. diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 52c6a45de9a26..cb13c5225b713 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -65,6 +65,7 @@ add_clang_library(clangAST ExternalASTSource.cpp FormatString.cpp InheritViz.cpp + ByteCode/BitcastBuffer.cpp ByteCode/ByteCodeEmitter.cpp ByteCode/Compiler.cpp ByteCode/Context.cpp diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp index 10b8d524ff897..ee5775837d535 100644 --- a/clang/lib/AST/CXXInheritance.cpp +++ b/clang/lib/AST/CXXInheritance.cpp @@ -368,8 +368,8 @@ bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier, const CXXRecordDecl *BaseRecord) { assert(BaseRecord->getCanonicalDecl() == BaseRecord && "User data for FindBaseClass is not canonical!"); - return Specifier->getType()->castAs()->getDecl() - ->getCanonicalDecl() == BaseRecord; + return cast(Specifier->getType()->getAsRecordDecl()) + ->getCanonicalDecl() == BaseRecord; } bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, @@ -378,8 +378,8 @@ bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, assert(BaseRecord->getCanonicalDecl() == BaseRecord && "User data for FindBaseClass is not canonical!"); return Specifier->isVirtual() && - Specifier->getType()->castAs()->getDecl() - ->getCanonicalDecl() == BaseRecord; + cast(Specifier->getType()->getAsRecordDecl()) + ->getCanonicalDecl() == BaseRecord; } static bool isOrdinaryMember(const NamedDecl *ND) { @@ -692,7 +692,7 @@ AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, "Cannot get indirect primary bases for class with dependent bases."); const CXXRecordDecl *BaseDecl = - cast(I.getType()->castAs()->getDecl()); + cast(I.getType()->getAsRecordDecl()); // Only bases with virtual bases participate in computing the // indirect primary virtual base classes. @@ -714,7 +714,7 @@ CXXRecordDecl::getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const { "Cannot get indirect primary bases for class with dependent bases."); const CXXRecordDecl *BaseDecl = - cast(I.getType()->castAs()->getDecl()); + cast(I.getType()->getAsRecordDecl()); // Only bases with virtual bases participate in computing the // indirect primary virtual base classes. diff --git a/clang/lib/AST/CommentLexer.cpp b/clang/lib/AST/CommentLexer.cpp index f0250fc9fd55e..ec9a5b480aa29 100644 --- a/clang/lib/AST/CommentLexer.cpp +++ b/clang/lib/AST/CommentLexer.cpp @@ -8,8 +8,8 @@ #include "clang/AST/CommentLexer.h" #include "clang/AST/CommentCommandTraits.h" -#include "clang/AST/CommentDiagnostic.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/DiagnosticComment.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ConvertUTF.h" diff --git a/clang/lib/AST/CommentParser.cpp b/clang/lib/AST/CommentParser.cpp index 61508fe886efc..12ed8e3f1b79a 100644 --- a/clang/lib/AST/CommentParser.cpp +++ b/clang/lib/AST/CommentParser.cpp @@ -8,9 +8,9 @@ #include "clang/AST/CommentParser.h" #include "clang/AST/CommentCommandTraits.h" -#include "clang/AST/CommentDiagnostic.h" #include "clang/AST/CommentSema.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/DiagnosticComment.h" #include "clang/Basic/SourceManager.h" #include "llvm/Support/ErrorHandling.h" diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp index 69eda00643a8f..bd2206bb8a3bc 100644 --- a/clang/lib/AST/CommentSema.cpp +++ b/clang/lib/AST/CommentSema.cpp @@ -9,9 +9,9 @@ #include "clang/AST/CommentSema.h" #include "clang/AST/Attr.h" #include "clang/AST/CommentCommandTraits.h" -#include "clang/AST/CommentDiagnostic.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" +#include "clang/Basic/DiagnosticComment.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Preprocessor.h" diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index a4fb4d5a1f2ec..5a6738196d289 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1639,11 +1639,19 @@ SourceLocation CallExpr::getBeginLoc() const { if (const auto *OCE = dyn_cast(this)) return OCE->getBeginLoc(); + if (const auto *Method = + dyn_cast_if_present(getCalleeDecl()); + Method && Method->isExplicitObjectMemberFunction()) { + assert(getNumArgs() > 0 && getArg(0)); + return getArg(0)->getBeginLoc(); + } + SourceLocation begin = getCallee()->getBeginLoc(); if (begin.isInvalid() && getNumArgs() > 0 && getArg(0)) begin = getArg(0)->getBeginLoc(); return begin; } + SourceLocation CallExpr::getEndLoc() const { if (const auto *OCE = dyn_cast(this)) return OCE->getEndLoc(); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 6b5b95aee3552..eed277deb4ac1 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -10172,7 +10172,9 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { return false; IsNothrow = true; } else if (OperatorNew->isReservedGlobalPlacementOperator()) { - if (Info.CurrentCall->isStdFunction() || Info.getLangOpts().CPlusPlus26) { + if (Info.CurrentCall->isStdFunction() || Info.getLangOpts().CPlusPlus26 || + (Info.CurrentCall->CanEvalMSConstexpr && + OperatorNew->hasAttr())) { if (!EvaluatePointer(E->getPlacementArg(0), Result, Info)) return false; if (Result.Designator.Invalid) @@ -11339,6 +11341,37 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { return Success(APValue(ResultElements.data(), ResultElements.size()), E); } + case Builtin::BI__builtin_elementwise_add_sat: + case Builtin::BI__builtin_elementwise_sub_sat: { + APValue SourceLHS, SourceRHS; + if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) || + !EvaluateAsRValue(Info, E->getArg(1), SourceRHS)) + return false; + + QualType DestEltTy = E->getType()->castAs()->getElementType(); + unsigned SourceLen = SourceLHS.getVectorLength(); + SmallVector ResultElements; + ResultElements.reserve(SourceLen); + + for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) { + APSInt LHS = SourceLHS.getVectorElt(EltNum).getInt(); + APSInt RHS = SourceRHS.getVectorElt(EltNum).getInt(); + switch (E->getBuiltinCallee()) { + case Builtin::BI__builtin_elementwise_add_sat: + ResultElements.push_back(APValue( + APSInt(LHS.isSigned() ? LHS.sadd_sat(RHS) : RHS.uadd_sat(RHS), + DestEltTy->isUnsignedIntegerOrEnumerationType()))); + break; + case Builtin::BI__builtin_elementwise_sub_sat: + ResultElements.push_back(APValue( + APSInt(LHS.isSigned() ? LHS.ssub_sat(RHS) : RHS.usub_sat(RHS), + DestEltTy->isUnsignedIntegerOrEnumerationType()))); + break; + } + } + + return Success(APValue(ResultElements.data(), ResultElements.size()), E); + } } } @@ -13204,6 +13237,25 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return Success(Val.rotr(Amt.urem(Val.getBitWidth())), E); } + case Builtin::BI__builtin_elementwise_add_sat: { + APSInt LHS, RHS; + if (!EvaluateInteger(E->getArg(0), LHS, Info) || + !EvaluateInteger(E->getArg(1), RHS, Info)) + return false; + + APInt Result = LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS); + return Success(APSInt(Result, !LHS.isSigned()), E); + } + case Builtin::BI__builtin_elementwise_sub_sat: { + APSInt LHS, RHS; + if (!EvaluateInteger(E->getArg(0), LHS, Info) || + !EvaluateInteger(E->getArg(1), RHS, Info)) + return false; + + APInt Result = LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS); + return Success(APSInt(Result, !LHS.isSigned()), E); + } + case Builtin::BIstrlen: case Builtin::BIwcslen: // A call to strlen is not a constant expression. diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 7642ff7ca606c..edeeaeaa9ae17 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1014,6 +1014,7 @@ void MicrosoftCXXNameMangler::mangleFloat(llvm::APFloat Number) { case APFloat::S_x87DoubleExtended: Out << 'X'; break; case APFloat::S_IEEEquad: Out << 'Y'; break; case APFloat::S_PPCDoubleDouble: Out << 'Z'; break; + case APFloat::S_PPCDoubleDoubleLegacy: case APFloat::S_Float8E5M2: case APFloat::S_Float8E4M3: case APFloat::S_Float8E4M3FN: diff --git a/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/clang/lib/Analysis/ExprMutationAnalyzer.cpp index be0e8aa5743dd..53b838e9ede4d 100644 --- a/clang/lib/Analysis/ExprMutationAnalyzer.cpp +++ b/clang/lib/Analysis/ExprMutationAnalyzer.cpp @@ -55,25 +55,13 @@ static bool canExprResolveTo(const Expr *Source, const Expr *Target) { // This is matched by `IgnoreDerivedToBase(canResolveToExpr(InnerMatcher))` // below. const auto ConditionalOperatorM = [Target](const Expr *E) { - if (const auto *OP = dyn_cast(E)) { - if (const auto *TE = OP->getTrueExpr()->IgnoreParens()) - if (canExprResolveTo(TE, Target)) - return true; - if (const auto *FE = OP->getFalseExpr()->IgnoreParens()) - if (canExprResolveTo(FE, Target)) - return true; - } - return false; - }; - - const auto ElvisOperator = [Target](const Expr *E) { - if (const auto *OP = dyn_cast(E)) { - if (const auto *TE = OP->getTrueExpr()->IgnoreParens()) - if (canExprResolveTo(TE, Target)) - return true; - if (const auto *FE = OP->getFalseExpr()->IgnoreParens()) - if (canExprResolveTo(FE, Target)) - return true; + if (const auto *CO = dyn_cast(E)) { + const auto *TE = CO->getTrueExpr()->IgnoreParens(); + if (TE && canExprResolveTo(TE, Target)) + return true; + const auto *FE = CO->getFalseExpr()->IgnoreParens(); + if (FE && canExprResolveTo(FE, Target)) + return true; } return false; }; @@ -81,8 +69,7 @@ static bool canExprResolveTo(const Expr *Source, const Expr *Target) { const Expr *SourceExprP = Source->IgnoreParens(); return IgnoreDerivedToBase(SourceExprP, [&](const Expr *E) { - return E == Target || ConditionalOperatorM(E) || - ElvisOperator(E); + return E == Target || ConditionalOperatorM(E); }) || EvalCommaExpr(SourceExprP, [&](const Expr *E) { return IgnoreDerivedToBase( diff --git a/clang/lib/Basic/Builtins.cpp b/clang/lib/Basic/Builtins.cpp index 25a601573698e..c991139b8d5ad 100644 --- a/clang/lib/Basic/Builtins.cpp +++ b/clang/lib/Basic/Builtins.cpp @@ -29,54 +29,93 @@ const char *HeaderDesc::getName() const { llvm_unreachable("Unknown HeaderDesc::HeaderID enum"); } -static constexpr Builtin::Info BuiltinInfo[] = { - {"not a builtin function", nullptr, nullptr, nullptr, HeaderDesc::NO_HEADER, - ALL_LANGUAGES}, -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define LANGBUILTIN(ID, TYPE, ATTRS, LANGS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, LANGS}, -#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, LANGS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, LANGS}, +static constexpr auto BuiltinStorage = + Builtin::Storage::Make( + CLANG_BUILTIN_STR_TABLE("not a builtin function", "", "") +#define BUILTIN CLANG_BUILTIN_STR_TABLE #include "clang/Basic/Builtins.inc" -}; + , + {CLANG_BUILTIN_ENTRY("not a builtin function", "", "") +#define BUILTIN CLANG_BUILTIN_ENTRY +#define LANGBUILTIN CLANG_LANGBUILTIN_ENTRY +#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY +#include "clang/Basic/Builtins.inc" + }); -const Builtin::Info &Builtin::Context::getRecord(unsigned ID) const { +std::pair +Builtin::Context::getStrTableAndInfo(unsigned ID) const { if (ID < Builtin::FirstTSBuiltin) - return BuiltinInfo[ID]; - assert(((ID - Builtin::FirstTSBuiltin) < - (TSRecords.size() + AuxTSRecords.size())) && - "Invalid builtin ID!"); + return {BuiltinStorage.StringTable, BuiltinStorage.Infos[ID]}; + assert( + ((ID - Builtin::FirstTSBuiltin) < (TSInfos.size() + AuxTSInfos.size())) && + "Invalid builtin ID!"); if (isAuxBuiltinID(ID)) - return AuxTSRecords[getAuxBuiltinID(ID) - Builtin::FirstTSBuiltin]; - return TSRecords[ID - Builtin::FirstTSBuiltin]; + return {AuxTSStrTable, + AuxTSInfos[getAuxBuiltinID(ID) - Builtin::FirstTSBuiltin]}; + return {TSStrTable, TSInfos[ID - Builtin::FirstTSBuiltin]}; +} + +static llvm::StringRef getStrFromTable(const char *StrTable, int Offset) { + return &StrTable[Offset]; +} + +/// Return the identifier name for the specified builtin, +/// e.g. "__builtin_abs". +llvm::StringRef Builtin::Context::getName(unsigned ID) const { + const auto &[StrTable, I] = getStrTableAndInfo(ID); + return getStrFromTable(StrTable, I.Offsets.Name); +} + +const char *Builtin::Context::getTypeString(unsigned ID) const { + const auto &[StrTable, I] = getStrTableAndInfo(ID); + return getStrFromTable(StrTable, I.Offsets.Type).data(); +} + +const char *Builtin::Context::getAttributesString(unsigned ID) const { + const auto &[StrTable, I] = getStrTableAndInfo(ID); + return getStrFromTable(StrTable, I.Offsets.Attributes).data(); +} + +const char *Builtin::Context::getRequiredFeatures(unsigned ID) const { + const auto &[StrTable, I] = getStrTableAndInfo(ID); + return getStrFromTable(StrTable, I.Offsets.Features).data(); } void Builtin::Context::InitializeTarget(const TargetInfo &Target, const TargetInfo *AuxTarget) { - assert(TSRecords.empty() && "Already initialized target?"); - TSRecords = Target.getTargetBuiltins(); - if (AuxTarget) - AuxTSRecords = AuxTarget->getTargetBuiltins(); + assert(TSStrTable == nullptr && "Already initialized target?"); + assert(TSInfos.empty() && "Already initialized target?"); + std::tie(TSStrTable, TSInfos) = Target.getTargetBuiltinStorage(); + if (AuxTarget) { + std::tie(AuxTSStrTable, AuxTSInfos) = AuxTarget->getTargetBuiltinStorage(); + } } bool Builtin::Context::isBuiltinFunc(llvm::StringRef FuncName) { bool InStdNamespace = FuncName.consume_front("std-"); + const char *StrTable = BuiltinStorage.StringTable; for (unsigned i = Builtin::NotBuiltin + 1; i != Builtin::FirstTSBuiltin; ++i) { - if (FuncName == BuiltinInfo[i].Name && - (bool)strchr(BuiltinInfo[i].Attributes, 'z') == InStdNamespace) - return strchr(BuiltinInfo[i].Attributes, 'f') != nullptr; + const auto &I = BuiltinStorage.Infos[i]; + if (FuncName == getStrFromTable(StrTable, I.Offsets.Name) && + (bool)strchr(getStrFromTable(StrTable, I.Offsets.Attributes).data(), + 'z') == InStdNamespace) + return strchr(getStrFromTable(StrTable, I.Offsets.Attributes).data(), + 'f') != nullptr; } return false; } /// Is this builtin supported according to the given language options? -static bool builtinIsSupported(const Builtin::Info &BuiltinInfo, +static bool builtinIsSupported(const char *StrTable, + const Builtin::Info &BuiltinInfo, const LangOptions &LangOpts) { + auto AttributesStr = + getStrFromTable(StrTable, BuiltinInfo.Offsets.Attributes); + /* Builtins Unsupported */ - if (LangOpts.NoBuiltin && strchr(BuiltinInfo.Attributes, 'f') != nullptr) + if (LangOpts.NoBuiltin && strchr(AttributesStr.data(), 'f') != nullptr) return false; /* CorBuiltins Unsupported */ if (!LangOpts.Coroutines && (BuiltinInfo.Langs & COR_LANG)) @@ -123,7 +162,7 @@ static bool builtinIsSupported(const Builtin::Info &BuiltinInfo, if (!LangOpts.CPlusPlus && BuiltinInfo.Langs == CXX_LANG) return false; /* consteval Unsupported */ - if (!LangOpts.CPlusPlus20 && strchr(BuiltinInfo.Attributes, 'G') != nullptr) + if (!LangOpts.CPlusPlus20 && strchr(AttributesStr.data(), 'G') != nullptr) return false; return true; } @@ -134,20 +173,23 @@ static bool builtinIsSupported(const Builtin::Info &BuiltinInfo, void Builtin::Context::initializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts) { // Step #1: mark all target-independent builtins with their ID's. - for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i) - if (builtinIsSupported(BuiltinInfo[i], LangOpts)) { - Table.get(BuiltinInfo[i].Name).setBuiltinID(i); + for (const auto &&[Index, I] : + llvm::enumerate(llvm::ArrayRef(BuiltinStorage.Infos).drop_front())) + if (builtinIsSupported(BuiltinStorage.StringTable, I, LangOpts)) { + Table.get(getStrFromTable(BuiltinStorage.StringTable, I.Offsets.Name)) + .setBuiltinID(Index + 1); } // Step #2: Register target-specific builtins. - for (unsigned i = 0, e = TSRecords.size(); i != e; ++i) - if (builtinIsSupported(TSRecords[i], LangOpts)) - Table.get(TSRecords[i].Name).setBuiltinID(i + Builtin::FirstTSBuiltin); + for (const auto &&[Index, I] : llvm::enumerate(TSInfos)) + if (builtinIsSupported(TSStrTable, I, LangOpts)) + Table.get(getStrFromTable(TSStrTable, I.Offsets.Name)) + .setBuiltinID(Index + Builtin::FirstTSBuiltin); // Step #3: Register target-specific builtins for AuxTarget. - for (unsigned i = 0, e = AuxTSRecords.size(); i != e; ++i) - Table.get(AuxTSRecords[i].Name) - .setBuiltinID(i + Builtin::FirstTSBuiltin + TSRecords.size()); + for (const auto &&[Index, I] : llvm::enumerate(AuxTSInfos)) + Table.get(getStrFromTable(AuxTSStrTable, I.Offsets.Name)) + .setBuiltinID(Index + Builtin::FirstTSBuiltin + TSInfos.size()); // Step #4: Unregister any builtins specified by -fno-builtin-foo. for (llvm::StringRef Name : LangOpts.NoBuiltinFuncs) { @@ -164,7 +206,7 @@ void Builtin::Context::initializeBuiltins(IdentifierTable &Table, } unsigned Builtin::Context::getRequiredVectorWidth(unsigned ID) const { - const char *WidthPos = ::strchr(getRecord(ID).Attributes, 'V'); + const char *WidthPos = ::strchr(getAttributesString(ID), 'V'); if (!WidthPos) return 0; @@ -187,7 +229,7 @@ bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx, assert(::toupper(Fmt[0]) == Fmt[1] && "Format string is not in the form \"xX\""); - const char *Like = ::strpbrk(getRecord(ID).Attributes, Fmt); + const char *Like = ::strpbrk(getAttributesString(ID), Fmt); if (!Like) return false; @@ -214,7 +256,7 @@ bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx, bool Builtin::Context::performsCallback(unsigned ID, SmallVectorImpl &Encoding) const { - const char *CalleePos = ::strchr(getRecord(ID).Attributes, 'C'); + const char *CalleePos = ::strchr(getAttributesString(ID), 'C'); if (!CalleePos) return false; diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp index 2d0e358116362..ae71758bc81e0 100644 --- a/clang/lib/Basic/Diagnostic.cpp +++ b/clang/lib/Basic/Diagnostic.cpp @@ -500,7 +500,8 @@ class WarningsSpecialCaseList : public llvm::SpecialCaseList { // the last section take precedence in such cases. void processSections(DiagnosticsEngine &Diags); - bool isDiagSuppressed(diag::kind DiagId, StringRef FilePath) const; + bool isDiagSuppressed(diag::kind DiagId, SourceLocation DiagLoc, + const SourceManager &SM) const; private: // Find the longest glob pattern that matches FilePath amongst @@ -573,13 +574,14 @@ void DiagnosticsEngine::setDiagSuppressionMapping(llvm::MemoryBuffer &Input) { WarningSuppressionList->processSections(*this); DiagSuppressionMapping = [WarningSuppressionList(std::move(WarningSuppressionList))]( - diag::kind DiagId, StringRef Path) { - return WarningSuppressionList->isDiagSuppressed(DiagId, Path); + diag::kind DiagId, SourceLocation DiagLoc, const SourceManager &SM) { + return WarningSuppressionList->isDiagSuppressed(DiagId, DiagLoc, SM); }; } bool WarningsSpecialCaseList::isDiagSuppressed(diag::kind DiagId, - StringRef FilePath) const { + SourceLocation DiagLoc, + const SourceManager &SM) const { const Section *DiagSection = DiagToSection.lookup(DiagId); if (!DiagSection) return false; @@ -589,7 +591,13 @@ bool WarningsSpecialCaseList::isDiagSuppressed(diag::kind DiagId, return false; const llvm::StringMap &CategoriesToMatchers = SrcEntriesIt->getValue(); - return globsMatches(CategoriesToMatchers, FilePath); + // We also use presumed locations here to improve reproducibility for + // preprocessed inputs. + if (PresumedLoc PLoc = SM.getPresumedLoc(DiagLoc); PLoc.isValid()) + return globsMatches( + CategoriesToMatchers, + llvm::sys::path::remove_leading_dotslash(PLoc.getFilename())); + return false; } bool WarningsSpecialCaseList::globsMatches( @@ -614,8 +622,10 @@ bool WarningsSpecialCaseList::globsMatches( } bool DiagnosticsEngine::isSuppressedViaMapping(diag::kind DiagId, - StringRef FilePath) const { - return DiagSuppressionMapping && DiagSuppressionMapping(DiagId, FilePath); + SourceLocation DiagLoc) const { + if (!hasSourceManager() || !DiagSuppressionMapping) + return false; + return DiagSuppressionMapping(DiagId, DiagLoc, getSourceManager()); } void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) { diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp index 44922aa7872db..d77f28c80b2eb 100644 --- a/clang/lib/Basic/DiagnosticIDs.cpp +++ b/clang/lib/Basic/DiagnosticIDs.cpp @@ -601,15 +601,8 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, return diag::Severity::Ignored; // Clang-diagnostics pragmas always take precedence over suppression mapping. - if (!Mapping.isPragma() && Diag.DiagSuppressionMapping) { - // We also use presumed locations here to improve reproducibility for - // preprocessed inputs. - if (PresumedLoc PLoc = SM.getPresumedLoc(Loc); - PLoc.isValid() && Diag.isSuppressedViaMapping( - DiagID, llvm::sys::path::remove_leading_dotslash( - PLoc.getFilename()))) - return diag::Severity::Ignored; - } + if (!Mapping.isPragma() && Diag.isSuppressedViaMapping(DiagID, Loc)) + return diag::Severity::Ignored; return Result; } diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 4efc1841c836d..858f83d090d7a 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -26,35 +26,39 @@ using namespace clang; using namespace clang::targets; -static constexpr Builtin::Info BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#include "clang/Basic/BuiltinsNEON.def" +static constexpr int NumBuiltins = + clang::AArch64::LastTSBuiltin - Builtin::FirstTSBuiltin; -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +static constexpr auto BuiltinStorage = Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE +#include "clang/Basic/BuiltinsNEON.def" +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsSVE.def" - -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsSME.def" - -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, LANG}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::HEADER, LANGS}, +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE +#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsAArch64.def" -}; + , { +#define BUILTIN CLANG_BUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +#include "clang/Basic/BuiltinsNEON.def" +#define BUILTIN CLANG_BUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +#include "clang/Basic/BuiltinsSVE.def" +#define BUILTIN CLANG_BUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +#include "clang/Basic/BuiltinsSME.def" +#define BUILTIN CLANG_BUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +#define LANGBUILTIN CLANG_LANGBUILTIN_ENTRY +#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_ENTRY +#include "clang/Basic/BuiltinsAArch64.def" + }); void AArch64TargetInfo::setArchFeatures() { if (*ArchInfo == llvm::AArch64::ARMV8R) { @@ -232,14 +236,23 @@ bool AArch64TargetInfo::validateTarget(DiagnosticsEngine &Diags) const { bool AArch64TargetInfo::validateGlobalRegisterVariable( StringRef RegName, unsigned RegSize, bool &HasSizeMismatch) const { - if ((RegName == "sp") || RegName.starts_with("x")) { + if (RegName == "sp") { HasSizeMismatch = RegSize != 64; return true; - } else if (RegName.starts_with("w")) { - HasSizeMismatch = RegSize != 32; - return true; } - return false; + if (RegName.starts_with("w")) + HasSizeMismatch = RegSize != 32; + else if (RegName.starts_with("x")) + HasSizeMismatch = RegSize != 64; + else + return false; + StringRef RegNum = RegName.drop_front(); + // Check if the register is reserved. See also + // AArch64TargetLowering::getRegisterByName(). + return RegNum == "0" || + (RegNum == "18" && + llvm::AArch64::isX18ReservedByDefault(getTriple())) || + getTargetOpts().FeatureMap.lookup(("reserve-x" + RegNum).str()); } bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef, @@ -447,6 +460,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1"); Builder.defineMacro("__ARM_FP16_ARGS", "1"); + // Clang supports arm_neon_sve_bridge.h + Builder.defineMacro("__ARM_NEON_SVE_BRIDGE", "1"); + if (Opts.UnsafeFPMath) Builder.defineMacro("__ARM_FP_FAST", "1"); @@ -464,9 +480,6 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, if (FPU & SveMode) Builder.defineMacro("__ARM_FEATURE_SVE", "1"); - if ((FPU & NeonMode) && (FPU & SveMode)) - Builder.defineMacro("__ARM_NEON_SVE_BRIDGE", "1"); - if (HasSVE2) Builder.defineMacro("__ARM_FEATURE_SVE2", "1"); @@ -688,9 +701,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, } } -ArrayRef AArch64TargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin - - Builtin::FirstTSBuiltin); +std::pair> +AArch64TargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } std::optional> diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index 68a8b1ebad8cd..a3ce04e249e30 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -180,7 +180,8 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; std::optional> getVScaleRange(const LangOptions &LangOpts) const override; diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp index 99f8f2944e279..21281e7201b02 100644 --- a/clang/lib/Basic/Targets/AMDGPU.cpp +++ b/clang/lib/Basic/Targets/AMDGPU.cpp @@ -88,13 +88,18 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = { } // namespace targets } // namespace clang -static constexpr Builtin::Info BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +static constexpr int NumBuiltins = + clang::AMDGPU::LastTSBuiltin - Builtin::FirstTSBuiltin; + +static constexpr auto BuiltinStorage = Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsAMDGPU.def" -}; + , { +#define BUILTIN CLANG_BUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +#include "clang/Basic/BuiltinsAMDGPU.def" + }); const char *const AMDGPUTargetInfo::GCCRegNames[] = { "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", @@ -266,9 +271,9 @@ void AMDGPUTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) { !isAMDGCN(getTriple())); } -ArrayRef AMDGPUTargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfo, - clang::AMDGPU::LastTSBuiltin - Builtin::FirstTSBuiltin); +std::pair> +AMDGPUTargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } void AMDGPUTargetInfo::getTargetDefines(const LangOptions &Opts, diff --git a/clang/lib/Basic/Targets/AMDGPU.h b/clang/lib/Basic/Targets/AMDGPU.h index ea4189cdea47d..8068184a0d411 100644 --- a/clang/lib/Basic/Targets/AMDGPU.h +++ b/clang/lib/Basic/Targets/AMDGPU.h @@ -257,7 +257,8 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo { StringRef CPU, const std::vector &FeatureVec) const override; - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; bool useFP16ConversionIntrinsics() const override { return false; } diff --git a/clang/lib/Basic/Targets/ARC.h b/clang/lib/Basic/Targets/ARC.h index 7f3d0aa15ab81..d84daf2e527ca 100644 --- a/clang/lib/Basic/Targets/ARC.h +++ b/clang/lib/Basic/Targets/ARC.h @@ -40,7 +40,10 @@ class LLVM_LIBRARY_VISIBILITY ARCTargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - ArrayRef getTargetBuiltins() const override { return {}; } + std::pair> + getTargetBuiltinStorage() const override { + return {nullptr, {}}; + } BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::VoidPtrBuiltinVaList; diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp index 370444057b429..fb10bc8249e98 100644 --- a/clang/lib/Basic/Targets/ARM.cpp +++ b/clang/lib/Basic/Targets/ARM.cpp @@ -1071,31 +1071,34 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts, } } -static constexpr Builtin::Info BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +static constexpr int NumBuiltins = + clang::ARM::LastTSBuiltin - Builtin::FirstTSBuiltin; + +static constexpr auto BuiltinStorage = Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsNEON.def" -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, LANG}, -#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::HEADER, LANGS}, +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE +#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsARM.def" -}; + , { +#define BUILTIN CLANG_BUILTIN_ENTRY +#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +#include "clang/Basic/BuiltinsNEON.def" +#define BUILTIN CLANG_BUILTIN_ENTRY +#define LANGBUILTIN CLANG_LANGBUILTIN_ENTRY +#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_ENTRY +#include "clang/Basic/BuiltinsARM.def" + }); -ArrayRef ARMTargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfo, - clang::ARM::LastTSBuiltin - Builtin::FirstTSBuiltin); +std::pair> +ARMTargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } bool ARMTargetInfo::isCLZForZeroUndef() const { return false; } diff --git a/clang/lib/Basic/Targets/ARM.h b/clang/lib/Basic/Targets/ARM.h index 55ecb99d82d8f..71f44f7248f68 100644 --- a/clang/lib/Basic/Targets/ARM.h +++ b/clang/lib/Basic/Targets/ARM.h @@ -196,7 +196,8 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; bool isCLZForZeroUndef() const override; BuiltinVaListKind getBuiltinVaListKind() const override; diff --git a/clang/lib/Basic/Targets/AVR.h b/clang/lib/Basic/Targets/AVR.h index df1f8d171efba..f19dee3a88231 100644 --- a/clang/lib/Basic/Targets/AVR.h +++ b/clang/lib/Basic/Targets/AVR.h @@ -63,7 +63,10 @@ class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - ArrayRef getTargetBuiltins() const override { return {}; } + std::pair> + getTargetBuiltinStorage() const override { + return {nullptr, {}}; + } bool allowsLargerPreferedTypeAlignment() const override { return false; } diff --git a/clang/lib/Basic/Targets/BPF.cpp b/clang/lib/Basic/Targets/BPF.cpp index f4684765b7ffb..b62e792590185 100644 --- a/clang/lib/Basic/Targets/BPF.cpp +++ b/clang/lib/Basic/Targets/BPF.cpp @@ -19,11 +19,16 @@ using namespace clang; using namespace clang::targets; -static constexpr Builtin::Info BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +static constexpr int NumBuiltins = + clang::BPF::LastTSBuiltin - Builtin::FirstTSBuiltin; + +static constexpr auto BuiltinStorage = Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#include "clang/Basic/BuiltinsBPF.inc" + , { +#define BUILTIN CLANG_BUILTIN_ENTRY #include "clang/Basic/BuiltinsBPF.inc" -}; + }); void BPFTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { @@ -81,9 +86,9 @@ void BPFTargetInfo::fillValidCPUList(SmallVectorImpl &Values) const { Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames)); } -ArrayRef BPFTargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfo, - clang::BPF::LastTSBuiltin - Builtin::FirstTSBuiltin); +std::pair> +BPFTargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } bool BPFTargetInfo::handleTargetFeatures(std::vector &Features, diff --git a/clang/lib/Basic/Targets/BPF.h b/clang/lib/Basic/Targets/BPF.h index 27a4b5f314970..8f5c0e31aa87c 100644 --- a/clang/lib/Basic/Targets/BPF.h +++ b/clang/lib/Basic/Targets/BPF.h @@ -58,7 +58,8 @@ class LLVM_LIBRARY_VISIBILITY BPFTargetInfo : public TargetInfo { bool handleTargetFeatures(std::vector &Features, DiagnosticsEngine &Diags) override; - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; std::string_view getClobbers() const override { return ""; } diff --git a/clang/lib/Basic/Targets/CSKY.cpp b/clang/lib/Basic/Targets/CSKY.cpp index c8bf8b9234d24..e698508a2370c 100644 --- a/clang/lib/Basic/Targets/CSKY.cpp +++ b/clang/lib/Basic/Targets/CSKY.cpp @@ -139,10 +139,6 @@ bool CSKYTargetInfo::handleTargetFeatures(std::vector &Features, return true; } -ArrayRef CSKYTargetInfo::getTargetBuiltins() const { - return ArrayRef(); -} - ArrayRef CSKYTargetInfo::getGCCRegNames() const { static const char *const GCCRegNames[] = { // Integer registers diff --git a/clang/lib/Basic/Targets/CSKY.h b/clang/lib/Basic/Targets/CSKY.h index 94d4eeb9a1fff..59c83340b8c31 100644 --- a/clang/lib/Basic/Targets/CSKY.h +++ b/clang/lib/Basic/Targets/CSKY.h @@ -73,7 +73,10 @@ class LLVM_LIBRARY_VISIBILITY CSKYTargetInfo : public TargetInfo { unsigned getMinGlobalAlign(uint64_t, bool HasNonWeakDef) const override; - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override { + return {nullptr, {}}; + } BuiltinVaListKind getBuiltinVaListKind() const override { return VoidPtrBuiltinVaList; diff --git a/clang/lib/Basic/Targets/DirectX.h b/clang/lib/Basic/Targets/DirectX.h index ab22d1281a4df..3e6e84b0d9e6f 100644 --- a/clang/lib/Basic/Targets/DirectX.h +++ b/clang/lib/Basic/Targets/DirectX.h @@ -72,7 +72,10 @@ class LLVM_LIBRARY_VISIBILITY DirectXTargetInfo : public TargetInfo { return Feature == "directx"; } - ArrayRef getTargetBuiltins() const override { return {}; } + std::pair> + getTargetBuiltinStorage() const override { + return {nullptr, {}}; + } std::string_view getClobbers() const override { return ""; } diff --git a/clang/lib/Basic/Targets/Hexagon.cpp b/clang/lib/Basic/Targets/Hexagon.cpp index 0282ac812c306..70059d68c562b 100644 --- a/clang/lib/Basic/Targets/Hexagon.cpp +++ b/clang/lib/Basic/Targets/Hexagon.cpp @@ -198,15 +198,19 @@ ArrayRef HexagonTargetInfo::getGCCRegAliases() const { return llvm::ArrayRef(GCCRegAliases); } -static constexpr Builtin::Info BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ - {#ID, TYPE, ATTRS, nullptr, HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +static constexpr int NumBuiltins = + clang::Hexagon::LastTSBuiltin - Builtin::FirstTSBuiltin; + +static constexpr auto BuiltinStorage = Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsHexagon.def" -}; + , { +#define BUILTIN CLANG_BUILTIN_ENTRY +#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +#include "clang/Basic/BuiltinsHexagon.def" + }); bool HexagonTargetInfo::hasFeature(StringRef Feature) const { std::string VS = "hvxv" + HVXVersion; @@ -264,7 +268,7 @@ void HexagonTargetInfo::fillValidCPUList( Values.push_back(Suffix.Name); } -ArrayRef HexagonTargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin - - Builtin::FirstTSBuiltin); +std::pair> +HexagonTargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } diff --git a/clang/lib/Basic/Targets/Hexagon.h b/clang/lib/Basic/Targets/Hexagon.h index 7f053ab7e4888..2230735b8971b 100644 --- a/clang/lib/Basic/Targets/Hexagon.h +++ b/clang/lib/Basic/Targets/Hexagon.h @@ -66,7 +66,8 @@ class LLVM_LIBRARY_VISIBILITY HexagonTargetInfo : public TargetInfo { BoolWidth = BoolAlign = 8; } - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &Info) const override { diff --git a/clang/lib/Basic/Targets/Lanai.h b/clang/lib/Basic/Targets/Lanai.h index f7e439c7c9e1c..f37b0fdb08731 100644 --- a/clang/lib/Basic/Targets/Lanai.h +++ b/clang/lib/Basic/Targets/Lanai.h @@ -78,7 +78,10 @@ class LLVM_LIBRARY_VISIBILITY LanaiTargetInfo : public TargetInfo { return TargetInfo::VoidPtrBuiltinVaList; } - ArrayRef getTargetBuiltins() const override { return {}; } + std::pair> + getTargetBuiltinStorage() const override { + return {nullptr, {}}; + } bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &info) const override { diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp index d36186aa9c2fb..7c714000af42f 100644 --- a/clang/lib/Basic/Targets/LoongArch.cpp +++ b/clang/lib/Basic/Targets/LoongArch.cpp @@ -270,13 +270,18 @@ void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); } -static constexpr Builtin::Info BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +static constexpr int NumBuiltins = + clang::LoongArch::LastTSBuiltin - Builtin::FirstTSBuiltin; + +static constexpr auto BuiltinStorage = Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE +#include "clang/Basic/BuiltinsLoongArch.def" + , { +#define BUILTIN CLANG_BUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY #include "clang/Basic/BuiltinsLoongArch.def" -}; + }); bool LoongArchTargetInfo::initFeatureMap( llvm::StringMap &Features, DiagnosticsEngine &Diags, StringRef CPU, @@ -303,9 +308,9 @@ bool LoongArchTargetInfo::hasFeature(StringRef Feature) const { .Default(false); } -ArrayRef LoongArchTargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfo, clang::LoongArch::LastTSBuiltin - - Builtin::FirstTSBuiltin); +std::pair> +LoongArchTargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } bool LoongArchTargetInfo::handleTargetFeatures( diff --git a/clang/lib/Basic/Targets/LoongArch.h b/clang/lib/Basic/Targets/LoongArch.h index abaa05aa42d43..1bb82667cb512 100644 --- a/clang/lib/Basic/Targets/LoongArch.h +++ b/clang/lib/Basic/Targets/LoongArch.h @@ -70,7 +70,8 @@ class LLVM_LIBRARY_VISIBILITY LoongArchTargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::VoidPtrBuiltinVaList; diff --git a/clang/lib/Basic/Targets/M68k.cpp b/clang/lib/Basic/Targets/M68k.cpp index b5b29fd867563..5670c6309e717 100644 --- a/clang/lib/Basic/Targets/M68k.cpp +++ b/clang/lib/Basic/Targets/M68k.cpp @@ -115,9 +115,10 @@ void M68kTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__HAVE_68881__"); } -ArrayRef M68kTargetInfo::getTargetBuiltins() const { +std::pair> +M68kTargetInfo::getTargetBuiltinStorage() const { // FIXME: Implement. - return {}; + return {nullptr, {}}; } bool M68kTargetInfo::hasFeature(StringRef Feature) const { diff --git a/clang/lib/Basic/Targets/M68k.h b/clang/lib/Basic/Targets/M68k.h index b732add77e034..c68b2ab132ea0 100644 --- a/clang/lib/Basic/Targets/M68k.h +++ b/clang/lib/Basic/Targets/M68k.h @@ -44,7 +44,8 @@ class LLVM_LIBRARY_VISIBILITY M68kTargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; bool hasFeature(StringRef Feature) const override; ArrayRef getGCCRegNames() const override; ArrayRef getGCCRegAliases() const override; diff --git a/clang/lib/Basic/Targets/MSP430.h b/clang/lib/Basic/Targets/MSP430.h index 2266ada25c1dd..462bcdfaa9b21 100644 --- a/clang/lib/Basic/Targets/MSP430.h +++ b/clang/lib/Basic/Targets/MSP430.h @@ -50,9 +50,10 @@ class LLVM_LIBRARY_VISIBILITY MSP430TargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - ArrayRef getTargetBuiltins() const override { + std::pair> + getTargetBuiltinStorage() const override { // FIXME: Implement. - return {}; + return {nullptr, {}}; } bool allowsLargerPreferedTypeAlignment() const override { return false; } diff --git a/clang/lib/Basic/Targets/Mips.cpp b/clang/lib/Basic/Targets/Mips.cpp index 174bc9d2ab996..b4f137b2c1950 100644 --- a/clang/lib/Basic/Targets/Mips.cpp +++ b/clang/lib/Basic/Targets/Mips.cpp @@ -20,13 +20,17 @@ using namespace clang; using namespace clang::targets; -static constexpr Builtin::Info BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES}, +static constexpr int NumBuiltins = + clang::Mips::LastTSBuiltin - Builtin::FirstTSBuiltin; + +static constexpr auto BuiltinStorage = Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#include "clang/Basic/BuiltinsMips.def" + , { +#define BUILTIN CLANG_BUILTIN_ENTRY +#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY #include "clang/Basic/BuiltinsMips.def" -}; + }); bool MipsTargetInfo::processorSupportsGPR64() const { return llvm::StringSwitch(CPU) @@ -223,9 +227,9 @@ bool MipsTargetInfo::hasFeature(StringRef Feature) const { .Default(false); } -ArrayRef MipsTargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfo, - clang::Mips::LastTSBuiltin - Builtin::FirstTSBuiltin); +std::pair> +MipsTargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } unsigned MipsTargetInfo::getUnwindWordWidth() const { diff --git a/clang/lib/Basic/Targets/Mips.h b/clang/lib/Basic/Targets/Mips.h index 8acaf56523b21..2749b5d43a45d 100644 --- a/clang/lib/Basic/Targets/Mips.h +++ b/clang/lib/Basic/Targets/Mips.h @@ -197,7 +197,8 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; bool hasFeature(StringRef Feature) const override; diff --git a/clang/lib/Basic/Targets/NVPTX.cpp b/clang/lib/Basic/Targets/NVPTX.cpp index dbc3fec365761..1d490d9f12992 100644 --- a/clang/lib/Basic/Targets/NVPTX.cpp +++ b/clang/lib/Basic/Targets/NVPTX.cpp @@ -20,15 +20,19 @@ using namespace clang; using namespace clang::targets; -static constexpr Builtin::Info BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +static constexpr int NumBuiltins = + clang::NVPTX::LastTSBuiltin - Builtin::FirstTSBuiltin; + +static constexpr auto BuiltinStorage = Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE +#include "clang/Basic/BuiltinsNVPTX.def" + , { +#define BUILTIN CLANG_BUILTIN_ENTRY +#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY #include "clang/Basic/BuiltinsNVPTX.def" -}; + }); const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"}; @@ -295,7 +299,7 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts, } } -ArrayRef NVPTXTargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfo, - clang::NVPTX::LastTSBuiltin - Builtin::FirstTSBuiltin); +std::pair> +NVPTXTargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h index d81b89a7f24ac..6520f441b4167 100644 --- a/clang/lib/Basic/Targets/NVPTX.h +++ b/clang/lib/Basic/Targets/NVPTX.h @@ -74,7 +74,8 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; bool useFP16ConversionIntrinsics() const override { return false; } diff --git a/clang/lib/Basic/Targets/PNaCl.h b/clang/lib/Basic/Targets/PNaCl.h index 7e0e10aa362d8..20c0892fbf8c8 100644 --- a/clang/lib/Basic/Targets/PNaCl.h +++ b/clang/lib/Basic/Targets/PNaCl.h @@ -52,7 +52,10 @@ class LLVM_LIBRARY_VISIBILITY PNaClTargetInfo : public TargetInfo { return Feature == "pnacl"; } - ArrayRef getTargetBuiltins() const override { return {}; } + std::pair> + getTargetBuiltinStorage() const override { + return {nullptr, {}}; + } BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::PNaClABIBuiltinVaList; diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index 1448069173b5f..6aa36839afa81 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -19,15 +19,19 @@ using namespace clang; using namespace clang::targets; -static constexpr Builtin::Info BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES}, +static constexpr int NumBuiltins = + clang::PPC::LastTSBuiltin - Builtin::FirstTSBuiltin; + +static constexpr auto BuiltinStorage = Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsPPC.def" -}; + , { +#define BUILTIN CLANG_BUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY +#include "clang/Basic/BuiltinsPPC.def" + }); /// handleTargetFeatures - Perform initialization based on the user /// configured set of features. @@ -927,9 +931,9 @@ void PPCTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) { MaxAtomicInlineWidth = 128; } -ArrayRef PPCTargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfo, - clang::PPC::LastTSBuiltin - Builtin::FirstTSBuiltin); +std::pair> +PPCTargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } bool PPCTargetInfo::validateCpuSupports(StringRef FeatureStr) const { diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index b0833d30550af..4e8da8406116e 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -187,7 +187,8 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo { StringRef getABI() const override { return ABI; } - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; bool isCLZForZeroUndef() const override { return false; } diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index a541dfedc9b8e..0add1dfdb2f57 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -240,22 +240,28 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, } } -static constexpr Builtin::Info BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +static constexpr int NumBuiltins = + clang::RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin; + +static constexpr auto BuiltinStorage = Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE +#include "clang/Basic/BuiltinsRISCVVector.def" +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE +#include "clang/Basic/BuiltinsRISCV.inc" + , { +#define BUILTIN CLANG_BUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY #include "clang/Basic/BuiltinsRISCVVector.def" -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +#define BUILTIN CLANG_BUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY #include "clang/Basic/BuiltinsRISCV.inc" -}; + }); -ArrayRef RISCVTargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfo, - clang::RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin); +std::pair> +RISCVTargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } bool RISCVTargetInfo::initFeatureMap( diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index 68f10e74ba98c..a168952e6c6f5 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -62,7 +62,8 @@ class RISCVTargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::VoidPtrBuiltinVaList; diff --git a/clang/lib/Basic/Targets/SPIR.cpp b/clang/lib/Basic/Targets/SPIR.cpp index 040303983594f..b0e1fa35cca69 100644 --- a/clang/lib/Basic/Targets/SPIR.cpp +++ b/clang/lib/Basic/Targets/SPIR.cpp @@ -81,8 +81,9 @@ SPIRV64AMDGCNTargetInfo::convertConstraint(const char *&Constraint) const { return AMDGPUTI.convertConstraint(Constraint); } -ArrayRef SPIRV64AMDGCNTargetInfo::getTargetBuiltins() const { - return AMDGPUTI.getTargetBuiltins(); +std::pair> +SPIRV64AMDGCNTargetInfo::getTargetBuiltinStorage() const { + return AMDGPUTI.getTargetBuiltinStorage(); } void SPIRV64AMDGCNTargetInfo::getTargetDefines(const LangOptions &Opts, diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index 85e4bd920d853..f25c0cb93e657 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -159,7 +159,10 @@ class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo { // memcpy as per section 3 of the SPIR spec. bool useFP16ConversionIntrinsics() const override { return false; } - ArrayRef getTargetBuiltins() const override { return {}; } + std::pair> + getTargetBuiltinStorage() const override { + return {nullptr, {}}; + } std::string_view getClobbers() const override { return ""; } @@ -408,7 +411,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64AMDGCNTargetInfo final std::string convertConstraint(const char *&Constraint) const override; - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; diff --git a/clang/lib/Basic/Targets/Sparc.h b/clang/lib/Basic/Targets/Sparc.h index 9c529a5bc5e7f..480073fae35c5 100644 --- a/clang/lib/Basic/Targets/Sparc.h +++ b/clang/lib/Basic/Targets/Sparc.h @@ -48,9 +48,10 @@ class LLVM_LIBRARY_VISIBILITY SparcTargetInfo : public TargetInfo { bool hasFeature(StringRef Feature) const override; - ArrayRef getTargetBuiltins() const override { + std::pair> + getTargetBuiltinStorage() const override { // FIXME: Implement! - return {}; + return {nullptr, {}}; } BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::VoidPtrBuiltinVaList; diff --git a/clang/lib/Basic/Targets/SystemZ.cpp b/clang/lib/Basic/Targets/SystemZ.cpp index 06f08db2eadd4..ffc55a80db9d9 100644 --- a/clang/lib/Basic/Targets/SystemZ.cpp +++ b/clang/lib/Basic/Targets/SystemZ.cpp @@ -20,13 +20,18 @@ using namespace clang; using namespace clang::targets; -static constexpr Builtin::Info BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +static constexpr int NumBuiltins = + clang::SystemZ::LastTSBuiltin - Builtin::FirstTSBuiltin; + +static constexpr auto BuiltinStorage = Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsSystemZ.def" -}; + , { +#define BUILTIN CLANG_BUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +#include "clang/Basic/BuiltinsSystemZ.def" + }); const char *const SystemZTargetInfo::GCCRegNames[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", @@ -170,7 +175,7 @@ void SystemZTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__VEC__", "10304"); } -ArrayRef SystemZTargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfo, clang::SystemZ::LastTSBuiltin - - Builtin::FirstTSBuiltin); +std::pair> +SystemZTargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h index ef9a07033a6e4..98637f230b69c 100644 --- a/clang/lib/Basic/Targets/SystemZ.h +++ b/clang/lib/Basic/Targets/SystemZ.h @@ -99,7 +99,8 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; ArrayRef getGCCRegNames() const override; diff --git a/clang/lib/Basic/Targets/TCE.h b/clang/lib/Basic/Targets/TCE.h index d6280b02f07b2..52a2b13fe2805 100644 --- a/clang/lib/Basic/Targets/TCE.h +++ b/clang/lib/Basic/Targets/TCE.h @@ -95,7 +95,10 @@ class LLVM_LIBRARY_VISIBILITY TCETargetInfo : public TargetInfo { bool hasFeature(StringRef Feature) const override { return Feature == "tce"; } - ArrayRef getTargetBuiltins() const override { return {}; } + std::pair> + getTargetBuiltinStorage() const override { + return {nullptr, {}}; + } std::string_view getClobbers() const override { return ""; } diff --git a/clang/lib/Basic/Targets/VE.cpp b/clang/lib/Basic/Targets/VE.cpp index 67cae8faf6052..f54ddc00f6f68 100644 --- a/clang/lib/Basic/Targets/VE.cpp +++ b/clang/lib/Basic/Targets/VE.cpp @@ -18,11 +18,16 @@ using namespace clang; using namespace clang::targets; -static constexpr Builtin::Info BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +static constexpr int NumBuiltins = + clang::VE::LastTSBuiltin - Builtin::FirstTSBuiltin; + +static constexpr auto BuiltinStorage = Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#include "clang/Basic/BuiltinsVE.def" + , { +#define BUILTIN CLANG_BUILTIN_ENTRY #include "clang/Basic/BuiltinsVE.def" -}; + }); void VETargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { @@ -39,7 +44,7 @@ void VETargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); } -ArrayRef VETargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfo, - clang::VE::LastTSBuiltin - Builtin::FirstTSBuiltin); +std::pair> +VETargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } diff --git a/clang/lib/Basic/Targets/VE.h b/clang/lib/Basic/Targets/VE.h index 7e8fdf6096ef2..d2b0cd6de4d51 100644 --- a/clang/lib/Basic/Targets/VE.h +++ b/clang/lib/Basic/Targets/VE.h @@ -55,7 +55,8 @@ class LLVM_LIBRARY_VISIBILITY VETargetInfo : public TargetInfo { bool hasSjLjLowering() const override { return true; } - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::VoidPtrBuiltinVaList; diff --git a/clang/lib/Basic/Targets/WebAssembly.cpp b/clang/lib/Basic/Targets/WebAssembly.cpp index 85e550ad20d5e..a837c3df99217 100644 --- a/clang/lib/Basic/Targets/WebAssembly.cpp +++ b/clang/lib/Basic/Targets/WebAssembly.cpp @@ -20,15 +20,19 @@ using namespace clang; using namespace clang::targets; -static constexpr Builtin::Info BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES}, +static constexpr int NumBuiltins = + clang::WebAssembly::LastTSBuiltin - Builtin::FirstTSBuiltin; + +static constexpr auto BuiltinStorage = Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE +#include "clang/Basic/BuiltinsWebAssembly.def" + , { +#define BUILTIN CLANG_BUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY #include "clang/Basic/BuiltinsWebAssembly.def" -}; + }); static constexpr llvm::StringLiteral ValidCPUNames[] = { {"mvp"}, {"bleeding-edge"}, {"generic"}, {"lime"}}; @@ -360,9 +364,9 @@ bool WebAssemblyTargetInfo::handleTargetFeatures( return true; } -ArrayRef WebAssemblyTargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfo, clang::WebAssembly::LastTSBuiltin - - Builtin::FirstTSBuiltin); +std::pair> +WebAssemblyTargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags, diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h index c92ed161a92a7..1cae72e58e08b 100644 --- a/clang/lib/Basic/Targets/WebAssembly.h +++ b/clang/lib/Basic/Targets/WebAssembly.h @@ -120,7 +120,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo { bool setCPU(const std::string &Name) final { return isValidCPUName(Name); } - ArrayRef getTargetBuiltins() const final; + std::pair> + getTargetBuiltinStorage() const final; BuiltinVaListKind getBuiltinVaListKind() const final { return VoidPtrBuiltinVaList; diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index 1b16888a0711b..0b071573aa1e0 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -23,31 +23,45 @@ namespace clang { namespace targets { -static constexpr Builtin::Info BuiltinInfoX86[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::HEADER, LANGS}, +// The x86-32 builtins are a subset and prefix of the x86-64 builtins. +static constexpr int NumX86Builtins = + X86::LastX86CommonBuiltin - Builtin::FirstTSBuiltin + 1; +static constexpr int NumX86_64Builtins = + X86::LastTSBuiltin - Builtin::FirstTSBuiltin; +static_assert(NumX86Builtins < NumX86_64Builtins); + +static constexpr auto BuiltinStorage = + Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE +#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsX86.def" -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::HEADER, LANGS}, +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE +#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsX86.inc" -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ - {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::HEADER, LANGS}, +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE +#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsX86_64.def" -}; + , { +#define BUILTIN CLANG_BUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_ENTRY +#include "clang/Basic/BuiltinsX86.def" + +#define BUILTIN CLANG_BUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_ENTRY +#include "clang/Basic/BuiltinsX86.inc" + +#define BUILTIN CLANG_BUILTIN_ENTRY +#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_ENTRY +#include "clang/Basic/BuiltinsX86_64.def" + }); static const char *const GCCRegNames[] = { "ax", "dx", "cx", "bx", "si", "di", "bp", "sp", @@ -1864,12 +1878,14 @@ ArrayRef X86TargetInfo::getGCCAddlRegNames() const { return llvm::ArrayRef(AddlRegNames); } -ArrayRef X86_32TargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfoX86, clang::X86::LastX86CommonBuiltin - - Builtin::FirstTSBuiltin + 1); +std::pair> +X86_32TargetInfo::getTargetBuiltinStorage() const { + // Only use the relevant prefix of the infos, the string table base is common. + return {BuiltinStorage.StringTable, + llvm::ArrayRef(BuiltinStorage.Infos).take_front(NumX86Builtins)}; } -ArrayRef X86_64TargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfoX86, - X86::LastTSBuiltin - Builtin::FirstTSBuiltin); +std::pair> +X86_64TargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index 3ed36c8fa724b..385d9e87a4e37 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -508,7 +508,8 @@ class LLVM_LIBRARY_VISIBILITY X86_32TargetInfo : public X86TargetInfo { MaxAtomicInlineWidth = 64; } - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; bool hasBitIntType() const override { return true; } size_t getMaxBitIntWidth() const override { @@ -812,7 +813,8 @@ class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo { MaxAtomicInlineWidth = 128; } - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; bool hasBitIntType() const override { return true; } size_t getMaxBitIntWidth() const override { diff --git a/clang/lib/Basic/Targets/XCore.cpp b/clang/lib/Basic/Targets/XCore.cpp index fd377bbfb90e1..403d421d0c067 100644 --- a/clang/lib/Basic/Targets/XCore.cpp +++ b/clang/lib/Basic/Targets/XCore.cpp @@ -18,13 +18,17 @@ using namespace clang; using namespace clang::targets; -static constexpr Builtin::Info BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ - {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES}, +static constexpr int NumBuiltins = + XCore::LastTSBuiltin - Builtin::FirstTSBuiltin; + +static constexpr auto BuiltinStorage = Builtin::Storage::Make( +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#include "clang/Basic/BuiltinsXCore.def" + , { +#define BUILTIN CLANG_BUILTIN_ENTRY +#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY #include "clang/Basic/BuiltinsXCore.def" -}; + }); void XCoreTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { @@ -32,7 +36,7 @@ void XCoreTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__XS1B__"); } -ArrayRef XCoreTargetInfo::getTargetBuiltins() const { - return llvm::ArrayRef(BuiltinInfo, - clang::XCore::LastTSBuiltin - Builtin::FirstTSBuiltin); +std::pair> +XCoreTargetInfo::getTargetBuiltinStorage() const { + return {BuiltinStorage.StringTable, BuiltinStorage.Infos}; } diff --git a/clang/lib/Basic/Targets/XCore.h b/clang/lib/Basic/Targets/XCore.h index 84fd59d1a71e4..1082990d74b2b 100644 --- a/clang/lib/Basic/Targets/XCore.h +++ b/clang/lib/Basic/Targets/XCore.h @@ -43,7 +43,8 @@ class LLVM_LIBRARY_VISIBILITY XCoreTargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - ArrayRef getTargetBuiltins() const override; + std::pair> + getTargetBuiltinStorage() const override; BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::VoidPtrBuiltinVaList; diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 5963d43bb9672..b44f66493254f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -31,7 +31,7 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context, DiagnosticsEngine &diags) : builder(&context), astCtx(astctx), langOpts(astctx.getLangOpts()), theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&context))}, - diags(diags), target(astCtx.getTargetInfo()) {} + diags(diags), target(astCtx.getTargetInfo()), genTypes(*this) {} mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) { assert(cLoc.isValid() && "expected valid source location"); @@ -67,7 +67,8 @@ void CIRGenModule::emitGlobal(clang::GlobalDecl gd) { return; } } else { - errorNYI(global->getSourceRange(), "global variable declaration"); + assert(cast(global)->isFileVarDecl() && + "Cannot emit local var decl as global"); } // TODO(CIR): Defer emitting some global definitions until later @@ -77,9 +78,27 @@ void CIRGenModule::emitGlobal(clang::GlobalDecl gd) { void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op) { auto const *funcDecl = cast(gd.getDecl()); - auto funcOp = builder.create( - getLoc(funcDecl->getSourceRange()), funcDecl->getIdentifier()->getName()); - theModule.push_back(funcOp); + if (clang::IdentifierInfo *identifier = funcDecl->getIdentifier()) { + auto funcOp = builder.create( + getLoc(funcDecl->getSourceRange()), identifier->getName()); + theModule.push_back(funcOp); + } else { + errorNYI(funcDecl->getSourceRange().getBegin(), + "function definition with a non-identifier for a name"); + } +} + +void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd, + bool isTentative) { + mlir::Type type = getTypes().convertType(vd->getType()); + if (clang::IdentifierInfo *identifier = vd->getIdentifier()) { + auto varOp = builder.create(getLoc(vd->getSourceRange()), + identifier->getName(), type); + theModule.push_back(varOp); + } else { + errorNYI(vd->getSourceRange().getBegin(), + "variable definition with a non-identifier for a name"); + } } void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd, @@ -103,6 +122,9 @@ void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd, return; } + if (const auto *vd = dyn_cast(decl)) + return emitGlobalVarDefinition(vd, !vd->hasDefinition()); + llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition"); } @@ -126,13 +148,13 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) { emitGlobal(fd); break; } - } -} -DiagnosticBuilder CIRGenModule::errorNYI(llvm::StringRef feature) { - unsigned diagID = diags.getCustomDiagID( - DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0"); - return diags.Report(diagID) << feature; + case Decl::Var: { + auto *vd = cast(decl); + emitGlobal(vd); + break; + } + } } DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc, @@ -142,21 +164,7 @@ DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc, return diags.Report(loc, diagID) << feature; } -DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc, - llvm::StringRef feature, - llvm::StringRef name) { - unsigned diagID = diags.getCustomDiagID( - DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0: %1"); - return diags.Report(loc, diagID) << feature << name; -} - DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc, llvm::StringRef feature) { return errorNYI(loc.getBegin(), feature) << loc; } - -DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc, - llvm::StringRef feature, - llvm::StringRef name) { - return errorNYI(loc.getBegin(), feature, name) << loc; -} diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index aaded92e6a633..7a84c942af491 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -14,23 +14,22 @@ #define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H #include "CIRGenTypeCache.h" +#include "CIRGenTypes.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/MLIRContext.h" +#include "clang/Basic/SourceManager.h" #include "llvm/ADT/StringRef.h" namespace clang { class ASTContext; class CodeGenOptions; class Decl; -class DiagnosticBuilder; -class DiagnosticsEngine; class GlobalDecl; class LangOptions; -class SourceLocation; -class SourceRange; class TargetInfo; +class VarDecl; namespace CIRGen { @@ -64,8 +63,13 @@ class CIRGenModule : public CIRGenTypeCache { const clang::TargetInfo ⌖ + CIRGenTypes genTypes; + public: mlir::ModuleOp getModule() const { return theModule; } + mlir::OpBuilder &getBuilder() { return builder; } + clang::ASTContext &getASTContext() const { return astCtx; } + CIRGenTypes &getTypes() { return genTypes; } /// Helpers to convert the presumed location of Clang's SourceLocation to an /// MLIR Location. @@ -81,13 +85,28 @@ class CIRGenModule : public CIRGenTypeCache { void emitGlobalDefinition(clang::GlobalDecl gd, mlir::Operation *op = nullptr); void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op); + void emitGlobalVarDefinition(const clang::VarDecl *vd, + bool isTentative = false); /// Helpers to emit "not yet implemented" error diagnostics - DiagnosticBuilder errorNYI(llvm::StringRef); DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef); - DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef, llvm::StringRef); + + template + DiagnosticBuilder errorNYI(SourceLocation loc, llvm::StringRef feature, + const T &name) { + unsigned diagID = + diags.getCustomDiagID(DiagnosticsEngine::Error, + "ClangIR code gen Not Yet Implemented: %0: %1"); + return diags.Report(loc, diagID) << feature << name; + } + DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef); - DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef, llvm::StringRef); + + template + DiagnosticBuilder errorNYI(SourceRange loc, llvm::StringRef feature, + const T &name) { + return errorNYI(loc.getBegin(), feature, name) << loc; + } }; } // namespace CIRGen diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp new file mode 100644 index 0000000000000..e3fcbacf5f810 --- /dev/null +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -0,0 +1,87 @@ +#include "CIRGenTypes.h" + +#include "CIRGenModule.h" + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Type.h" + +using namespace clang; +using namespace clang::CIRGen; + +CIRGenTypes::CIRGenTypes(CIRGenModule &genModule) + : cgm(genModule), context(genModule.getASTContext()) {} + +CIRGenTypes::~CIRGenTypes() {} + +mlir::Type CIRGenTypes::convertType(QualType type) { + type = context.getCanonicalType(type); + const Type *ty = type.getTypePtr(); + + // For types that haven't been implemented yet or are otherwise unsupported, + // report an error and return 'int'. + + mlir::Type resultType = nullptr; + switch (ty->getTypeClass()) { + case Type::Builtin: { + switch (cast(ty)->getKind()) { + // Signed types. + case BuiltinType::Char_S: + case BuiltinType::Int: + case BuiltinType::Int128: + case BuiltinType::Long: + case BuiltinType::LongLong: + case BuiltinType::SChar: + case BuiltinType::Short: + case BuiltinType::WChar_S: + resultType = cir::IntType::get(cgm.getBuilder().getContext(), + context.getTypeSize(ty), + /*isSigned=*/true); + break; + // Unsigned types. + case BuiltinType::Char8: + case BuiltinType::Char16: + case BuiltinType::Char32: + case BuiltinType::Char_U: + case BuiltinType::UChar: + case BuiltinType::UInt: + case BuiltinType::UInt128: + case BuiltinType::ULong: + case BuiltinType::ULongLong: + case BuiltinType::UShort: + case BuiltinType::WChar_U: + resultType = cir::IntType::get(cgm.getBuilder().getContext(), + context.getTypeSize(ty), + /*isSigned=*/false); + break; + default: + cgm.errorNYI(SourceLocation(), "processing of built-in type", type); + resultType = cir::IntType::get(cgm.getBuilder().getContext(), 32, + /*isSigned=*/true); + break; + } + break; + } + case Type::BitInt: { + const auto *bitIntTy = cast(type); + if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) { + cgm.errorNYI(SourceLocation(), "large _BitInt type", type); + resultType = cir::IntType::get(cgm.getBuilder().getContext(), 32, + /*isSigned=*/true); + } else { + resultType = + cir::IntType::get(cgm.getBuilder().getContext(), + bitIntTy->getNumBits(), bitIntTy->isSigned()); + } + break; + } + default: + cgm.errorNYI(SourceLocation(), "processing of type", type); + resultType = + cir::IntType::get(cgm.getBuilder().getContext(), 32, /*isSigned=*/true); + break; + } + + assert(resultType && "Type conversion not yet implemented"); + + return resultType; +} diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.h b/clang/lib/CIR/CodeGen/CIRGenTypes.h new file mode 100644 index 0000000000000..b37738c770de1 --- /dev/null +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.h @@ -0,0 +1,47 @@ +//===--- CIRGenTypes.h - Type translation for CIR CodeGen -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is the code that handles AST -> CIR type lowering. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H +#define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H + +#include "clang/CIR/Dialect/IR/CIRTypes.h" + +namespace clang { +class ASTContext; +class QualType; +} // namespace clang + +namespace mlir { +class Type; +} + +namespace clang::CIRGen { + +class CIRGenModule; + +/// This class organizes the cross-module state that is used while lowering +/// AST types to CIR types. +class CIRGenTypes { + CIRGenModule &cgm; + clang::ASTContext &context; + +public: + CIRGenTypes(CIRGenModule &cgm); + ~CIRGenTypes(); + + /// Convert a Clang type into a mlir::Type. + mlir::Type convertType(clang::QualType type); +}; + +} // namespace clang::CIRGen + +#endif diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt index 17a3aabfbd7f0..9ada31c11de95 100644 --- a/clang/lib/CIR/CodeGen/CMakeLists.txt +++ b/clang/lib/CIR/CodeGen/CMakeLists.txt @@ -9,6 +9,7 @@ get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS) add_clang_library(clangCIR CIRGenerator.cpp CIRGenModule.cpp + CIRGenTypes.cpp DEPENDS MLIRCIR diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index f666e5ab4b999..dbdca1f840166 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -32,6 +32,22 @@ void cir::CIRDialect::initialize() { >(); } +//===----------------------------------------------------------------------===// +// GlobalOp +//===----------------------------------------------------------------------===// + +// TODO(CIR): The properties of global variables that require verification +// haven't been implemented yet. +mlir::LogicalResult cir::GlobalOp::verify() { return success(); } + +void cir::GlobalOp::build(OpBuilder &odsBuilder, OperationState &odsState, + llvm::StringRef sym_name, mlir::Type sym_type) { + odsState.addAttribute(getSymNameAttrName(odsState.name), + odsBuilder.getStringAttr(sym_name)); + odsState.addAttribute(getSymTypeAttrName(odsState.name), + mlir::TypeAttr::get(sym_type)); +} + //===----------------------------------------------------------------------===// // FuncOp //===----------------------------------------------------------------------===// @@ -56,6 +72,8 @@ void cir::FuncOp::print(OpAsmPrinter &p) { p.printSymbolName(getSymName()); } +// TODO(CIR): The properties of functions that require verification haven't +// been implemented yet. mlir::LogicalResult cir::FuncOp::verify() { return success(); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index 4eeb70f06f5f7..de38337057d3d 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -10,7 +10,18 @@ // //===----------------------------------------------------------------------===// +#include "clang/CIR/Dialect/IR/CIRTypes.h" + +#include "mlir/IR/DialectImplementation.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "llvm/ADT/TypeSwitch.h" + +//===----------------------------------------------------------------------===// +// Get autogenerated stuff +//===----------------------------------------------------------------------===// + +#define GET_TYPEDEF_CLASSES +#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc" using namespace mlir; using namespace cir; @@ -20,12 +31,106 @@ using namespace cir; //===----------------------------------------------------------------------===// Type CIRDialect::parseType(DialectAsmParser &parser) const { - // No types yet to parse - return Type{}; + llvm::SMLoc typeLoc = parser.getCurrentLocation(); + llvm::StringRef mnemonic; + Type genType; + + // Try to parse as a tablegen'd type. + OptionalParseResult parseResult = + generatedTypeParser(parser, &mnemonic, genType); + if (parseResult.has_value()) + return genType; + + // TODO(CIR) Attempt to parse as a raw C++ type. + parser.emitError(typeLoc) << "unknown CIR type: " << mnemonic; + return Type(); } void CIRDialect::printType(Type type, DialectAsmPrinter &os) const { - // No types yet to print + // Try to print as a tablegen'd type. + if (generatedTypePrinter(type, os).succeeded()) + return; + + // TODO(CIR) Attempt to print as a raw C++ type. + llvm::report_fatal_error("printer is missing a handler for this type"); +} + +//===----------------------------------------------------------------------===// +// IntType Definitions +//===----------------------------------------------------------------------===// + +Type IntType::parse(mlir::AsmParser &parser) { + mlir::MLIRContext *context = parser.getBuilder().getContext(); + llvm::SMLoc loc = parser.getCurrentLocation(); + bool isSigned; + unsigned width; + + if (parser.parseLess()) + return {}; + + // Fetch integer sign. + llvm::StringRef sign; + if (parser.parseKeyword(&sign)) + return {}; + if (sign == "s") + isSigned = true; + else if (sign == "u") + isSigned = false; + else { + parser.emitError(loc, "expected 's' or 'u'"); + return {}; + } + + if (parser.parseComma()) + return {}; + + // Fetch integer size. + if (parser.parseInteger(width)) + return {}; + if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) { + parser.emitError(loc, "expected integer width to be from ") + << IntType::minBitwidth() << " up to " << IntType::maxBitwidth(); + return {}; + } + + if (parser.parseGreater()) + return {}; + + return IntType::get(context, width, isSigned); +} + +void IntType::print(mlir::AsmPrinter &printer) const { + char sign = isSigned() ? 's' : 'u'; + printer << '<' << sign << ", " << getWidth() << '>'; +} + +llvm::TypeSize +IntType::getTypeSizeInBits(const mlir::DataLayout &dataLayout, + mlir::DataLayoutEntryListRef params) const { + return llvm::TypeSize::getFixed(getWidth()); +} + +uint64_t IntType::getABIAlignment(const mlir::DataLayout &dataLayout, + mlir::DataLayoutEntryListRef params) const { + return (uint64_t)(getWidth() / 8); +} + +uint64_t +IntType::getPreferredAlignment(const ::mlir::DataLayout &dataLayout, + ::mlir::DataLayoutEntryListRef params) const { + return (uint64_t)(getWidth() / 8); +} + +mlir::LogicalResult +IntType::verify(llvm::function_ref emitError, + unsigned width, bool isSigned) { + if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) { + emitError() << "IntType only supports widths from " + << IntType::minBitwidth() << " up to " + << IntType::maxBitwidth(); + return mlir::failure(); + } + return mlir::success(); } //===----------------------------------------------------------------------===// @@ -33,5 +138,12 @@ void CIRDialect::printType(Type type, DialectAsmPrinter &os) const { //===----------------------------------------------------------------------===// void CIRDialect::registerTypes() { - // No types yet to register + // Register tablegen'd types. + addTypes< +#define GET_TYPEDEF_LIST +#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc" + >(); + + // Register raw C++ types. + // TODO(CIR) addTypes(); } diff --git a/clang/lib/CIR/Dialect/IR/CMakeLists.txt b/clang/lib/CIR/Dialect/IR/CMakeLists.txt index 75cee3f871130..7ddc4ce501907 100644 --- a/clang/lib/CIR/Dialect/IR/CMakeLists.txt +++ b/clang/lib/CIR/Dialect/IR/CMakeLists.txt @@ -8,4 +8,8 @@ add_clang_library(MLIRCIR LINK_LIBS PUBLIC MLIRIR + MLIRDLTIDialect + MLIRDataLayoutInterfaces + MLIRFuncDialect + clangAST ) diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index bf9b04f02e9f4..8cf44592a1747 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -789,13 +789,12 @@ static void addSanitizers(const Triple &TargetTriple, } if (LowerAllowCheckPass::IsRequested()) { - // We can optimize after inliner, and PGO profile matching. The hook below - // is called at the end `buildFunctionSimplificationPipeline`, which called - // from `buildInlinerPipeline`, which called after profile matching. - PB.registerScalarOptimizerLateEPCallback( - [](FunctionPassManager &FPM, OptimizationLevel Level) { - FPM.addPass(LowerAllowCheckPass()); - }); + // We want to call it after inline, which is about OptimizerEarlyEPCallback. + PB.registerOptimizerEarlyEPCallback([](ModulePassManager &MPM, + OptimizationLevel Level, + ThinOrFullLTOPhase Phase) { + MPM.addPass(createModuleToFunctionPassAdaptor(LowerAllowCheckPass())); + }); } } @@ -1024,12 +1023,14 @@ void EmitAssemblyHelper::RunOptimizationPipeline( FPM.addPass(BoundsCheckingPass()); }); - if (LangOpts.Sanitize.has(SanitizerKind::Realtime)) + if (LangOpts.Sanitize.has(SanitizerKind::Realtime)) { PB.registerScalarOptimizerLateEPCallback( [](FunctionPassManager &FPM, OptimizationLevel Level) { RealtimeSanitizerOptions Opts; FPM.addPass(RealtimeSanitizerPass(Opts)); }); + MPM.addPass(ModuleRealtimeSanitizerPass()); + } // Don't add sanitizers if we are here from ThinLTO PostLink. That already // done on PreLink stage. diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 7588f8427cdd3..c2e983eebebc1 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -244,6 +244,19 @@ static Value *handleAsDoubleBuiltin(CodeGenFunction &CGF, const CallExpr *E) { return CGF.Builder.CreateBitCast(BitVec, ResultType); } +/// Helper for the read/write/add/inc X18 builtins: read the X18 register and +/// return it as an i8 pointer. +Value *readX18AsPtr(CodeGenFunction &CGF) { + LLVMContext &Context = CGF.CGM.getLLVMContext(); + llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")}; + llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops); + llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName); + llvm::Function *F = + CGF.CGM.getIntrinsic(llvm::Intrinsic::read_register, {CGF.Int64Ty}); + llvm::Value *X18 = CGF.Builder.CreateCall(F, Metadata); + return CGF.Builder.CreateIntToPtr(X18, CGF.Int8PtrTy); +} + /// getBuiltinLibFunction - Given a builtin id for a function like /// "__builtin_fabsf", return a Function* for "fabsf". llvm::Constant *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD, @@ -509,8 +522,15 @@ Value *EmitAtomicCmpXchgForMSIntrin(CodeGenFunction &CGF, const CallExpr *E, Address DestAddr = CheckAtomicAlignment(CGF, E); - auto *Comparand = CGF.EmitScalarExpr(E->getArg(2)); auto *Exchange = CGF.EmitScalarExpr(E->getArg(1)); + auto *RTy = Exchange->getType(); + + auto *Comparand = CGF.EmitScalarExpr(E->getArg(2)); + + if (RTy->isPointerTy()) { + Exchange = CGF.Builder.CreatePtrToInt(Exchange, CGF.IntPtrTy); + Comparand = CGF.Builder.CreatePtrToInt(Comparand, CGF.IntPtrTy); + } // For Release ordering, the failure ordering should be Monotonic. auto FailureOrdering = SuccessOrdering == AtomicOrdering::Release ? @@ -521,10 +541,16 @@ Value *EmitAtomicCmpXchgForMSIntrin(CodeGenFunction &CGF, const CallExpr *E, // blocks the few atomics optimizations that LLVM has. If we want to optimize // _Interlocked* operations in the future, we will have to remove the volatile // marker. - auto *Result = CGF.Builder.CreateAtomicCmpXchg( + auto *CmpXchg = CGF.Builder.CreateAtomicCmpXchg( DestAddr, Comparand, Exchange, SuccessOrdering, FailureOrdering); - Result->setVolatile(true); - return CGF.Builder.CreateExtractValue(Result, 0); + CmpXchg->setVolatile(true); + + auto *Result = CGF.Builder.CreateExtractValue(CmpXchg, 0); + if (RTy->isPointerTy()) { + Result = CGF.Builder.CreateIntToPtr(Result, RTy); + } + + return Result; } // 64-bit Microsoft platforms support 128 bit cmpxchg operations. They are @@ -1607,6 +1633,7 @@ enum class CodeGenFunction::MSVCIntrin { _BitScanForward, _BitScanReverse, _InterlockedAnd, + _InterlockedCompareExchange, _InterlockedDecrement, _InterlockedExchange, _InterlockedExchangeAdd, @@ -1692,26 +1719,31 @@ translateArmToMsvcIntrin(unsigned BuiltinID) { case clang::ARM::BI_InterlockedExchange16_acq: case clang::ARM::BI_InterlockedExchange_acq: case clang::ARM::BI_InterlockedExchange64_acq: + case clang::ARM::BI_InterlockedExchangePointer_acq: return MSVCIntrin::_InterlockedExchange_acq; case clang::ARM::BI_InterlockedExchange8_rel: case clang::ARM::BI_InterlockedExchange16_rel: case clang::ARM::BI_InterlockedExchange_rel: case clang::ARM::BI_InterlockedExchange64_rel: + case clang::ARM::BI_InterlockedExchangePointer_rel: return MSVCIntrin::_InterlockedExchange_rel; case clang::ARM::BI_InterlockedExchange8_nf: case clang::ARM::BI_InterlockedExchange16_nf: case clang::ARM::BI_InterlockedExchange_nf: case clang::ARM::BI_InterlockedExchange64_nf: + case clang::ARM::BI_InterlockedExchangePointer_nf: return MSVCIntrin::_InterlockedExchange_nf; case clang::ARM::BI_InterlockedCompareExchange8_acq: case clang::ARM::BI_InterlockedCompareExchange16_acq: case clang::ARM::BI_InterlockedCompareExchange_acq: case clang::ARM::BI_InterlockedCompareExchange64_acq: + case clang::ARM::BI_InterlockedCompareExchangePointer_acq: return MSVCIntrin::_InterlockedCompareExchange_acq; case clang::ARM::BI_InterlockedCompareExchange8_rel: case clang::ARM::BI_InterlockedCompareExchange16_rel: case clang::ARM::BI_InterlockedCompareExchange_rel: case clang::ARM::BI_InterlockedCompareExchange64_rel: + case clang::ARM::BI_InterlockedCompareExchangePointer_rel: return MSVCIntrin::_InterlockedCompareExchange_rel; case clang::ARM::BI_InterlockedCompareExchange8_nf: case clang::ARM::BI_InterlockedCompareExchange16_nf: @@ -1838,26 +1870,31 @@ translateAarch64ToMsvcIntrin(unsigned BuiltinID) { case clang::AArch64::BI_InterlockedExchange16_acq: case clang::AArch64::BI_InterlockedExchange_acq: case clang::AArch64::BI_InterlockedExchange64_acq: + case clang::AArch64::BI_InterlockedExchangePointer_acq: return MSVCIntrin::_InterlockedExchange_acq; case clang::AArch64::BI_InterlockedExchange8_rel: case clang::AArch64::BI_InterlockedExchange16_rel: case clang::AArch64::BI_InterlockedExchange_rel: case clang::AArch64::BI_InterlockedExchange64_rel: + case clang::AArch64::BI_InterlockedExchangePointer_rel: return MSVCIntrin::_InterlockedExchange_rel; case clang::AArch64::BI_InterlockedExchange8_nf: case clang::AArch64::BI_InterlockedExchange16_nf: case clang::AArch64::BI_InterlockedExchange_nf: case clang::AArch64::BI_InterlockedExchange64_nf: + case clang::AArch64::BI_InterlockedExchangePointer_nf: return MSVCIntrin::_InterlockedExchange_nf; case clang::AArch64::BI_InterlockedCompareExchange8_acq: case clang::AArch64::BI_InterlockedCompareExchange16_acq: case clang::AArch64::BI_InterlockedCompareExchange_acq: case clang::AArch64::BI_InterlockedCompareExchange64_acq: + case clang::AArch64::BI_InterlockedCompareExchangePointer_acq: return MSVCIntrin::_InterlockedCompareExchange_acq; case clang::AArch64::BI_InterlockedCompareExchange8_rel: case clang::AArch64::BI_InterlockedCompareExchange16_rel: case clang::AArch64::BI_InterlockedCompareExchange_rel: case clang::AArch64::BI_InterlockedCompareExchange64_rel: + case clang::AArch64::BI_InterlockedCompareExchangePointer_rel: return MSVCIntrin::_InterlockedCompareExchange_rel; case clang::AArch64::BI_InterlockedCompareExchange8_nf: case clang::AArch64::BI_InterlockedCompareExchange16_nf: @@ -2060,6 +2097,8 @@ Value *CodeGenFunction::EmitMSVCBuiltinExpr(MSVCIntrin BuiltinID, case MSVCIntrin::_InterlockedExchange_nf: return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E, AtomicOrdering::Monotonic); + case MSVCIntrin::_InterlockedCompareExchange: + return EmitAtomicCmpXchgForMSIntrin(*this, E); case MSVCIntrin::_InterlockedCompareExchange_acq: return EmitAtomicCmpXchgForMSIntrin(*this, E, AtomicOrdering::Acquire); case MSVCIntrin::_InterlockedCompareExchange_rel: @@ -5707,32 +5746,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get( EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange, E)); case Builtin::BI_InterlockedCompareExchangePointer: - case Builtin::BI_InterlockedCompareExchangePointer_nf: { - llvm::Type *RTy; - llvm::IntegerType *IntType = IntegerType::get( - getLLVMContext(), getContext().getTypeSize(E->getType())); - - Address DestAddr = CheckAtomicAlignment(*this, E); - - llvm::Value *Exchange = EmitScalarExpr(E->getArg(1)); - RTy = Exchange->getType(); - Exchange = Builder.CreatePtrToInt(Exchange, IntType); - - llvm::Value *Comparand = - Builder.CreatePtrToInt(EmitScalarExpr(E->getArg(2)), IntType); - - auto Ordering = - BuiltinID == Builtin::BI_InterlockedCompareExchangePointer_nf ? - AtomicOrdering::Monotonic : AtomicOrdering::SequentiallyConsistent; - - auto Result = Builder.CreateAtomicCmpXchg(DestAddr, Comparand, Exchange, - Ordering, Ordering); - Result->setVolatile(true); - - return RValue::get(Builder.CreateIntToPtr(Builder.CreateExtractValue(Result, - 0), - RTy)); - } + return RValue::get( + EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange, E)); + case Builtin::BI_InterlockedCompareExchangePointer_nf: + return RValue::get( + EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_nf, E)); case Builtin::BI_InterlockedCompareExchange8: case Builtin::BI_InterlockedCompareExchange16: case Builtin::BI_InterlockedCompareExchange: @@ -10183,6 +10201,8 @@ CodeGenFunction::getSVEType(const SVETypeFlags &TypeFlags) { case SVETypeFlags::EltTyInt64: return llvm::ScalableVectorType::get(Builder.getInt64Ty(), 2); + case SVETypeFlags::EltTyMFloat8: + return llvm::ScalableVectorType::get(Builder.getInt8Ty(), 16); case SVETypeFlags::EltTyFloat16: return llvm::ScalableVectorType::get(Builder.getHalfTy(), 8); case SVETypeFlags::EltTyBFloat16: @@ -10628,7 +10648,7 @@ Value *CodeGenFunction::EmitSMELd1St1(const SVETypeFlags &TypeFlags, NewOps.push_back(Ops[2]); llvm::Value *BasePtr = Ops[3]; - + llvm::Value *RealSlice = Ops[1]; // If the intrinsic contains the vnum parameter, multiply it with the vector // size in bytes. if (Ops.size() == 5) { @@ -10640,10 +10660,13 @@ Value *CodeGenFunction::EmitSMELd1St1(const SVETypeFlags &TypeFlags, Builder.CreateMul(StreamingVectorLengthCall, Ops[4], "mulvl"); // The type of the ptr parameter is void *, so use Int8Ty here. BasePtr = Builder.CreateGEP(Int8Ty, Ops[3], Mulvl); + RealSlice = Builder.CreateZExt(RealSlice, Int64Ty); + RealSlice = Builder.CreateAdd(RealSlice, Ops[4]); + RealSlice = Builder.CreateTrunc(RealSlice, Int32Ty); } NewOps.push_back(BasePtr); NewOps.push_back(Ops[0]); - NewOps.push_back(Ops[1]); + NewOps.push_back(RealSlice); Function *F = CGM.getIntrinsic(IntID); return Builder.CreateCall(F, NewOps); } @@ -11234,6 +11257,10 @@ Value *CodeGenFunction::EmitAArch64SMEBuiltinExpr(unsigned BuiltinID, BuiltinID == SME::BI__builtin_sme_svstr_za) return EmitSMELdrStr(TypeFlags, Ops, Builtin->LLVMIntrinsic); + // Emit set FPMR for intrinsics that require it + if (TypeFlags.setsFPMR()) + Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_set_fpmr), + Ops.pop_back_val()); // Handle builtins which require their multi-vector operands to be swapped swapCommutativeSMEOperands(BuiltinID, Ops); @@ -11836,21 +11863,18 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, BuiltinID == AArch64::BI__writex18word || BuiltinID == AArch64::BI__writex18dword || BuiltinID == AArch64::BI__writex18qword) { + // Process the args first + Value *OffsetArg = EmitScalarExpr(E->getArg(0)); + Value *DataArg = EmitScalarExpr(E->getArg(1)); + // Read x18 as i8* - LLVMContext &Context = CGM.getLLVMContext(); - llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")}; - llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops); - llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName); - llvm::Function *F = - CGM.getIntrinsic(llvm::Intrinsic::read_register, {Int64Ty}); - llvm::Value *X18 = Builder.CreateCall(F, Metadata); - X18 = Builder.CreateIntToPtr(X18, Int8PtrTy); + llvm::Value *X18 = readX18AsPtr(*this); // Store val at x18 + offset - Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)), Int64Ty); + Value *Offset = Builder.CreateZExt(OffsetArg, Int64Ty); Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset); - Value *Val = EmitScalarExpr(E->getArg(1)); - StoreInst *Store = Builder.CreateAlignedStore(Val, Ptr, CharUnits::One()); + StoreInst *Store = + Builder.CreateAlignedStore(DataArg, Ptr, CharUnits::One()); return Store; } @@ -11858,25 +11882,74 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, BuiltinID == AArch64::BI__readx18word || BuiltinID == AArch64::BI__readx18dword || BuiltinID == AArch64::BI__readx18qword) { - llvm::Type *IntTy = ConvertType(E->getType()); + // Process the args first + Value *OffsetArg = EmitScalarExpr(E->getArg(0)); // Read x18 as i8* - LLVMContext &Context = CGM.getLLVMContext(); - llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")}; - llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops); - llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName); - llvm::Function *F = - CGM.getIntrinsic(llvm::Intrinsic::read_register, {Int64Ty}); - llvm::Value *X18 = Builder.CreateCall(F, Metadata); - X18 = Builder.CreateIntToPtr(X18, Int8PtrTy); + llvm::Value *X18 = readX18AsPtr(*this); // Load x18 + offset - Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)), Int64Ty); + Value *Offset = Builder.CreateZExt(OffsetArg, Int64Ty); Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset); + llvm::Type *IntTy = ConvertType(E->getType()); LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One()); return Load; } + if (BuiltinID == AArch64::BI__addx18byte || + BuiltinID == AArch64::BI__addx18word || + BuiltinID == AArch64::BI__addx18dword || + BuiltinID == AArch64::BI__addx18qword || + BuiltinID == AArch64::BI__incx18byte || + BuiltinID == AArch64::BI__incx18word || + BuiltinID == AArch64::BI__incx18dword || + BuiltinID == AArch64::BI__incx18qword) { + llvm::Type *IntTy; + bool isIncrement; + switch (BuiltinID) { + case AArch64::BI__incx18byte: + IntTy = Int8Ty; + isIncrement = true; + break; + case AArch64::BI__incx18word: + IntTy = Int16Ty; + isIncrement = true; + break; + case AArch64::BI__incx18dword: + IntTy = Int32Ty; + isIncrement = true; + break; + case AArch64::BI__incx18qword: + IntTy = Int64Ty; + isIncrement = true; + break; + default: + IntTy = ConvertType(E->getArg(1)->getType()); + isIncrement = false; + break; + } + // Process the args first + Value *OffsetArg = EmitScalarExpr(E->getArg(0)); + Value *ValToAdd = + isIncrement ? ConstantInt::get(IntTy, 1) : EmitScalarExpr(E->getArg(1)); + + // Read x18 as i8* + llvm::Value *X18 = readX18AsPtr(*this); + + // Load x18 + offset + Value *Offset = Builder.CreateZExt(OffsetArg, Int64Ty); + Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset); + LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One()); + + // Add values + Value *AddResult = Builder.CreateAdd(Load, ValToAdd); + + // Store val at x18 + offset + StoreInst *Store = + Builder.CreateAlignedStore(AddResult, Ptr, CharUnits::One()); + return Store; + } + if (BuiltinID == AArch64::BI_CopyDoubleFromInt64 || BuiltinID == AArch64::BI_CopyFloatFromInt32 || BuiltinID == AArch64::BI_CopyInt32FromFloat || diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 7c8d962fa5a92..3cefc9da66ddb 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4529,7 +4529,7 @@ void CodeGenFunction::EmitCallArgs( ArgTypes.assign(MD->param_type_begin() + ParamsToSkip, MD->param_type_end()); } else { - const auto *FPT = Prototype.P.get(); + const auto *FPT = cast(Prototype.P); IsVariadic = FPT->isVariadic(); ExplicitCC = FPT->getExtInfo().getCC(); ArgTypes.assign(FPT->param_type_begin() + ParamsToSkip, diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 4ae8a2b22b1bb..bbf68a4c66192 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2102,7 +2102,8 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { Expr *InitVector = E->getInit(0); // Initialize from another scalable vector of the same type. - if (InitVector->getType() == E->getType()) + if (InitVector->getType().getCanonicalType() == + E->getType().getCanonicalType()) return Visit(InitVector); } diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp index cdff7e50c4ee7..448571221ef81 100644 --- a/clang/lib/CodeGen/CGLoopInfo.cpp +++ b/clang/lib/CodeGen/CGLoopInfo.cpp @@ -811,7 +811,7 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx, // Identify loop attribute 'code_align' from Attrs. // For attribute code_align: // n - 'llvm.loop.align i32 n' metadata will be emitted. - if (const auto *CodeAlign = getSpecificAttr(Attrs)) { + if (const auto *CodeAlign = getSpecificAttr(Attrs)) { const auto *CE = cast(CodeAlign->getAlignment()); llvm::APSInt ArgVal = CE->getResultAsAPSInt(); setCodeAlign(ArgVal.getSExtValue()); diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 6a5860242035b..2deb91f27e37b 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -7770,7 +7770,7 @@ class MappableExprsHandler { if (const auto *Base = Data.dyn_cast()) getPlainLayout(Base, Layout, /*AsBase=*/true); else - Layout.push_back(Data.get()); + Layout.push_back(cast(Data)); } } @@ -8333,9 +8333,9 @@ class MappableExprsHandler { MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder, const llvm::DenseSet> &SkipVarSet = llvm::DenseSet>()) const { - assert(CurDir.is() && + assert(isa(CurDir) && "Expect a executable directive"); - const auto *CurExecDir = CurDir.get(); + const auto *CurExecDir = cast(CurDir); generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder, SkipVarSet); } @@ -8345,9 +8345,9 @@ class MappableExprsHandler { /// in \a CombinedInfo). void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder) const { - assert(CurDir.is() && + assert(isa(CurDir) && "Expect a declare mapper directive"); - const auto *CurMapperDir = CurDir.get(); + const auto *CurMapperDir = cast(CurDir); generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo, OMPBuilder); } @@ -8519,9 +8519,9 @@ class MappableExprsHandler { DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom, Unknown, /*IsImpicit = */ true, nullptr, nullptr); - assert(CurDir.is() && + assert(isa(CurDir) && "Expect a executable directive"); - const auto *CurExecDir = CurDir.get(); + const auto *CurExecDir = cast(CurDir); bool HasMapBasePtr = false; bool HasMapArraySec = false; for (const auto *C : CurExecDir->getClausesOfKind()) { diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index f8138e9cee250..2bc10cdd2d344 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -899,6 +899,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, Fn->addFnAttr("ptrauth-auth-traps"); if (CodeGenOpts.PointerAuth.IndirectGotos) Fn->addFnAttr("ptrauth-indirect-gotos"); + if (CodeGenOpts.PointerAuth.AArch64JumpTableHardening) + Fn->addFnAttr("aarch64-jump-table-hardening"); // Apply xray attributes to the function (as a string, for now) bool AlwaysXRayAttr = false; diff --git a/clang/lib/CodeGen/ConstantInitBuilder.cpp b/clang/lib/CodeGen/ConstantInitBuilder.cpp index 549d5dd66b123..ddbf3ef743370 100644 --- a/clang/lib/CodeGen/ConstantInitBuilder.cpp +++ b/clang/lib/CodeGen/ConstantInitBuilder.cpp @@ -20,10 +20,10 @@ using namespace CodeGen; llvm::Type *ConstantInitFuture::getType() const { assert(Data && "dereferencing null future"); - if (Data.is()) { - return Data.get()->getType(); + if (const auto *C = dyn_cast(Data)) { + return C->getType(); } else { - return Data.get()->Buffer[0]->getType(); + return cast(Data)->Buffer[0]->getType(); } } @@ -37,10 +37,10 @@ void ConstantInitFuture::abandon() { void ConstantInitFuture::installInGlobal(llvm::GlobalVariable *GV) { assert(Data && "installing null future"); - if (Data.is()) { - GV->setInitializer(Data.get()); + if (auto *C = dyn_cast(Data)) { + GV->setInitializer(C); } else { - auto &builder = *Data.get(); + auto &builder = *cast(Data); assert(builder.Buffer.size() == 1); builder.setGlobalInitializer(GV, builder.Buffer[0]); builder.Buffer.clear(); diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 7de8341b8d2d6..6ba13d7341169 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1039,34 +1039,59 @@ bool Driver::readConfigFile(StringRef FileName, } // Try reading the given file. - SmallVector NewCfgArgs; - if (llvm::Error Err = ExpCtx.readConfigFile(FileName, NewCfgArgs)) { + SmallVector NewCfgFileArgs; + if (llvm::Error Err = ExpCtx.readConfigFile(FileName, NewCfgFileArgs)) { Diag(diag::err_drv_cannot_read_config_file) << FileName << toString(std::move(Err)); return true; } + // Populate head and tail lists. The tail list is used only when linking. + SmallVector NewCfgHeadArgs, NewCfgTailArgs; + for (const char *Opt : NewCfgFileArgs) { + // An $-prefixed option should go to the tail list. + if (Opt[0] == '$' && Opt[1]) + NewCfgTailArgs.push_back(Opt + 1); + else + NewCfgHeadArgs.push_back(Opt); + } + // Read options from config file. llvm::SmallString<128> CfgFileName(FileName); llvm::sys::path::native(CfgFileName); - bool ContainErrors; - auto NewOptions = std::make_unique( - ParseArgStrings(NewCfgArgs, /*UseDriverMode=*/true, ContainErrors)); + bool ContainErrors = false; + auto NewHeadOptions = std::make_unique( + ParseArgStrings(NewCfgHeadArgs, /*UseDriverMode=*/true, ContainErrors)); + if (ContainErrors) + return true; + auto NewTailOptions = std::make_unique( + ParseArgStrings(NewCfgTailArgs, /*UseDriverMode=*/true, ContainErrors)); if (ContainErrors) return true; // Claim all arguments that come from a configuration file so that the driver // does not warn on any that is unused. - for (Arg *A : *NewOptions) + for (Arg *A : *NewHeadOptions) + A->claim(); + for (Arg *A : *NewTailOptions) A->claim(); - if (!CfgOptions) - CfgOptions = std::move(NewOptions); + if (!CfgOptionsHead) + CfgOptionsHead = std::move(NewHeadOptions); + else { + // If this is a subsequent config file, append options to the previous one. + for (auto *Opt : *NewHeadOptions) + appendOneArg(*CfgOptionsHead, Opt); + } + + if (!CfgOptionsTail) + CfgOptionsTail = std::move(NewTailOptions); else { // If this is a subsequent config file, append options to the previous one. - for (auto *Opt : *NewOptions) - appendOneArg(*CfgOptions, Opt); + for (auto *Opt : *NewTailOptions) + appendOneArg(*CfgOptionsTail, Opt); } + ConfigFiles.push_back(std::string(CfgFileName)); return false; } @@ -1243,13 +1268,14 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { // Try parsing configuration file. if (!ContainsError) ContainsError = loadConfigFiles(); - bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr); + bool HasConfigFileHead = !ContainsError && CfgOptionsHead; + bool HasConfigFileTail = !ContainsError && CfgOptionsTail; // All arguments, from both config file and command line. - InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions) - : std::move(*CLOptions)); + InputArgList Args = + HasConfigFileHead ? std::move(*CfgOptionsHead) : std::move(*CLOptions); - if (HasConfigFile) + if (HasConfigFileHead) for (auto *Opt : *CLOptions) if (!Opt->getOption().matches(options::OPT_config)) appendOneArg(Args, Opt); @@ -1540,6 +1566,15 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { // Construct the list of inputs. InputList Inputs; BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs); + if (HasConfigFileTail && Inputs.size()) { + Arg *FinalPhaseArg; + if (getFinalPhase(*TranslatedArgs, &FinalPhaseArg) == phases::Link) { + DerivedArgList TranslatedLinkerIns(*CfgOptionsTail); + for (Arg *A : *CfgOptionsTail) + TranslatedLinkerIns.append(A); + BuildInputs(C->getDefaultToolChain(), TranslatedLinkerIns, Inputs); + } + } // Populate the tool chains for the offloading devices, if any. CreateOffloadingDeviceToolChains(*C, Inputs); @@ -4515,7 +4550,13 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args, ToolChain::getOpenMPTriple(Arg->getValue(0)) == TC->getTriple()) { Arg->claim(); unsigned Index = Args.getBaseArgs().MakeIndex(Arg->getValue(1)); + unsigned Prev = Index; ExtractedArg = getOpts().ParseOneArg(Args, Index); + if (!ExtractedArg || Index > Prev + 1) { + TC->getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args) + << Arg->getAsString(Args); + continue; + } Arg = ExtractedArg.get(); } diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 0d426a467e9a3..9f174fbda398b 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1596,8 +1596,10 @@ llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs( Prev = Index; std::unique_ptr XOpenMPTargetArg(Opts.ParseOneArg(Args, Index)); if (!XOpenMPTargetArg || Index > Prev + 1) { - getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args) - << A->getAsString(Args); + if (!A->isClaimed()) { + getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args) + << A->getAsString(Args); + } continue; } if (XOpenMPTargetNoTriple && XOpenMPTargetArg && diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp index e6ee2317a160c..b8181ce6dc012 100644 --- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -52,6 +52,26 @@ bool arm::isARMAProfile(const llvm::Triple &Triple) { return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::A; } +/// Is the triple {arm,armeb,thumb,thumbeb}-none-none-{eabi,eabihf} ? +bool arm::isARMEABIBareMetal(const llvm::Triple &Triple) { + auto arch = Triple.getArch(); + if (arch != llvm::Triple::arm && arch != llvm::Triple::thumb && + arch != llvm::Triple::armeb && arch != llvm::Triple::thumbeb) + return false; + + if (Triple.getVendor() != llvm::Triple::UnknownVendor) + return false; + + if (Triple.getOS() != llvm::Triple::UnknownOS) + return false; + + if (Triple.getEnvironment() != llvm::Triple::EABI && + Triple.getEnvironment() != llvm::Triple::EABIHF) + return false; + + return true; +} + // Get Arch/CPU from args. void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch, llvm::StringRef &CPU, bool FromAs) { diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.h b/clang/lib/Driver/ToolChains/Arch/ARM.h index fa62ac89e3a13..a23a8793a89e2 100644 --- a/clang/lib/Driver/ToolChains/Arch/ARM.h +++ b/clang/lib/Driver/ToolChains/Arch/ARM.h @@ -75,6 +75,7 @@ int getARMSubArchVersionNumber(const llvm::Triple &Triple); bool isARMMProfile(const llvm::Triple &Triple); bool isARMAProfile(const llvm::Triple &Triple); bool isARMBigEndian(const llvm::Triple &Triple, const llvm::opt::ArgList &Args); +bool isARMEABIBareMetal(const llvm::Triple &Triple); } // end namespace arm } // end namespace tools diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp index f9a73f60973e4..eecaaa9a42930 100644 --- a/clang/lib/Driver/ToolChains/BareMetal.cpp +++ b/clang/lib/Driver/ToolChains/BareMetal.cpp @@ -128,27 +128,6 @@ BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple, } } -/// Is the triple {arm,armeb,thumb,thumbeb}-none-none-{eabi,eabihf} ? -static bool isARMBareMetal(const llvm::Triple &Triple) { - if (Triple.getArch() != llvm::Triple::arm && - Triple.getArch() != llvm::Triple::thumb && - Triple.getArch() != llvm::Triple::armeb && - Triple.getArch() != llvm::Triple::thumbeb) - return false; - - if (Triple.getVendor() != llvm::Triple::UnknownVendor) - return false; - - if (Triple.getOS() != llvm::Triple::UnknownOS) - return false; - - if (Triple.getEnvironment() != llvm::Triple::EABI && - Triple.getEnvironment() != llvm::Triple::EABIHF) - return false; - - return true; -} - /// Is the triple {aarch64.aarch64_be}-none-elf? static bool isAArch64BareMetal(const llvm::Triple &Triple) { if (Triple.getArch() != llvm::Triple::aarch64 && @@ -267,7 +246,7 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple, } bool BareMetal::handlesTarget(const llvm::Triple &Triple) { - return isARMBareMetal(Triple) || isAArch64BareMetal(Triple) || + return arm::isARMEABIBareMetal(Triple) || isAArch64BareMetal(Triple) || isRISCVBareMetal(Triple) || isPPCBareMetal(Triple); } @@ -414,38 +393,6 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, } } -void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { - switch (GetCXXStdlibType(Args)) { - case ToolChain::CST_Libcxx: - CmdArgs.push_back("-lc++"); - if (Args.hasArg(options::OPT_fexperimental_library)) - CmdArgs.push_back("-lc++experimental"); - CmdArgs.push_back("-lc++abi"); - break; - case ToolChain::CST_Libstdcxx: - CmdArgs.push_back("-lstdc++"); - CmdArgs.push_back("-lsupc++"); - break; - } - CmdArgs.push_back("-lunwind"); -} - -void BareMetal::AddLinkRuntimeLib(const ArgList &Args, - ArgStringList &CmdArgs) const { - ToolChain::RuntimeLibType RLT = GetRuntimeLibType(Args); - switch (RLT) { - case ToolChain::RLT_CompilerRT: { - CmdArgs.push_back(getCompilerRTArgString(Args, "builtins")); - return; - } - case ToolChain::RLT_Libgcc: - CmdArgs.push_back("-lgcc"); - return; - } - llvm_unreachable("Unhandled RuntimeLibType."); -} - void baremetal::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -532,14 +479,21 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, for (const auto &LibPath : TC.getLibraryPaths()) CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-L", LibPath))); - if (TC.ShouldLinkCXXStdlib(Args)) + if (TC.ShouldLinkCXXStdlib(Args)) { + bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && + !Args.hasArg(options::OPT_static); + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bstatic"); TC.AddCXXStdlibLibArgs(Args, CmdArgs); + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bdynamic"); + CmdArgs.push_back("-lm"); + } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { - CmdArgs.push_back("-lc"); - CmdArgs.push_back("-lm"); + AddRunTimeLibs(TC, D, CmdArgs, Args); - TC.AddLinkRuntimeLib(Args, CmdArgs); + CmdArgs.push_back("-lc"); } if (D.isUsingLTO()) { @@ -561,7 +515,7 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, // The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf // and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and // arm*-*-*bsd). - if (isARMBareMetal(TC.getTriple())) + if (arm::isARMEABIBareMetal(TC.getTriple())) CmdArgs.push_back("--target2=rel"); CmdArgs.push_back("-o"); diff --git a/clang/lib/Driver/ToolChains/BareMetal.h b/clang/lib/Driver/ToolChains/BareMetal.h index b385c8cf76aab..483b5efab5e6e 100644 --- a/clang/lib/Driver/ToolChains/BareMetal.h +++ b/clang/lib/Driver/ToolChains/BareMetal.h @@ -67,10 +67,6 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain { void AddClangCXXStdlibIncludeArgs( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; - void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const override; - void AddLinkRuntimeLib(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const; std::string computeSysRoot() const override; SanitizerMask getSupportedSanitizers() const override; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 99a092d83d531..7ef55a33547c5 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1876,6 +1876,8 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_init_fini_address_discrimination, options::OPT_fno_ptrauth_init_fini_address_discrimination); + Args.addOptInFlag(CmdArgs, options::OPT_faarch64_jump_table_hardening, + options::OPT_fno_aarch64_jump_table_hardening); } void Clang::AddLoongArchTargetArgs(const ArgList &Args, @@ -5937,9 +5939,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption, options::OPT_fno_strict_aliasing, !IsWindowsMSVC)) CmdArgs.push_back("-relaxed-aliasing"); - if (Args.hasFlag(options::OPT_fpointer_tbaa, options::OPT_fno_pointer_tbaa, + if (Args.hasFlag(options::OPT_fno_pointer_tbaa, options::OPT_fpointer_tbaa, false)) - CmdArgs.push_back("-pointer-tbaa"); + CmdArgs.push_back("-no-pointer-tbaa"); if (!Args.hasFlag(options::OPT_fstruct_path_tbaa, options::OPT_fno_struct_path_tbaa, true)) CmdArgs.push_back("-no-struct-path-tbaa"); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 8d977149e6248..03dbdc27975b4 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -19,6 +19,7 @@ #include "Arch/SystemZ.h" #include "Arch/VE.h" #include "Arch/X86.h" +#include "BareMetal.h" #include "HIPAMD.h" #include "Hexagon.h" #include "MSP430.h" @@ -151,6 +152,9 @@ static bool useFramePointerForTargetByDefault(const llvm::opt::ArgList &Args, } } + if (arm::isARMEABIBareMetal(Triple)) + return false; + return true; } @@ -1406,7 +1410,7 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC, // libresolv.a, even if exists, is an empty archive to satisfy POSIX -lresolv // requirement. if (TC.getTriple().isOSLinux() && !TC.getTriple().isAndroid() && - !TC.getTriple().isMusl()) + !TC.getTriple().isMusl() && TC.getSanitizerArgs(Args).needsMsanRt()) CmdArgs.push_back("-lresolv"); } diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 72c0787d7df99..9186647b09c88 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -213,6 +213,14 @@ void Flang::AddLoongArch64TargetArgs(const ArgList &Args, D.Diag(diag::err_drv_argument_not_allowed_with) << "-mabi" << V; } } + + if (const Arg *A = Args.getLastArg(options::OPT_mannotate_tablejump, + options::OPT_mno_annotate_tablejump)) { + if (A->getOption().matches(options::OPT_mannotate_tablejump)) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-loongarch-annotate-tablejump"); + } + } } void Flang::AddPPCTargetArgs(const ArgList &Args, diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp index 72accbff4a3bf..c2badc80a7b45 100644 --- a/clang/lib/Driver/ToolChains/Fuchsia.cpp +++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -156,6 +156,12 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); + // Sample these options first so they are claimed even under -nostdlib et al. + bool NoLibc = Args.hasArg(options::OPT_nolibc); + bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && + !Args.hasArg(options::OPT_static); + bool Pthreads = Args.hasArg(options::OPT_pthread, options::OPT_pthreads); + bool SplitStack = Args.hasArg(options::OPT_fsplit_stack); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, options::OPT_r)) { if (Args.hasArg(options::OPT_static)) @@ -163,8 +169,6 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) { - bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && - !Args.hasArg(options::OPT_static); CmdArgs.push_back("--push-state"); CmdArgs.push_back("--as-needed"); if (OnlyLibstdcxxStatic) @@ -188,14 +192,13 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddRunTimeLibs(ToolChain, D, CmdArgs, Args); - if (Args.hasArg(options::OPT_pthread) || - Args.hasArg(options::OPT_pthreads)) + if (Pthreads) CmdArgs.push_back("-lpthread"); - if (Args.hasArg(options::OPT_fsplit_stack)) + if (SplitStack) CmdArgs.push_back("--wrap=pthread_create"); - if (!Args.hasArg(options::OPT_nolibc)) + if (!NoLibc) CmdArgs.push_back("-lc"); } @@ -229,7 +232,7 @@ void fuchsia::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA, for (const auto &II : Inputs) { if (II.isFilename()) { - CmdArgs.push_back(II.getFilename()); + CmdArgs.push_back(II.getFilename()); } } @@ -343,16 +346,14 @@ std::string Fuchsia::ComputeEffectiveClangTriple(const ArgList &Args, return Triple.str(); } -Tool *Fuchsia::buildLinker() const { - return new tools::fuchsia::Linker(*this); -} +Tool *Fuchsia::buildLinker() const { return new tools::fuchsia::Linker(*this); } Tool *Fuchsia::buildStaticLibTool() const { return new tools::fuchsia::StaticLibTool(*this); } -ToolChain::RuntimeLibType Fuchsia::GetRuntimeLibType( - const ArgList &Args) const { +ToolChain::RuntimeLibType +Fuchsia::GetRuntimeLibType(const ArgList &Args) const { if (Arg *A = Args.getLastArg(clang::driver::options::OPT_rtlib_EQ)) { StringRef Value = A->getValue(); if (Value != "compiler-rt") @@ -363,13 +364,12 @@ ToolChain::RuntimeLibType Fuchsia::GetRuntimeLibType( return ToolChain::RLT_CompilerRT; } -ToolChain::CXXStdlibType -Fuchsia::GetCXXStdlibType(const ArgList &Args) const { +ToolChain::CXXStdlibType Fuchsia::GetCXXStdlibType(const ArgList &Args) const { if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { StringRef Value = A->getValue(); if (Value != "libc++") getDriver().Diag(diag::err_drv_invalid_stdlib_name) - << A->getAsString(Args); + << A->getAsString(Args); } return ToolChain::CST_Libcxx; diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index d1cb625613415..46962e88d4550 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -256,6 +256,24 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) ExtraOpts.push_back("-z"); ExtraOpts.push_back("max-page-size=16384"); } + if (Triple.isAndroidVersionLT(29)) { + // https://github.com/android/ndk/issues/1196 + // The unwinder used by the crash handler on versions of Android prior to + // API 29 did not correctly handle binaries built with rosegment, which is + // enabled by default for LLD. Android only supports LLD, so it's not an + // issue that this flag is not accepted by other linkers. + ExtraOpts.push_back("--no-rosegment"); + } + if (!Triple.isAndroidVersionLT(28)) { + // Android supports relr packing starting with API 28 and had its own + // flavor (--pack-dyn-relocs=android) starting in API 23. + // TODO: It's possible to use both with --pack-dyn-relocs=android+relr, + // but we need to gather some data on the impact of that form before we + // can know if it's a good default. + // On the other hand, relr should always be an improvement. + ExtraOpts.push_back("--use-android-relr-tags"); + ExtraOpts.push_back("--pack-dyn-relocs=relr"); + } } if (GCCInstallation.getParentLibPath().contains("opt/rh/")) diff --git a/clang/lib/Format/CMakeLists.txt b/clang/lib/Format/CMakeLists.txt index ff987cc608fb8..9f4939824fdb8 100644 --- a/clang/lib/Format/CMakeLists.txt +++ b/clang/lib/Format/CMakeLists.txt @@ -41,15 +41,46 @@ file(GLOB_RECURSE files set(check_format_depends) set(i 0) -foreach (file IN LISTS files) - add_custom_command(OUTPUT clang-format-check-format${i} +foreach(file IN LISTS files) + add_custom_command(OUTPUT check_format_depend_${i} COMMAND clang-format ${file} | diff -u ${file} - VERBATIM - COMMENT "Checking format of ${file}..." + COMMENT "Checking format of ${file}" ) - list(APPEND check_format_depends clang-format-check-format${i}) - + list(APPEND check_format_depends check_format_depend_${i}) math(EXPR i ${i}+1) -endforeach () - +endforeach() add_custom_target(clang-format-check-format DEPENDS ${check_format_depends}) + +set(docs_tools_dir ${CLANG_SOURCE_DIR}/docs/tools) + +set(format_style_depend ${CMAKE_CURRENT_BINARY_DIR}/format_style_depend) +set(dump_style dump_format_style.py) +set(style_options_rst ${CLANG_SOURCE_DIR}/docs/ClangFormatStyleOptions.rst) +add_custom_command(OUTPUT ${format_style_depend} + COMMAND ${Python3_EXECUTABLE} ${dump_style} && touch ${format_style_depend} + WORKING_DIRECTORY ${docs_tools_dir} + VERBATIM + COMMENT "Updating ${style_options_rst}" + DEPENDS ${CLANG_SOURCE_DIR}/include/clang/Format/Format.h + ${CLANG_SOURCE_DIR}/include/clang/Tooling/Inclusions/IncludeStyle.h + ${style_options_rst} + ${docs_tools_dir}/plurals.txt + ${docs_tools_dir}/${dump_style} + ) +add_custom_target(clang-format-style DEPENDS ${format_style_depend}) + +set(format_help_depend ${CMAKE_CURRENT_BINARY_DIR}/format_help_depend) +set(dump_help dump_format_help.py) +set(clang_format_rst ${CLANG_SOURCE_DIR}/docs/ClangFormat.rst) +add_custom_command(OUTPUT ${format_help_depend} + COMMAND ${Python3_EXECUTABLE} ${dump_help} -d ${CMAKE_BINARY_DIR}/bin && + touch ${format_help_depend} + WORKING_DIRECTORY ${docs_tools_dir} + VERBATIM + COMMENT "Updating ${clang_format_rst}" + DEPENDS clang-format + ${clang_format_rst} + ${docs_tools_dir}/${dump_help} + ) +add_custom_target(clang-format-help DEPENDS ${format_help_depend}) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index bc5239209f3aa..49482973223c6 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3901,6 +3901,11 @@ bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const { } void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { + if (Line.Computed) + return; + + Line.Computed = true; + for (AnnotatedLine *ChildLine : Line.Children) calculateFormattingInformation(*ChildLine); diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index 5a02030e5ba7f..9117ca3f9fb7b 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -182,6 +182,9 @@ class AnnotatedLine { /// \c True if this line contains a macro call for which an expansion exists. bool ContainsMacroCall = false; + /// \c True if calculateFormattingInformation() has been called on this line. + bool Computed = false; + /// \c True if this line should be formatted, i.e. intersects directly or /// indirectly with one of the input ranges. bool Affected; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 3dd94c31b2bc7..98136b7a455d9 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1511,6 +1511,7 @@ void CompilerInvocation::setDefaultPointerAuthOptions( Opts.ReturnAddresses = LangOpts.PointerAuthReturns; Opts.AuthTraps = LangOpts.PointerAuthAuthTraps; Opts.IndirectGotos = LangOpts.PointerAuthIndirectGotos; + Opts.AArch64JumpTableHardening = LangOpts.AArch64JumpTableHardening; } static void parsePointerAuthOptions(PointerAuthOptions &Opts, @@ -1518,7 +1519,8 @@ static void parsePointerAuthOptions(PointerAuthOptions &Opts, const llvm::Triple &Triple, DiagnosticsEngine &Diags) { if (!LangOpts.PointerAuthCalls && !LangOpts.PointerAuthReturns && - !LangOpts.PointerAuthAuthTraps && !LangOpts.PointerAuthIndirectGotos) + !LangOpts.PointerAuthAuthTraps && !LangOpts.PointerAuthIndirectGotos && + !LangOpts.AArch64JumpTableHardening) return; CompilerInvocation::setDefaultPointerAuthOptions(Opts, LangOpts, Triple); @@ -3454,6 +3456,8 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts, GenerateArg(Consumer, OPT_fptrauth_init_fini_address_discrimination); if (Opts.PointerAuthELFGOT) GenerateArg(Consumer, OPT_fptrauth_elf_got); + if (Opts.AArch64JumpTableHardening) + GenerateArg(Consumer, OPT_faarch64_jump_table_hardening); } static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, @@ -3475,6 +3479,8 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, Opts.PointerAuthInitFiniAddressDiscrimination = Args.hasArg(OPT_fptrauth_init_fini_address_discrimination); Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got); + Opts.AArch64JumpTableHardening = + Args.hasArg(OPT_faarch64_jump_table_hardening); } /// Check if input file kind and language standard are compatible. diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 9b611bfcc9e63..e20feedb840b5 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -587,7 +587,7 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, if (LangOpts.getSYCLVersion() == LangOptions::SYCL_2017) Builder.defineMacro("CL_SYCL_LANGUAGE_VERSION", "121"); else if (LangOpts.getSYCLVersion() == LangOptions::SYCL_2020) - Builder.defineMacro("SYCL_LANGUAGE_VERSION", "202001"); + Builder.defineMacro("SYCL_LANGUAGE_VERSION", "202012L"); } // Not "standard" per se, but available even with the -undef flag. diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h index 8e2b95b52442d..e8a01d1888026 100644 --- a/clang/lib/Headers/intrin.h +++ b/clang/lib/Headers/intrin.h @@ -396,6 +396,16 @@ unsigned short __readx18word(unsigned long offset); unsigned long __readx18dword(unsigned long offset); unsigned __int64 __readx18qword(unsigned long offset); +void __addx18byte(unsigned long offset, unsigned char data); +void __addx18word(unsigned long offset, unsigned short data); +void __addx18dword(unsigned long offset, unsigned long data); +void __addx18qword(unsigned long offset, unsigned __int64 data); + +void __incx18byte(unsigned long offset); +void __incx18word(unsigned long offset); +void __incx18dword(unsigned long offset); +void __incx18qword(unsigned long offset); + double _CopyDoubleFromInt64(__int64); float _CopyFloatFromInt32(__int32); __int32 _CopyInt32FromFloat(float); diff --git a/clang/lib/Headers/intrin0.h b/clang/lib/Headers/intrin0.h index 6b01f3808652a..2bca9fc877e9c 100644 --- a/clang/lib/Headers/intrin0.h +++ b/clang/lib/Headers/intrin0.h @@ -207,6 +207,9 @@ long _InterlockedExchange_rel(long volatile *_Target, long _Value); __int64 _InterlockedExchange64_acq(__int64 volatile *_Target, __int64 _Value); __int64 _InterlockedExchange64_nf(__int64 volatile *_Target, __int64 _Value); __int64 _InterlockedExchange64_rel(__int64 volatile *_Target, __int64 _Value); +void *_InterlockedExchangePointer_acq(void *volatile *_Target, void *_Value); +void *_InterlockedExchangePointer_nf(void *volatile *_Target, void *_Value); +void *_InterlockedExchangePointer_rel(void *volatile *_Target, void *_Value); /*----------------------------------------------------------------------------*\ |* Interlocked Compare Exchange @@ -237,6 +240,12 @@ __int64 _InterlockedCompareExchange64_nf(__int64 volatile *_Destination, __int64 _InterlockedCompareExchange64_rel(__int64 volatile *_Destination, __int64 _Exchange, __int64 _Comparand); +void *_InterlockedCompareExchangePointer_acq(void *volatile *_Destination, + void *_Exchange, void *_Comparand); +void *_InterlockedCompareExchangePointer_nf(void *volatile *_Destination, + void *_Exchange, void *_Comparand); +void *_InterlockedCompareExchangePointer_rel(void *volatile *_Destination, + void *_Exchange, void *_Comparand); #endif #ifdef __cplusplus diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 887b494ff98f1..fa4c1439c9261 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -200,7 +200,6 @@ IncrementalCompilerBuilder::CreateCpp() { #ifdef __EMSCRIPTEN__ Argv.push_back("-target"); Argv.push_back("wasm32-unknown-emscripten"); - Argv.push_back("-shared"); Argv.push_back("-fvisibility=default"); #endif Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end()); diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index e58c8bc72ae5b..72364500a48f9 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -527,7 +527,7 @@ bool Lexer::getRawToken(SourceLocation Loc, Token &Result, const char *StrData = Buffer.data()+LocInfo.second; - if (!IgnoreWhiteSpace && isWhitespace(StrData[0])) + if (!IgnoreWhiteSpace && isWhitespace(SkipEscapedNewLines(StrData)[0])) return true; // Create a lexer starting at the beginning of this token. diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 736484ded8383..8dd72db8f5b4a 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1199,7 +1199,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, // If the token is not annotated, then it might be an expression pack // indexing if (!TryAnnotateTypeOrScopeToken() && - Tok.is(tok::annot_pack_indexing_type)) + Tok.isOneOf(tok::annot_pack_indexing_type, tok::annot_cxxscope)) return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast, isVectorLiteral, NotPrimaryExpression); } diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index f849e841de190..8e57123c503cb 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -35,14 +35,17 @@ namespace { struct TemplateParameterListBuilder; -struct BuiltinTypeDeclBuilder { - Sema &SemaRef; - CXXRecordDecl *Record = nullptr; +class BuiltinTypeDeclBuilder { ClassTemplateDecl *Template = nullptr; ClassTemplateDecl *PrevTemplate = nullptr; NamespaceDecl *HLSLNamespace = nullptr; llvm::StringMap Fields; +public: + Sema &SemaRef; + CXXRecordDecl *Record = nullptr; + friend struct TemplateParameterListBuilder; + BuiltinTypeDeclBuilder(Sema &SemaRef, CXXRecordDecl *R) : SemaRef(SemaRef), Record(R) { Record->startDefinition(); @@ -51,7 +54,7 @@ struct BuiltinTypeDeclBuilder { BuiltinTypeDeclBuilder(Sema &SemaRef, NamespaceDecl *Namespace, StringRef Name) - : SemaRef(SemaRef), HLSLNamespace(Namespace) { + : HLSLNamespace(Namespace), SemaRef(SemaRef) { ASTContext &AST = SemaRef.getASTContext(); IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier); @@ -91,6 +94,18 @@ struct BuiltinTypeDeclBuilder { HLSLNamespace->addDecl(Record); } + CXXRecordDecl *finalizeForwardDeclaration() { + // Force the QualType to be generated for the record declaration. In most + // cases this will happen naturally when something uses the type the + // QualType gets lazily created. Unfortunately, with our injected types if a + // type isn't used in a translation unit the QualType may not get + // automatically generated before a PCH is generated. To resolve this we + // just force that the QualType is generated after we create a forward + // declaration. + (void)Record->getASTContext().getRecordType(Record); + return Record; + } + BuiltinTypeDeclBuilder & addMemberVariable(StringRef Name, QualType Type, llvm::ArrayRef Attrs, AccessSpecifier Access = AccessSpecifier::AS_private) { @@ -849,7 +864,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { constructTypedBufferConceptDecl(*SemaPtr, HLSLNamespace); Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer") .addSimpleTemplateParams({"element_type"}, TypedBufferConcept) - .Record; + .finalizeForwardDeclaration(); onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, @@ -862,7 +877,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedBuffer") .addSimpleTemplateParams({"element_type"}) - .Record; + .finalizeForwardDeclaration(); onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::TypedBuffer, /*IsROV=*/true, @@ -873,7 +888,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "StructuredBuffer") .addSimpleTemplateParams({"element_type"}) - .Record; + .finalizeForwardDeclaration(); onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, ResourceKind::RawBuffer, /*IsROV=*/false, /*RawBuffer=*/true) @@ -883,7 +898,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWStructuredBuffer") .addSimpleTemplateParams({"element_type"}) - .Record; + .finalizeForwardDeclaration(); onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer, /*IsROV=*/false, /*RawBuffer=*/true) @@ -896,7 +911,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "AppendStructuredBuffer") .addSimpleTemplateParams({"element_type"}) - .Record; + .finalizeForwardDeclaration(); onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer, /*IsROV=*/false, /*RawBuffer=*/true) @@ -906,7 +921,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "ConsumeStructuredBuffer") .addSimpleTemplateParams({"element_type"}) - .Record; + .finalizeForwardDeclaration(); onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer, /*IsROV=*/false, /*RawBuffer=*/true) @@ -916,7 +931,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedStructuredBuffer") .addSimpleTemplateParams({"element_type"}) - .Record; + .finalizeForwardDeclaration(); onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer, /*IsROV=*/true, /*RawBuffer=*/true) @@ -925,6 +940,32 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { .addDecrementCounterMethod() .completeDefinition(); }); + + Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "ByteAddressBuffer") + .finalizeForwardDeclaration(); + onCompletion(Decl, [this](CXXRecordDecl *Decl) { + setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, ResourceKind::RawBuffer, + /*IsROV=*/false, + /*RawBuffer=*/true) + .completeDefinition(); + }); + Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWByteAddressBuffer") + .finalizeForwardDeclaration(); + onCompletion(Decl, [this](CXXRecordDecl *Decl) { + setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer, + /*IsROV=*/false, + /*RawBuffer=*/true) + .completeDefinition(); + }); + Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, + "RasterizerOrderedByteAddressBuffer") + .finalizeForwardDeclaration(); + onCompletion(Decl, [this](CXXRecordDecl *Decl) { + setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer, + /*IsROV=*/true, + /*RawBuffer=*/true) + .completeDefinition(); + }); } void HLSLExternalSemaSource::onCompletion(CXXRecordDecl *Record, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c4bb73b2924bc..55e891e3acf20 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -16,7 +16,6 @@ #include "clang/AST/ASTLambda.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" -#include "clang/AST/CommentDiagnostic.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" @@ -30,6 +29,7 @@ #include "clang/AST/StmtCXX.h" #include "clang/AST/Type.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/DiagnosticComment.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 7e8e321c4b90e..f7a0b3c059ec9 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7535,8 +7535,15 @@ void Sema::CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *FD) { return; } - if (DefKind.isComparison()) - UnusedPrivateFields.clear(); + if (DefKind.isComparison()) { + auto PT = FD->getParamDecl(0)->getType(); + if (const CXXRecordDecl *RD = + PT.getNonReferenceType()->getAsCXXRecordDecl()) { + for (FieldDecl *Field : RD->fields()) { + UnusedPrivateFields.remove(Field); + } + } + } if (DefKind.isSpecialMember() ? CheckExplicitlyDefaultedSpecialMember(cast(FD), diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index ecfd79a50542c..6a9f43d6f5215 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1205,15 +1205,16 @@ CanThrowResult Sema::canThrow(const Stmt *S) { if (DTy.isNull() || DTy->isDependentType()) { CT = CT_Dependent; } else { - CT = canCalleeThrow(*this, DE, DE->getOperatorDelete()); - if (const RecordType *RT = DTy->getAs()) { - const CXXRecordDecl *RD = cast(RT->getDecl()); - const CXXDestructorDecl *DD = RD->getDestructor(); - if (DD) - CT = mergeCanThrow(CT, canCalleeThrow(*this, DE, DD)); + const FunctionDecl *OperatorDelete = DE->getOperatorDelete(); + CT = canCalleeThrow(*this, DE, OperatorDelete); + if (!OperatorDelete->isDestroyingOperatorDelete()) { + if (const auto *RD = DTy->getAsCXXRecordDecl()) { + if (const CXXDestructorDecl *DD = RD->getDestructor()) + CT = mergeCanThrow(CT, canCalleeThrow(*this, DE, DD)); + } + if (CT == CT_Can) + return CT; } - if (CT == CT_Can) - return CT; } return mergeCanThrow(CT, canSubStmtsThrow(*this, DE)); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index adad14cc0f1f6..14564b99de44c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -11833,14 +11833,23 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc, AlwaysEqual, // std::strong_ordering::equal from operator<=> }; + // C++1a [array.comp]: + // Equality and relational comparisons ([expr.eq], [expr.rel]) between two + // operands of array type. // C++2a [depr.array.comp]: // Equality and relational comparisons ([expr.eq], [expr.rel]) between two // operands of array type are deprecated. - if (S.getLangOpts().CPlusPlus20 && LHSStripped->getType()->isArrayType() && + if (S.getLangOpts().CPlusPlus && LHSStripped->getType()->isArrayType() && RHSStripped->getType()->isArrayType()) { - S.Diag(Loc, diag::warn_depr_array_comparison) - << LHS->getSourceRange() << RHS->getSourceRange() - << LHSStripped->getType() << RHSStripped->getType(); + auto IsDeprArrayComparionIgnored = + S.getDiagnostics().isIgnored(diag::warn_depr_array_comparison, Loc); + auto DiagID = S.getLangOpts().CPlusPlus26 + ? diag::warn_array_comparison_cxx26 + : !S.getLangOpts().CPlusPlus20 || IsDeprArrayComparionIgnored + ? diag::warn_array_comparison + : diag::warn_depr_array_comparison; + S.Diag(Loc, DiagID) << LHS->getSourceRange() << RHS->getSourceRange() + << LHSStripped->getType() << RHSStripped->getType(); // Carry on to produce the tautological comparison warning, if this // expression is potentially-evaluated, we can resolve the array to a // non-weak declaration, and so on. diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f58c0fa21e838..caea13b192ad5 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -3747,7 +3747,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, } else if (!Pointee->isDependentType()) { // FIXME: This can result in errors if the definition was imported from a // module but is hidden. - if (!RequireCompleteType(StartLoc, Pointee, + if (Pointee->isEnumeralType() || + !RequireCompleteType(StartLoc, Pointee, LangOpts.CPlusPlus26 ? diag::err_delete_incomplete : diag::warn_delete_incomplete, diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 060df967322ac..18d58a43d265c 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -737,6 +737,26 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitNumGangsClause( return nullptr; } } + + // OpenACC 3.3 Section 2.9.2: + // An argument with no keyword or with the 'num' wkeyword is allowed only when + // the 'num_gangs' does not appear on the 'kernel' construct. + if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) { + auto GangClauses = llvm::make_filter_range( + ExistingClauses, llvm::IsaPred); + + for (auto *GC : GangClauses) { + if (cast(GC)->hasExprOfKind(OpenACCGangKind::Num)) { + SemaRef.Diag(Clause.getBeginLoc(), + diag::err_acc_num_arg_conflict_reverse) + << OpenACCClauseKind::NumGangs << OpenACCClauseKind::Gang + << /*Num argument*/ 1; + SemaRef.Diag(GC->getBeginLoc(), diag::note_acc_previous_clause_here); + return nullptr; + } + } + } + return OpenACCNumGangsClause::Create( Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs(), Clause.getEndLoc()); @@ -750,6 +770,25 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitNumWorkersClause( if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause)) return nullptr; + // OpenACC 3.3 Section 2.9.2: + // An argument is allowed only when the 'num_workers' does not appear on the + // kernels construct. + if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) { + auto WorkerClauses = llvm::make_filter_range( + ExistingClauses, llvm::IsaPred); + + for (auto *WC : WorkerClauses) { + if (cast(WC)->hasIntExpr()) { + SemaRef.Diag(Clause.getBeginLoc(), + diag::err_acc_num_arg_conflict_reverse) + << OpenACCClauseKind::NumWorkers << OpenACCClauseKind::Worker + << /*num argument*/ 0; + SemaRef.Diag(WC->getBeginLoc(), diag::note_acc_previous_clause_here); + return nullptr; + } + } + } + assert(Clause.getIntExprs().size() == 1 && "Invalid number of expressions for NumWorkers"); return OpenACCNumWorkersClause::Create( @@ -765,6 +804,25 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorLengthClause( if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause)) return nullptr; + // OpenACC 3.3 Section 2.9.4: + // An argument is allowed only when the 'vector_length' does not appear on the + // 'kernels' construct. + if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) { + auto VectorClauses = llvm::make_filter_range( + ExistingClauses, llvm::IsaPred); + + for (auto *VC : VectorClauses) { + if (cast(VC)->hasIntExpr()) { + SemaRef.Diag(Clause.getBeginLoc(), + diag::err_acc_num_arg_conflict_reverse) + << OpenACCClauseKind::VectorLength << OpenACCClauseKind::Vector + << /*num argument*/ 0; + SemaRef.Diag(VC->getBeginLoc(), diag::note_acc_previous_clause_here); + return nullptr; + } + } + } + assert(Clause.getIntExprs().size() == 1 && "Invalid number of expressions for NumWorkers"); return OpenACCVectorLengthClause::Create( @@ -1033,90 +1091,237 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause( Clause.getEndLoc()); } +ExprResult CheckGangStaticExpr(SemaOpenACC &S, Expr *E) { + if (isa(E)) + return E; + return S.ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang, + E->getBeginLoc(), E); +} + +bool IsOrphanLoop(OpenACCDirectiveKind DK, OpenACCDirectiveKind AssocKind) { + return DK == OpenACCDirectiveKind::Loop && + AssocKind == OpenACCDirectiveKind::Invalid; +} + +bool HasAssocKind(OpenACCDirectiveKind DK, OpenACCDirectiveKind AssocKind) { + return DK == OpenACCDirectiveKind::Loop && + AssocKind != OpenACCDirectiveKind::Invalid; +} + +ExprResult DiagIntArgInvalid(SemaOpenACC &S, Expr *E, OpenACCGangKind GK, + OpenACCClauseKind CK, OpenACCDirectiveKind DK, + OpenACCDirectiveKind AssocKind) { + S.Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid) + << GK << CK << IsOrphanLoop(DK, AssocKind) << DK + << HasAssocKind(DK, AssocKind) << AssocKind; + return ExprError(); +} +ExprResult DiagIntArgInvalid(SemaOpenACC &S, Expr *E, StringRef TagKind, + OpenACCClauseKind CK, OpenACCDirectiveKind DK, + OpenACCDirectiveKind AssocKind) { + S.Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid) + << TagKind << CK << IsOrphanLoop(DK, AssocKind) << DK + << HasAssocKind(DK, AssocKind) << AssocKind; + return ExprError(); +} + +ExprResult CheckGangParallelExpr(SemaOpenACC &S, OpenACCDirectiveKind DK, + OpenACCDirectiveKind AssocKind, + OpenACCGangKind GK, Expr *E) { + switch (GK) { + case OpenACCGangKind::Static: + return CheckGangStaticExpr(S, E); + case OpenACCGangKind::Num: + // OpenACC 3.3 2.9.2: When the parent compute construct is a parallel + // construct, or an orphaned loop construct, the gang clause behaves as + // follows. ... The num argument is not allowed. + return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind); + case OpenACCGangKind::Dim: { + // OpenACC 3.3 2.9.2: When the parent compute construct is a parallel + // construct, or an orphaned loop construct, the gang clause behaves as + // follows. ... The dim argument must be a constant positive integer value + // 1, 2, or 3. + if (!E) + return ExprError(); + ExprResult Res = + S.ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang, + E->getBeginLoc(), E); + + if (!Res.isUsable()) + return Res; + + if (Res.get()->isInstantiationDependent()) + return Res; + + std::optional ICE = + Res.get()->getIntegerConstantExpr(S.getASTContext()); + + if (!ICE || *ICE <= 0 || ICE > 3) { + S.Diag(Res.get()->getBeginLoc(), diag::err_acc_gang_dim_value) + << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue(); + return ExprError(); + } + + return ExprResult{ + ConstantExpr::Create(S.getASTContext(), Res.get(), APValue{*ICE})}; + } + } + llvm_unreachable("Unknown gang kind in gang parallel check"); +} + +ExprResult CheckGangKernelsExpr(SemaOpenACC &S, + ArrayRef ExistingClauses, + OpenACCDirectiveKind DK, + OpenACCDirectiveKind AssocKind, + OpenACCGangKind GK, Expr *E) { + switch (GK) { + // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels + // construct, the gang clause behaves as follows. ... The dim argument is + // not allowed. + case OpenACCGangKind::Dim: + return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind); + case OpenACCGangKind::Num: { + // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels + // construct, the gang clause behaves as follows. ... An argument with no + // keyword or with num keyword is only allowed when num_gangs does not + // appear on the kernels construct. ... The region of a loop with the gang + // clause may not contain another loop with a gang clause unless within a + // nested compute region. + + // If this is a 'combined' construct, search the list of existing clauses. + // Else we need to search the containing 'kernel'. + auto Collection = isOpenACCCombinedDirectiveKind(DK) + ? ExistingClauses + : S.getActiveComputeConstructInfo().Clauses; + + const auto *Itr = + llvm::find_if(Collection, llvm::IsaPred); + + if (Itr != Collection.end()) { + S.Diag(E->getBeginLoc(), diag::err_acc_num_arg_conflict) + << "num" << OpenACCClauseKind::Gang << DK + << HasAssocKind(DK, AssocKind) << AssocKind + << OpenACCClauseKind::NumGangs; + + S.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here); + return ExprError(); + } + return ExprResult{E}; + } + case OpenACCGangKind::Static: + return CheckGangStaticExpr(S, E); + return ExprError(); + } + llvm_unreachable("Unknown gang kind in gang kernels check"); +} + +ExprResult CheckGangSerialExpr(SemaOpenACC &S, OpenACCDirectiveKind DK, + OpenACCDirectiveKind AssocKind, + OpenACCGangKind GK, Expr *E) { + switch (GK) { + // 'dim' and 'num' don't really make sense on serial, and GCC rejects them + // too, so we disallow them too. + case OpenACCGangKind::Dim: + case OpenACCGangKind::Num: + return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind); + case OpenACCGangKind::Static: + return CheckGangStaticExpr(S, E); + } + llvm_unreachable("Unknown gang kind in gang serial check"); +} + OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorClause( SemaOpenACC::OpenACCParsedClause &Clause) { if (DiagIfSeqClause(Clause)) return nullptr; - // Restrictions only properly implemented on 'loop' constructs, and it is - // the only construct that can do anything with this, so skip/treat as - // unimplemented for the combined constructs. - if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) + + // Restrictions only properly implemented on 'loop'/'combined' constructs, and + // it is the only construct that can do anything with this, so skip/treat as + // unimplemented for the routine constructs. + if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop && + !isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) return isNotImplemented(); Expr *IntExpr = Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr; if (IntExpr) { - switch (SemaRef.getActiveComputeConstructInfo().Kind) { - case OpenACCDirectiveKind::Invalid: - case OpenACCDirectiveKind::Parallel: - // No restriction on when 'parallel' can contain an argument. - break; - case OpenACCDirectiveKind::Serial: - // GCC disallows this, and there is no real good reason for us to permit - // it, so disallow until we come up with a use case that makes sense. - SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_int_arg_invalid) - << OpenACCClauseKind::Vector << "num" << /*serial=*/3; - IntExpr = nullptr; - break; - case OpenACCDirectiveKind::Kernels: { - const auto *Itr = - llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses, - llvm::IsaPred); - if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) { - SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict) - << OpenACCClauseKind::Vector << /*vector_length=*/2; - SemaRef.Diag((*Itr)->getBeginLoc(), - diag::note_acc_previous_clause_here); - + if (!isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) { + switch (SemaRef.getActiveComputeConstructInfo().Kind) { + case OpenACCDirectiveKind::Invalid: + case OpenACCDirectiveKind::Parallel: + // No restriction on when 'parallel' can contain an argument. + break; + case OpenACCDirectiveKind::Serial: + // GCC disallows this, and there is no real good reason for us to permit + // it, so disallow until we come up with a use case that makes sense. + DiagIntArgInvalid(SemaRef, IntExpr, "length", OpenACCClauseKind::Vector, + Clause.getDirectiveKind(), + SemaRef.getActiveComputeConstructInfo().Kind); IntExpr = nullptr; + break; + case OpenACCDirectiveKind::Kernels: { + const auto *Itr = + llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses, + llvm::IsaPred); + if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) { + SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict) + << "length" << OpenACCClauseKind::Vector + << Clause.getDirectiveKind() + << HasAssocKind(Clause.getDirectiveKind(), + SemaRef.getActiveComputeConstructInfo().Kind) + << SemaRef.getActiveComputeConstructInfo().Kind + << OpenACCClauseKind::VectorLength; + SemaRef.Diag((*Itr)->getBeginLoc(), + diag::note_acc_previous_clause_here); + + IntExpr = nullptr; + } + break; + } + default: + llvm_unreachable("Non compute construct in active compute construct"); + } + } else { + if (Clause.getDirectiveKind() == OpenACCDirectiveKind::SerialLoop) { + DiagIntArgInvalid(SemaRef, IntExpr, "length", OpenACCClauseKind::Vector, + Clause.getDirectiveKind(), + SemaRef.getActiveComputeConstructInfo().Kind); + IntExpr = nullptr; + } else if (Clause.getDirectiveKind() == + OpenACCDirectiveKind::KernelsLoop) { + const auto *Itr = llvm::find_if( + ExistingClauses, llvm::IsaPred); + if (Itr != ExistingClauses.end()) { + SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict) + << "length" << OpenACCClauseKind::Vector + << Clause.getDirectiveKind() + << HasAssocKind(Clause.getDirectiveKind(), + SemaRef.getActiveComputeConstructInfo().Kind) + << SemaRef.getActiveComputeConstructInfo().Kind + << OpenACCClauseKind::VectorLength; + SemaRef.Diag((*Itr)->getBeginLoc(), + diag::note_acc_previous_clause_here); + + IntExpr = nullptr; + } } - break; - } - default: - llvm_unreachable("Non compute construct in active compute construct"); } } - // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels - // construct, the gang clause behaves as follows. ... The region of a loop - // with a gang clause may not contain another loop with a gang clause unless - // within a nested compute region. - if (SemaRef.LoopGangClauseOnKernelLoc.isValid()) { - // This handles the 'inner loop' diagnostic, but we cannot set that we're on - // one of these until we get to the end of the construct. - SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region) - << OpenACCClauseKind::Vector << OpenACCClauseKind::Gang - << /*skip kernels construct info*/ 0; - SemaRef.Diag(SemaRef.LoopGangClauseOnKernelLoc, - diag::note_acc_previous_clause_here); - return nullptr; - } - - // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not - // contain a loop with a gang or worker clause unless within a nested compute - // region. - if (SemaRef.LoopWorkerClauseLoc.isValid()) { - // This handles the 'inner loop' diagnostic, but we cannot set that we're on - // one of these until we get to the end of the construct. - SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region) - << OpenACCClauseKind::Vector << OpenACCClauseKind::Worker - << /*skip kernels construct info*/ 0; - SemaRef.Diag(SemaRef.LoopWorkerClauseLoc, - diag::note_acc_previous_clause_here); - return nullptr; - } - // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not - // contain a loop with a gang, worker, or vector clause unless within a nested - // compute region. - if (SemaRef.LoopVectorClauseLoc.isValid()) { - // This handles the 'inner loop' diagnostic, but we cannot set that we're on - // one of these until we get to the end of the construct. - SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region) - << OpenACCClauseKind::Vector << OpenACCClauseKind::Vector - << /*skip kernels construct info*/ 0; - SemaRef.Diag(SemaRef.LoopVectorClauseLoc, - diag::note_acc_previous_clause_here); - return nullptr; + if (!isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) { + // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not + // contain a loop with a gang, worker, or vector clause unless within a + // nested compute region. + if (SemaRef.LoopVectorClauseLoc.isValid()) { + // This handles the 'inner loop' diagnostic, but we cannot set that we're + // on one of these until we get to the end of the construct. + SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region) + << OpenACCClauseKind::Vector << OpenACCClauseKind::Vector + << /*skip kernels construct info*/ 0; + SemaRef.Diag(SemaRef.LoopVectorClauseLoc, + diag::note_acc_previous_clause_here); + return nullptr; + } } return OpenACCVectorClause::Create(Ctx, Clause.getBeginLoc(), @@ -1129,77 +1334,107 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitWorkerClause( if (DiagIfSeqClause(Clause)) return nullptr; - // Restrictions only properly implemented on 'loop' constructs, and it is - // the only construct that can do anything with this, so skip/treat as - // unimplemented for the combined constructs. - if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) + // Restrictions only properly implemented on 'loop'/'combined' constructs, and + // it is the only construct that can do anything with this, so skip/treat as + // unimplemented for the routine constructs. + if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop && + !isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) return isNotImplemented(); Expr *IntExpr = Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr; if (IntExpr) { - switch (SemaRef.getActiveComputeConstructInfo().Kind) { - case OpenACCDirectiveKind::Invalid: - SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_int_arg_invalid) - << OpenACCClauseKind::Worker << "num" << /*orphan=*/0; - IntExpr = nullptr; - break; - case OpenACCDirectiveKind::Parallel: - SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_int_arg_invalid) - << OpenACCClauseKind::Worker << "num" << /*parallel=*/1; - IntExpr = nullptr; - break; - case OpenACCDirectiveKind::Serial: - SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_int_arg_invalid) - << OpenACCClauseKind::Worker << "num" << /*serial=*/3; - IntExpr = nullptr; - break; - case OpenACCDirectiveKind::Kernels: { - const auto *Itr = - llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses, - llvm::IsaPred); - if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) { - SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict) - << OpenACCClauseKind::Worker << /*num_workers=*/1; - SemaRef.Diag((*Itr)->getBeginLoc(), - diag::note_acc_previous_clause_here); - + if (!isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) { + switch (SemaRef.getActiveComputeConstructInfo().Kind) { + case OpenACCDirectiveKind::Invalid: + case OpenACCDirectiveKind::ParallelLoop: + case OpenACCDirectiveKind::SerialLoop: + case OpenACCDirectiveKind::Parallel: + case OpenACCDirectiveKind::Serial: + DiagIntArgInvalid(SemaRef, IntExpr, OpenACCGangKind::Num, + OpenACCClauseKind::Worker, Clause.getDirectiveKind(), + SemaRef.getActiveComputeConstructInfo().Kind); IntExpr = nullptr; + break; + case OpenACCDirectiveKind::KernelsLoop: + case OpenACCDirectiveKind::Kernels: { + const auto *Itr = + llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses, + llvm::IsaPred); + if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) { + SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict) + << "num" << OpenACCClauseKind::Worker << Clause.getDirectiveKind() + << HasAssocKind(Clause.getDirectiveKind(), + SemaRef.getActiveComputeConstructInfo().Kind) + << SemaRef.getActiveComputeConstructInfo().Kind + << OpenACCClauseKind::NumWorkers; + SemaRef.Diag((*Itr)->getBeginLoc(), + diag::note_acc_previous_clause_here); + + IntExpr = nullptr; + } + break; + } + default: + llvm_unreachable("Non compute construct in active compute construct"); + } + } else { + if (Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop || + Clause.getDirectiveKind() == OpenACCDirectiveKind::SerialLoop) { + DiagIntArgInvalid(SemaRef, IntExpr, OpenACCGangKind::Num, + OpenACCClauseKind::Worker, Clause.getDirectiveKind(), + SemaRef.getActiveComputeConstructInfo().Kind); + IntExpr = nullptr; + } else { + assert(Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop && + "Unknown combined directive kind?"); + const auto *Itr = llvm::find_if(ExistingClauses, + llvm::IsaPred); + if (Itr != ExistingClauses.end()) { + SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict) + << "num" << OpenACCClauseKind::Worker << Clause.getDirectiveKind() + << HasAssocKind(Clause.getDirectiveKind(), + SemaRef.getActiveComputeConstructInfo().Kind) + << SemaRef.getActiveComputeConstructInfo().Kind + << OpenACCClauseKind::NumWorkers; + SemaRef.Diag((*Itr)->getBeginLoc(), + diag::note_acc_previous_clause_here); + + IntExpr = nullptr; + } } - break; - } - default: - llvm_unreachable("Non compute construct in active compute construct"); } } - // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not - // contain a loop with a gang or worker clause unless within a nested compute - // region. - if (SemaRef.LoopWorkerClauseLoc.isValid()) { - // This handles the 'inner loop' diagnostic, but we cannot set that we're on - // one of these until we get to the end of the construct. - SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region) - << OpenACCClauseKind::Worker << OpenACCClauseKind::Worker - << /*skip kernels construct info*/ 0; - SemaRef.Diag(SemaRef.LoopWorkerClauseLoc, - diag::note_acc_previous_clause_here); - return nullptr; - } + if (!isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) { + // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not + // contain a loop with a gang or worker clause unless within a nested + // compute region. + if (SemaRef.LoopWorkerClauseLoc.isValid()) { + // This handles the 'inner loop' diagnostic, but we cannot set that we're + // on one of these until we get to the end of the construct. + SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region) + << OpenACCClauseKind::Worker << OpenACCClauseKind::Worker + << /*skip kernels construct info*/ 0; + SemaRef.Diag(SemaRef.LoopWorkerClauseLoc, + diag::note_acc_previous_clause_here); + return nullptr; + } - // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not - // contain a loop with a gang, worker, or vector clause unless within a nested - // compute region. - if (SemaRef.LoopVectorClauseLoc.isValid()) { - // This handles the 'inner loop' diagnostic, but we cannot set that we're on - // one of these until we get to the end of the construct. - SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region) - << OpenACCClauseKind::Worker << OpenACCClauseKind::Vector - << /*skip kernels construct info*/ 0; - SemaRef.Diag(SemaRef.LoopVectorClauseLoc, - diag::note_acc_previous_clause_here); - return nullptr; + // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not + // contain a loop with a gang, worker, or vector clause unless within a + // nested compute region. + if (SemaRef.LoopVectorClauseLoc.isValid()) { + // This handles the 'inner loop' diagnostic, but we cannot set that we're + // on one of these until we get to the end of the construct. + SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region) + << OpenACCClauseKind::Worker << OpenACCClauseKind::Vector + << /*skip kernels construct info*/ 0; + SemaRef.Diag(SemaRef.LoopVectorClauseLoc, + diag::note_acc_previous_clause_here); + return nullptr; + } } return OpenACCWorkerClause::Create(Ctx, Clause.getBeginLoc(), @@ -1215,12 +1450,15 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause( // Restrictions only properly implemented on 'loop' constructs, and it is // the only construct that can do anything with this, so skip/treat as // unimplemented for the combined constructs. - if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) + if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop && + !isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) return isNotImplemented(); // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop // directive that has a gang clause and is within a compute construct that has // a num_gangs clause with more than one explicit argument. + // TODO OpenACC: When we implement reduction on combined constructs, we need + // to do this too. if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop && SemaRef.getActiveComputeConstructInfo().Kind != OpenACCDirectiveKind::Invalid) { @@ -1257,31 +1495,13 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause( for (unsigned I = 0; I < Clause.getIntExprs().size(); ++I) { OpenACCGangKind GK = Clause.getGangKinds()[I]; - ExprResult ER = SemaRef.CheckGangExpr(GK, Clause.getIntExprs()[I]); + ExprResult ER = + SemaRef.CheckGangExpr(ExistingClauses, Clause.getDirectiveKind(), GK, + Clause.getIntExprs()[I]); if (!ER.isUsable()) continue; - // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels - // construct, the gang clause behaves as follows. ... An argument with no - // keyword or with num keyword is only allowed when num_gangs does not - // appear on the kernels construct. - if (SemaRef.getActiveComputeConstructInfo().Kind == - OpenACCDirectiveKind::Kernels && - GK == OpenACCGangKind::Num) { - const auto *Itr = - llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses, - llvm::IsaPred); - - if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) { - SemaRef.Diag(ER.get()->getBeginLoc(), diag::err_acc_num_arg_conflict) - << OpenACCClauseKind::Gang << /*num_gangs=*/0; - SemaRef.Diag((*Itr)->getBeginLoc(), - diag::note_acc_previous_clause_here); - continue; - } - } - // OpenACC 3.3 2.9: 'gang-arg-list' may have at most one num, one dim, and // one static argument. if (ExistingElemLoc[static_cast(GK)].isValid()) { @@ -1297,47 +1517,50 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause( IntExprs.push_back(ER.get()); } - // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels - // construct, the gang clause behaves as follows. ... The region of a loop - // with a gang clause may not contain another loop with a gang clause unless - // within a nested compute region. - if (SemaRef.LoopGangClauseOnKernelLoc.isValid()) { - // This handles the 'inner loop' diagnostic, but we cannot set that we're on - // one of these until we get to the end of the construct. - SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region) - << OpenACCClauseKind::Gang << OpenACCClauseKind::Gang - << /*kernels construct info*/ 1; - SemaRef.Diag(SemaRef.LoopGangClauseOnKernelLoc, - diag::note_acc_previous_clause_here); - return nullptr; - } + if (!isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) { + // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels + // construct, the gang clause behaves as follows. ... The region of a loop + // with a gang clause may not contain another loop with a gang clause unless + // within a nested compute region. + if (SemaRef.LoopGangClauseOnKernel.Loc.isValid()) { + // This handles the 'inner loop' diagnostic, but we cannot set that we're + // on one of these until we get to the end of the construct. + SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region) + << OpenACCClauseKind::Gang << OpenACCClauseKind::Gang + << /*kernels construct info*/ 1 + << SemaRef.LoopGangClauseOnKernel.DirKind; + SemaRef.Diag(SemaRef.LoopGangClauseOnKernel.Loc, + diag::note_acc_previous_clause_here); + return nullptr; + } - // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not - // contain a loop with a gang or worker clause unless within a nested compute - // region. - if (SemaRef.LoopWorkerClauseLoc.isValid()) { - // This handles the 'inner loop' diagnostic, but we cannot set that we're on - // one of these until we get to the end of the construct. - SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region) - << OpenACCClauseKind::Gang << OpenACCClauseKind::Worker - << /*kernels construct info*/ 1; - SemaRef.Diag(SemaRef.LoopWorkerClauseLoc, - diag::note_acc_previous_clause_here); - return nullptr; - } + // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not + // contain a loop with a gang or worker clause unless within a nested + // compute region. + if (SemaRef.LoopWorkerClauseLoc.isValid()) { + // This handles the 'inner loop' diagnostic, but we cannot set that we're + // on one of these until we get to the end of the construct. + SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region) + << OpenACCClauseKind::Gang << OpenACCClauseKind::Worker + << /*!kernels construct info*/ 0; + SemaRef.Diag(SemaRef.LoopWorkerClauseLoc, + diag::note_acc_previous_clause_here); + return nullptr; + } - // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not - // contain a loop with a gang, worker, or vector clause unless within a nested - // compute region. - if (SemaRef.LoopVectorClauseLoc.isValid()) { - // This handles the 'inner loop' diagnostic, but we cannot set that we're on - // one of these until we get to the end of the construct. - SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region) - << OpenACCClauseKind::Gang << OpenACCClauseKind::Vector - << /*kernels construct info*/ 1; - SemaRef.Diag(SemaRef.LoopVectorClauseLoc, - diag::note_acc_previous_clause_here); - return nullptr; + // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not + // contain a loop with a gang, worker, or vector clause unless within a + // nested compute region. + if (SemaRef.LoopVectorClauseLoc.isValid()) { + // This handles the 'inner loop' diagnostic, but we cannot set that we're + // on one of these until we get to the end of the construct. + SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region) + << OpenACCClauseKind::Gang << OpenACCClauseKind::Vector + << /*!kernels construct info*/ 0; + SemaRef.Diag(SemaRef.LoopVectorClauseLoc, + diag::note_acc_previous_clause_here); + return nullptr; + } } return SemaRef.CheckGangClause(ExistingClauses, Clause.getBeginLoc(), @@ -1517,7 +1740,7 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII( ArrayRef UnInstClauses, ArrayRef Clauses) : SemaRef(S), OldActiveComputeConstructInfo(S.ActiveComputeConstructInfo), - DirKind(DK), OldLoopGangClauseOnKernelLoc(S.LoopGangClauseOnKernelLoc), + DirKind(DK), OldLoopGangClauseOnKernel(S.LoopGangClauseOnKernel), OldLoopWorkerClauseLoc(S.LoopWorkerClauseLoc), OldLoopVectorClauseLoc(S.LoopVectorClauseLoc), OldLoopWithoutSeqInfo(S.LoopWithoutSeqInfo), @@ -1538,7 +1761,7 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII( // within a nested compute region. // // Implement the 'unless within a nested compute region' part. - SemaRef.LoopGangClauseOnKernelLoc = {}; + SemaRef.LoopGangClauseOnKernel = {}; SemaRef.LoopWorkerClauseLoc = {}; SemaRef.LoopVectorClauseLoc = {}; SemaRef.LoopWithoutSeqInfo = {}; @@ -1552,8 +1775,7 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII( SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses); SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses); - // TODO: OpenACC: We need to set these 3, CollapseInfo, and TileInfo - SemaRef.LoopGangClauseOnKernelLoc = {}; + SemaRef.LoopGangClauseOnKernel = {}; SemaRef.LoopWorkerClauseLoc = {}; SemaRef.LoopVectorClauseLoc = {}; @@ -1576,7 +1798,7 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII( // This handles the 'outer loop' part of this. auto *Itr = llvm::find_if(Clauses, llvm::IsaPred); if (Itr != Clauses.end()) - SemaRef.LoopGangClauseOnKernelLoc = (*Itr)->getBeginLoc(); + SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(), DirKind}; } if (UnInstClauses.empty()) { @@ -1614,7 +1836,8 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII( // This handles the 'outer loop' part of this. auto *Itr = llvm::find_if(Clauses, llvm::IsaPred); if (Itr != Clauses.end()) - SemaRef.LoopGangClauseOnKernelLoc = (*Itr)->getBeginLoc(); + SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(), + OpenACCDirectiveKind::Kernels}; } if (UnInstClauses.empty()) { @@ -1699,7 +1922,7 @@ void SemaOpenACC::AssociatedStmtRAII::SetTileInfoBeforeAssociatedStmt( SemaOpenACC::AssociatedStmtRAII::~AssociatedStmtRAII() { SemaRef.ActiveComputeConstructInfo = OldActiveComputeConstructInfo; - SemaRef.LoopGangClauseOnKernelLoc = OldLoopGangClauseOnKernelLoc; + SemaRef.LoopGangClauseOnKernel = OldLoopGangClauseOnKernel; SemaRef.LoopWorkerClauseLoc = OldLoopWorkerClauseLoc; SemaRef.LoopVectorClauseLoc = OldLoopVectorClauseLoc; SemaRef.LoopWithoutSeqInfo = OldLoopWithoutSeqInfo; @@ -2356,106 +2579,47 @@ ExprResult SemaOpenACC::CheckCollapseLoopCount(Expr *LoopCount) { ConstantExpr::Create(getASTContext(), LoopCount, APValue{*ICE})}; } -namespace { -ExprResult CheckGangStaticExpr(SemaOpenACC &S, Expr *E) { - if (isa(E)) - return E; - return S.ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang, - E->getBeginLoc(), E); -} -} // namespace - -ExprResult SemaOpenACC::CheckGangExpr(OpenACCGangKind GK, Expr *E) { - // Gang Expr legality depends on the associated compute construct. - switch (ActiveComputeConstructInfo.Kind) { - case OpenACCDirectiveKind::Invalid: - case OpenACCDirectiveKind::Parallel: { - switch (GK) { - // OpenACC 3.3 2.9.2: When the parent compute construct is a parallel - // construct, or an orphaned loop construct, the gang clause behaves as - // follows. ... The dim argument must be a constant positive integer value - // 1, 2, or 3. - case OpenACCGangKind::Dim: { - if (!E) - return ExprError(); - ExprResult Res = - ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang, - E->getBeginLoc(), E); - - if (!Res.isUsable()) - return Res; - - if (Res.get()->isInstantiationDependent()) - return Res; - - std::optional ICE = - Res.get()->getIntegerConstantExpr(getASTContext()); - - if (!ICE || *ICE <= 0 || ICE > 3) { - Diag(Res.get()->getBeginLoc(), diag::err_acc_gang_dim_value) - << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue(); - return ExprError(); - } - - return ExprResult{ - ConstantExpr::Create(getASTContext(), Res.get(), APValue{*ICE})}; - } - // OpenACC 3.3 2.9.2: When the parent compute construct is a parallel - // construct, or an orphaned loop construct, the gang clause behaves as - // follows. ... The num argument is not allowed. - case OpenACCGangKind::Num: - Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid) - << OpenACCClauseKind::Gang << GK - << (/*orphan/parallel=*/ActiveComputeConstructInfo.Kind == - OpenACCDirectiveKind::Parallel - ? 1 - : 0); - return ExprError(); - case OpenACCGangKind::Static: - return CheckGangStaticExpr(*this, E); - } - } break; - case OpenACCDirectiveKind::Kernels: { - switch (GK) { - // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels - // construct, the gang clause behaves as follows. ... The dim argument is - // not allowed. - case OpenACCGangKind::Dim: - Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid) - << OpenACCClauseKind::Gang << GK << /*kernels=*/2; - return ExprError(); - // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels - // construct, the gang clause behaves as follows. ... An argument with no - // keyword or with num keyword is only allowed when num_gangs does not - // appear on the kernels construct. ... The region of a loop with the gang - // clause may not contain another loop with a gang clause unless within a - // nested compute region. - case OpenACCGangKind::Num: - // This isn't allowed if there is a 'num_gangs' on the kernel construct, - // and makes loop-with-gang-clause ill-formed inside of this 'loop', but - // nothing can be enforced here. - return ExprResult{E}; - case OpenACCGangKind::Static: - return CheckGangStaticExpr(*this, E); - } - } break; - case OpenACCDirectiveKind::Serial: { - switch (GK) { - // 'dim' and 'num' don't really make sense on serial, and GCC rejects them - // too, so we disallow them too. - case OpenACCGangKind::Dim: - case OpenACCGangKind::Num: - Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid) - << OpenACCClauseKind::Gang << GK << /*Kernels=*/3; - return ExprError(); - case OpenACCGangKind::Static: - return CheckGangStaticExpr(*this, E); +ExprResult +SemaOpenACC::CheckGangExpr(ArrayRef ExistingClauses, + OpenACCDirectiveKind DK, OpenACCGangKind GK, + Expr *E) { + // There are two cases for the enforcement here: the 'current' directive is a + // 'loop', where we need to check the active compute construct kind, or the + // current directive is a 'combined' construct, where we have to check the + // current one. + switch (DK) { + case OpenACCDirectiveKind::ParallelLoop: + return CheckGangParallelExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK, + E); + case OpenACCDirectiveKind::SerialLoop: + return CheckGangSerialExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK, + E); + case OpenACCDirectiveKind::KernelsLoop: + return CheckGangKernelsExpr(*this, ExistingClauses, DK, + ActiveComputeConstructInfo.Kind, GK, E); + case OpenACCDirectiveKind::Loop: + switch (ActiveComputeConstructInfo.Kind) { + case OpenACCDirectiveKind::Invalid: + case OpenACCDirectiveKind::Parallel: + case OpenACCDirectiveKind::ParallelLoop: + return CheckGangParallelExpr(*this, DK, ActiveComputeConstructInfo.Kind, + GK, E); + case OpenACCDirectiveKind::SerialLoop: + case OpenACCDirectiveKind::Serial: + return CheckGangSerialExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK, + E); + case OpenACCDirectiveKind::KernelsLoop: + case OpenACCDirectiveKind::Kernels: + return CheckGangKernelsExpr(*this, ExistingClauses, DK, + ActiveComputeConstructInfo.Kind, GK, E); + default: + llvm_unreachable("Non compute construct in active compute construct?"); } - } break; default: - llvm_unreachable("Non compute construct in active compute construct?"); + // TODO: OpenACC: when we implement this on 'routine', we'll have to + // implement its checking here. + llvm_unreachable("Invalid directive kind for a Gang clause"); } - llvm_unreachable("Compute construct directive not handled?"); } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index c174922a926fc..3dabe362802c9 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -15575,7 +15575,7 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Build the actual expression node. ExprResult FnExpr = CreateFunctionRefExpr(*this, Method, FoundDecl, MemExpr, - HadMultipleCandidates, MemExpr->getBeginLoc()); + HadMultipleCandidates, MemExpr->getExprLoc()); if (FnExpr.isInvalid()) return ExprError(); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 5fb936297aa54..4893bb0ec2d26 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5347,15 +5347,23 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: - ClsType = QualType(NNS->getAsType(), 0); + const Type *NNSType = NNS->getAsType(); + ClsType = QualType(NNSType, 0); // Note: if the NNS has a prefix and ClsType is a nondependent - // TemplateSpecializationType, then the NNS prefix is NOT included - // in ClsType; hence we wrap ClsType into an ElaboratedType. - // NOTE: in particular, no wrap occurs if ClsType already is an - // Elaborated, DependentName, or DependentTemplateSpecialization. - if (isa(NNS->getAsType())) + // TemplateSpecializationType or a RecordType, then the NNS prefix is + // NOT included in ClsType; hence we wrap ClsType into an + // ElaboratedType. NOTE: in particular, no wrap occurs if ClsType + // already is an Elaborated, DependentName, or + // DependentTemplateSpecialization. + if (isa(NNSType)) { + // FIXME: Rebuild DependentTemplateSpecializationType, adding the + // Prefix. + } else if (isa(NNSType)) { + // Either the dependent case (TemplateSpecializationType), or the + // non-dependent one (RecordType). ClsType = Context.getElaboratedType(ElaboratedTypeKeyword::None, NNSPrefix, ClsType); + } break; } } else { diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 3a8f2d95f329b..81e515e7cb2a9 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -12027,7 +12027,9 @@ void OpenACCClauseTransform::VisitGangClause( if (!ER.isUsable()) continue; - ER = Self.getSema().OpenACC().CheckGangExpr(C.getExpr(I).first, ER.get()); + ER = Self.getSema().OpenACC().CheckGangExpr(ExistingClauses, + ParsedClause.getDirectiveKind(), + C.getExpr(I).first, ER.get()); if (!ER.isUsable()) continue; TransformedGangKinds.push_back(C.getExpr(I).first); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 6ece3ba7af9f4..ff0b963039238 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -4616,7 +4616,7 @@ void ASTDeclReader::UpdateDecl( .dyn_cast()) FTSInfo->setPointOfInstantiation(POI); else - FD->TemplateOrSpecialization.get() + cast(FD->TemplateOrSpecialization) ->setPointOfInstantiation(POI); } break; @@ -4715,8 +4715,8 @@ void ASTDeclReader::UpdateDecl( // FIXME: If we already have a partial specialization set, // check that it matches. - if (!Spec->getSpecializedTemplateOrPartial() - .is()) + if (!isa( + Spec->getSpecializedTemplateOrPartial())) Spec->setInstantiationOf(PartialSpec, TemplArgList); } } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 731ad0b64dc85..9f4877b19d870 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -911,9 +911,9 @@ void ASTStmtReader::VisitRequiresExpr(RequiresExpr *E) { std::move(*Req), Status, SubstitutedConstraintExpr); else R = new (Record.getContext()) concepts::ExprRequirement( - E.get(), - RK == concepts::Requirement::RK_Simple, NoexceptLoc, - std::move(*Req)); + cast(E), + RK == concepts::Requirement::RK_Simple, NoexceptLoc, + std::move(*Req)); } break; case concepts::Requirement::RK_Nested: { ASTContext &C = Record.getContext(); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index a52d59c61c4ce..368e8f2367543 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -184,14 +184,30 @@ GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) { const SourceManager &SM = PP.getSourceManager(); const ModuleMap &MM = HS.getModuleMap(); - llvm::DenseSet ModuleMaps; - - llvm::DenseSet ProcessedModules; - auto CollectModuleMapsForHierarchy = [&](const Module *M) { + // Module maps used only by textual headers are special. Their FileID is + // non-affecting, but their FileEntry is (i.e. must be written as InputFile). + enum AffectedReason : bool { + AR_TextualHeader = 0, + AR_ImportOrTextualHeader = 1, + }; + auto AssignMostImportant = [](AffectedReason &LHS, AffectedReason RHS) { + LHS = std::max(LHS, RHS); + }; + llvm::DenseMap ModuleMaps; + llvm::DenseMap ProcessedModules; + auto CollectModuleMapsForHierarchy = [&](const Module *M, + AffectedReason Reason) { M = M->getTopLevelModule(); - if (!ProcessedModules.insert(M).second) + // We need to process the header either when it was not present or when we + // previously flagged module map as textual headers and now we found a + // proper import. + if (auto [It, Inserted] = ProcessedModules.insert({M, Reason}); + !Inserted && Reason <= It->second) { return; + } else { + It->second = Reason; + } std::queue Q; Q.push(M); @@ -202,12 +218,12 @@ GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) { // The containing module map is affecting, because it's being pointed // into by Module::DefinitionLoc. if (auto F = MM.getContainingModuleMapFileID(Mod); F.isValid()) - ModuleMaps.insert(F); + AssignMostImportant(ModuleMaps[F], Reason); // For inferred modules, the module map that allowed inferring is not // related to the virtual containing module map file. It did affect the // compilation, though. if (auto UniqF = MM.getModuleMapFileIDForUniquing(Mod); UniqF.isValid()) - ModuleMaps.insert(UniqF); + AssignMostImportant(ModuleMaps[UniqF], Reason); for (auto *SubM : Mod->submodules()) Q.push(SubM); @@ -216,7 +232,7 @@ GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) { // Handle all the affecting modules referenced from the root module. - CollectModuleMapsForHierarchy(RootModule); + CollectModuleMapsForHierarchy(RootModule, AR_ImportOrTextualHeader); std::queue Q; Q.push(RootModule); @@ -225,9 +241,9 @@ GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) { Q.pop(); for (const Module *ImportedModule : CurrentModule->Imports) - CollectModuleMapsForHierarchy(ImportedModule); + CollectModuleMapsForHierarchy(ImportedModule, AR_ImportOrTextualHeader); for (const Module *UndeclaredModule : CurrentModule->UndeclaredUses) - CollectModuleMapsForHierarchy(UndeclaredModule); + CollectModuleMapsForHierarchy(UndeclaredModule, AR_ImportOrTextualHeader); for (auto *M : CurrentModule->submodules()) Q.push(M); @@ -256,7 +272,7 @@ GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) { for (const auto &KH : HS.findResolvedModulesForHeader(*File)) if (const Module *M = KH.getModule()) - CollectModuleMapsForHierarchy(M); + CollectModuleMapsForHierarchy(M, AR_TextualHeader); } // FIXME: This algorithm is not correct for module map hierarchies where @@ -278,13 +294,16 @@ GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) { // includes a module map defining a module that's not a submodule of X. llvm::DenseSet ModuleFileEntries; - for (FileID MM : ModuleMaps) { - if (auto *FE = SM.getFileEntryForID(MM)) + llvm::DenseSet ModuleFileIDs; + for (auto [FID, Reason] : ModuleMaps) { + if (Reason == AR_ImportOrTextualHeader) + ModuleFileIDs.insert(FID); + if (auto *FE = SM.getFileEntryForID(FID)) ModuleFileEntries.insert(FE); } AffectingModuleMaps R; - R.DefinitionFileIDs = std::move(ModuleMaps); + R.DefinitionFileIDs = std::move(ModuleFileIDs); R.DefinitionFiles = std::move(ModuleFileEntries); return std::move(R); } @@ -4922,7 +4941,7 @@ ASTWriter::WriteAST(llvm::PointerUnion Subject, Sema *SemaPtr = Subject.dyn_cast(); Preprocessor &PPRef = - SemaPtr ? SemaPtr->getPreprocessor() : *Subject.get(); + SemaPtr ? SemaPtr->getPreprocessor() : *cast(Subject); ASTHasCompilerErrors = PPRef.getDiagnostics().hasUncompilableErrorOccurred(); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index ad357e30d5752..c5112d46a95d7 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1656,7 +1656,7 @@ void ASTDeclWriter::VisitFriendDecl(FriendDecl *D) { // so as to simplify memory allocation during deserialization. Record.push_back(D->NumTPLists); VisitDecl(D); - bool hasFriendDecl = D->Friend.is(); + bool hasFriendDecl = isa(D->Friend); Record.push_back(hasFriendDecl); if (hasFriendDecl) Record.AddDeclRef(D->getFriendDecl()); @@ -1757,7 +1757,7 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl( if (Decl *InstFromD = InstFrom.dyn_cast()) { Record.AddDeclRef(InstFromD); } else { - Record.AddDeclRef(InstFrom.get()); + Record.AddDeclRef(cast(InstFrom)); Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs()); } @@ -1835,7 +1835,7 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl( if (Decl *InstFromD = InstFrom.dyn_cast()) { Record.AddDeclRef(InstFromD); } else { - Record.AddDeclRef(InstFrom.get()); + Record.AddDeclRef(cast(InstFrom)); Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs()); } diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 4994047d9fe10..603aa5707ce9b 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -480,7 +480,7 @@ addConstraintSatisfaction(ASTRecordWriter &Record, if (E) Record.AddStmt(E); else { - auto *Diag = DetailRecord.get *>(); + auto *Diag = cast *>(DetailRecord); Record.AddSourceLocation(Diag->first); Record.AddString(Diag->second); } @@ -532,10 +532,11 @@ void ASTStmtWriter::VisitRequiresExpr(RequiresExpr *E) { Record.push_back(ExprReq->getKind()); Record.push_back(ExprReq->Status); if (ExprReq->isExprSubstitutionFailure()) { - addSubstitutionDiagnostic(Record, - ExprReq->Value.get()); + addSubstitutionDiagnostic( + Record, cast( + ExprReq->Value)); } else - Record.AddStmt(ExprReq->Value.get()); + Record.AddStmt(cast(ExprReq->Value)); if (ExprReq->getKind() == concepts::Requirement::RK_Compound) { Record.AddSourceLocation(ExprReq->NoexceptLoc); const auto &RetReq = ExprReq->getReturnTypeRequirement(); @@ -1166,7 +1167,7 @@ void ASTStmtWriter::VisitInitListExpr(InitListExpr *E) { Record.AddStmt(E->getSyntacticForm()); Record.AddSourceLocation(E->getLBraceLoc()); Record.AddSourceLocation(E->getRBraceLoc()); - bool isArrayFiller = E->ArrayFillerOrUnionFieldInit.is(); + bool isArrayFiller = isa(E->ArrayFillerOrUnionFieldInit); Record.push_back(isArrayFiller); if (isArrayFiller) Record.AddStmt(E->getArrayFiller()); diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt index 2b15d31053cf4..fcbe8b864b6e4 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -131,6 +131,7 @@ add_clang_library(clangStaticAnalyzerCheckers VirtualCallChecker.cpp WebKit/RawPtrRefMemberChecker.cpp WebKit/ASTUtils.cpp + WebKit/MemoryUnsafeCastChecker.cpp WebKit/PtrTypesSemantics.cpp WebKit/RefCntblBaseVirtualDtorChecker.cpp WebKit/RawPtrRefCallArgsChecker.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/MemoryUnsafeCastChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/MemoryUnsafeCastChecker.cpp new file mode 100644 index 0000000000000..eeaccf9b70524 --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/MemoryUnsafeCastChecker.cpp @@ -0,0 +1,188 @@ +//=======- MemoryUnsafeCastChecker.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 +// +//===----------------------------------------------------------------------===// +// +// This file defines MemoryUnsafeCast checker, which checks for casts from a +// base type to a derived type. +//===----------------------------------------------------------------------===// + +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" + +using namespace clang; +using namespace ento; +using namespace ast_matchers; + +namespace { +static constexpr const char *const BaseNode = "BaseNode"; +static constexpr const char *const DerivedNode = "DerivedNode"; +static constexpr const char *const FromCastNode = "FromCast"; +static constexpr const char *const ToCastNode = "ToCast"; +static constexpr const char *const WarnRecordDecl = "WarnRecordDecl"; + +class MemoryUnsafeCastChecker : public Checker { + BugType BT{this, "Unsafe cast", "WebKit coding guidelines"}; + +public: + void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr, + BugReporter &BR) const; +}; +} // end namespace + +static void emitDiagnostics(const BoundNodes &Nodes, BugReporter &BR, + AnalysisDeclContext *ADC, + const MemoryUnsafeCastChecker *Checker, + const BugType &BT) { + const auto *CE = Nodes.getNodeAs(WarnRecordDecl); + const NamedDecl *Base = Nodes.getNodeAs(BaseNode); + const NamedDecl *Derived = Nodes.getNodeAs(DerivedNode); + assert(CE && Base && Derived); + + std::string Diagnostics; + llvm::raw_string_ostream OS(Diagnostics); + OS << "Unsafe cast from base type '" << Base->getNameAsString() + << "' to derived type '" << Derived->getNameAsString() << "'"; + PathDiagnosticLocation BSLoc(CE->getSourceRange().getBegin(), + BR.getSourceManager()); + auto Report = std::make_unique(BT, OS.str(), BSLoc); + Report->addRange(CE->getSourceRange()); + BR.emitReport(std::move(Report)); +} + +static void emitDiagnosticsUnrelated(const BoundNodes &Nodes, BugReporter &BR, + AnalysisDeclContext *ADC, + const MemoryUnsafeCastChecker *Checker, + const BugType &BT) { + const auto *CE = Nodes.getNodeAs(WarnRecordDecl); + const NamedDecl *FromCast = Nodes.getNodeAs(FromCastNode); + const NamedDecl *ToCast = Nodes.getNodeAs(ToCastNode); + assert(CE && FromCast && ToCast); + + std::string Diagnostics; + llvm::raw_string_ostream OS(Diagnostics); + OS << "Unsafe cast from type '" << FromCast->getNameAsString() + << "' to an unrelated type '" << ToCast->getNameAsString() << "'"; + PathDiagnosticLocation BSLoc(CE->getSourceRange().getBegin(), + BR.getSourceManager()); + auto Report = std::make_unique(BT, OS.str(), BSLoc); + Report->addRange(CE->getSourceRange()); + BR.emitReport(std::move(Report)); +} + +namespace clang { +namespace ast_matchers { +AST_MATCHER_P(StringLiteral, mentionsBoundType, std::string, BindingID) { + return Builder->removeBindings([this, &Node](const BoundNodesMap &Nodes) { + const auto &BN = Nodes.getNode(this->BindingID); + if (const auto *ND = BN.get()) { + return ND->getName() != Node.getString(); + } + return true; + }); +} +} // end namespace ast_matchers +} // end namespace clang + +static decltype(auto) hasTypePointingTo(DeclarationMatcher DeclM) { + return hasType(pointerType(pointee(hasDeclaration(DeclM)))); +} + +void MemoryUnsafeCastChecker::checkASTCodeBody(const Decl *D, + AnalysisManager &AM, + BugReporter &BR) const { + + AnalysisDeclContext *ADC = AM.getAnalysisDeclContext(D); + + // Match downcasts from base type to derived type and warn + auto MatchExprPtr = allOf( + hasSourceExpression(hasTypePointingTo(cxxRecordDecl().bind(BaseNode))), + hasTypePointingTo(cxxRecordDecl(isDerivedFrom(equalsBoundNode(BaseNode))) + .bind(DerivedNode)), + unless(anyOf(hasSourceExpression(cxxThisExpr()), + hasTypePointingTo(templateTypeParmDecl())))); + auto MatchExprPtrObjC = allOf( + hasSourceExpression(ignoringImpCasts(hasType(objcObjectPointerType( + pointee(hasDeclaration(objcInterfaceDecl().bind(BaseNode))))))), + ignoringImpCasts(hasType(objcObjectPointerType(pointee(hasDeclaration( + objcInterfaceDecl(isDerivedFrom(equalsBoundNode(BaseNode))) + .bind(DerivedNode))))))); + auto MatchExprRefTypeDef = + allOf(hasSourceExpression(hasType(hasUnqualifiedDesugaredType(recordType( + hasDeclaration(decl(cxxRecordDecl().bind(BaseNode))))))), + hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration( + decl(cxxRecordDecl(isDerivedFrom(equalsBoundNode(BaseNode))) + .bind(DerivedNode)))))), + unless(anyOf(hasSourceExpression(hasDescendant(cxxThisExpr())), + hasType(templateTypeParmDecl())))); + + auto ExplicitCast = explicitCastExpr(anyOf(MatchExprPtr, MatchExprRefTypeDef, + MatchExprPtrObjC)) + .bind(WarnRecordDecl); + auto Cast = stmt(ExplicitCast); + + auto Matches = + match(stmt(forEachDescendant(Cast)), *D->getBody(), AM.getASTContext()); + for (BoundNodes Match : Matches) + emitDiagnostics(Match, BR, ADC, this, BT); + + // Match casts between unrelated types and warn + auto MatchExprPtrUnrelatedTypes = allOf( + hasSourceExpression( + hasTypePointingTo(cxxRecordDecl().bind(FromCastNode))), + hasTypePointingTo(cxxRecordDecl().bind(ToCastNode)), + unless(anyOf(hasTypePointingTo(cxxRecordDecl( + isSameOrDerivedFrom(equalsBoundNode(FromCastNode)))), + hasSourceExpression(hasTypePointingTo(cxxRecordDecl( + isSameOrDerivedFrom(equalsBoundNode(ToCastNode)))))))); + auto MatchExprPtrObjCUnrelatedTypes = allOf( + hasSourceExpression(ignoringImpCasts(hasType(objcObjectPointerType( + pointee(hasDeclaration(objcInterfaceDecl().bind(FromCastNode))))))), + ignoringImpCasts(hasType(objcObjectPointerType( + pointee(hasDeclaration(objcInterfaceDecl().bind(ToCastNode)))))), + unless(anyOf( + ignoringImpCasts(hasType( + objcObjectPointerType(pointee(hasDeclaration(objcInterfaceDecl( + isSameOrDerivedFrom(equalsBoundNode(FromCastNode)))))))), + hasSourceExpression(ignoringImpCasts(hasType( + objcObjectPointerType(pointee(hasDeclaration(objcInterfaceDecl( + isSameOrDerivedFrom(equalsBoundNode(ToCastNode)))))))))))); + auto MatchExprRefTypeDefUnrelated = allOf( + hasSourceExpression(hasType(hasUnqualifiedDesugaredType(recordType( + hasDeclaration(decl(cxxRecordDecl().bind(FromCastNode))))))), + hasType(hasUnqualifiedDesugaredType( + recordType(hasDeclaration(decl(cxxRecordDecl().bind(ToCastNode)))))), + unless(anyOf( + hasType(hasUnqualifiedDesugaredType( + recordType(hasDeclaration(decl(cxxRecordDecl( + isSameOrDerivedFrom(equalsBoundNode(FromCastNode)))))))), + hasSourceExpression(hasType(hasUnqualifiedDesugaredType( + recordType(hasDeclaration(decl(cxxRecordDecl( + isSameOrDerivedFrom(equalsBoundNode(ToCastNode)))))))))))); + + auto ExplicitCastUnrelated = + explicitCastExpr(anyOf(MatchExprPtrUnrelatedTypes, + MatchExprPtrObjCUnrelatedTypes, + MatchExprRefTypeDefUnrelated)) + .bind(WarnRecordDecl); + auto CastUnrelated = stmt(ExplicitCastUnrelated); + auto MatchesUnrelatedTypes = match(stmt(forEachDescendant(CastUnrelated)), + *D->getBody(), AM.getASTContext()); + for (BoundNodes Match : MatchesUnrelatedTypes) + emitDiagnosticsUnrelated(Match, BR, ADC, this, BT); +} + +void ento::registerMemoryUnsafeCastChecker(CheckerManager &Mgr) { + Mgr.registerChecker(); +} + +bool ento::shouldRegisterMemoryUnsafeCastChecker(const CheckerManager &mgr) { + return true; +} diff --git a/clang/test/AST/ByteCode/amdgpu-nullptr.cl b/clang/test/AST/ByteCode/amdgpu-nullptr.cl new file mode 100644 index 0000000000000..d79f1cd4a237b --- /dev/null +++ b/clang/test/AST/ByteCode/amdgpu-nullptr.cl @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -no-enable-noundef-analysis %s -cl-std=CL2.0 -triple amdgcn -emit-llvm -o - | FileCheck %s + +// RUN: %clang_cc1 -no-enable-noundef-analysis %s -cl-std=CL2.0 -triple amdgcn -emit-llvm -fexperimental-new-constant-interpreter -o - | FileCheck %s + + +// CHECK: @fold_priv ={{.*}} local_unnamed_addr addrspace(1) global ptr addrspace(5) addrspacecast (ptr addrspace(1) null to ptr addrspace(5)), align 4 +private short *fold_priv = (private short*)(generic int*)(global void*)0; + +// CHECK: @fold_priv_arith ={{.*}} local_unnamed_addr addrspace(1) global ptr addrspace(5) inttoptr (i32 9 to ptr addrspace(5)), align 4 +private char *fold_priv_arith = (private char*)0 + 10; + + diff --git a/clang/test/AST/ByteCode/builtin-bit-cast-bitfields.cpp b/clang/test/AST/ByteCode/builtin-bit-cast-bitfields.cpp new file mode 100644 index 0000000000000..5aa4e256e4638 --- /dev/null +++ b/clang/test/AST/ByteCode/builtin-bit-cast-bitfields.cpp @@ -0,0 +1,475 @@ +// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-linux-gnu -fexperimental-new-constant-interpreter %s +// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple armv8 -fexperimental-new-constant-interpreter %s +// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s +// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -fexperimental-new-constant-interpreter -triple powerpc64le-unknown-unknown -mabi=ieeelongdouble %s +// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -fexperimental-new-constant-interpreter -triple powerpc64-unknown-unknown -mabi=ieeelongdouble %s + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define LITTLE_END 1 +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define LITTLE_END 0 +#else +# error "huh?" +#endif + +typedef decltype(nullptr) nullptr_t; +typedef __INTPTR_TYPE__ intptr_t; +typedef unsigned __INT16_TYPE__ uint16_t; +typedef unsigned __INT32_TYPE__ uint32_t; +typedef unsigned __INT64_TYPE__ uint64_t; + +static_assert(sizeof(int) == 4); +static_assert(sizeof(long long) == 8); + +template +constexpr To bit_cast(const From &from) { + static_assert(sizeof(To) == sizeof(From)); + return __builtin_bit_cast(To, from); +} + +template +constexpr bool check_round_trip(const Init &init) { + return bit_cast(bit_cast(init)) == init; +} + +template +constexpr Init round_trip(const Init &init) { + return bit_cast(bit_cast(init)); +} + +namespace std { +enum byte : unsigned char {}; +} // namespace std + +template +struct bits { + T : Pad; + T bits : N; + + constexpr bool operator==(const T& rhs) const { + return bits == rhs; + } +}; + +template +constexpr bool operator==(const struct bits& lhs, const struct bits& rhs) { + return lhs.bits == rhs.bits; +} + +template +struct bytes { + using size_t = unsigned int; + unsigned char d[N]; + + constexpr unsigned char operator[](size_t index) { + if (index < N) + return d[index]; // expected-note {{read of uninitialized object}} + return -1; + } +}; + +namespace Sanity { + /// This is just one byte, and we extract 2 bits from it. + /// + /// 3 is 0000'0011. + /// For both LE and BE, the buffer will contain exactly that + /// byte, unaltered and not reordered in any way. It contains all 8 bits. + static_assert(__builtin_bit_cast(bits<2>, (unsigned char)3) == (LITTLE_END ? 3 : 0)); + + /// Similarly, we have one full byte of data, with the two most-significant + /// bits set: + /// 192 is 1100'0000 + static_assert(__builtin_bit_cast(bits<2>, (unsigned char)192) == (LITTLE_END ? 0 : 3)); + + + /// Here we are instead bitcasting two 1-bits into a destination of 8 bits. + /// On LE, we should pick the two least-significant bits. On BE, the opposite. + /// NOTE: Can't verify this with gcc. + constexpr auto B1 = bits<2>{3}; + static_assert(__builtin_bit_cast(unsigned char, B1) == (LITTLE_END ? 3 : 192)); + + /// This should be 0000'0110. + /// On LE, this should result in 6. + /// On BE, 1100'0000 = 192. + constexpr auto B2 = bits<3>{6}; + static_assert(__builtin_bit_cast(unsigned char, B2) == (LITTLE_END ? 6 : 192)); + + constexpr auto B3 = bits<4>{6}; + static_assert(__builtin_bit_cast(unsigned char, B3) == (LITTLE_END ? 6 : 96)); + + struct B { + std::byte b0 : 4; + std::byte b1 : 4; + }; + + /// We can properly decompose one byte (8 bit) int two 4-bit bitfields. + constexpr struct { unsigned char b0; } T = {0xee}; + constexpr B MB = __builtin_bit_cast(B, T); + static_assert(MB.b0 == 0xe); + static_assert(MB.b1 == 0xe); +} + +namespace BitFields { + struct BitFields { + unsigned a : 2; + unsigned b : 30; + }; + + constexpr unsigned A = __builtin_bit_cast(unsigned, BitFields{3, 16}); + static_assert(A == (LITTLE_END ? 67 : 3221225488)); + + struct S { + unsigned a : 2; + unsigned b : 28; + unsigned c : 2; + }; + + constexpr S s = __builtin_bit_cast(S, 0xFFFFFFFF); + static_assert(s.a == 3); + static_assert(s.b == 268435455); + static_assert(s.c == 3); + + void bitfield_indeterminate() { + struct BF { unsigned char z : 2; }; + enum byte : unsigned char {}; + + constexpr BF bf = {0x3}; + static_assert(bit_cast>(bf).bits == bf.z); + static_assert(bit_cast(bf)); + + static_assert(__builtin_bit_cast(byte, bf)); // expected-error {{not an integral constant expression}} \ + // expected-note {{indeterminate value can only initialize an object of type 'unsigned char' or 'std::byte'; 'byte' is invalid}} + + struct M { + // expected-note@+1 {{subobject declared here}} + unsigned char mem[sizeof(BF)]; + }; + // expected-error@+2 {{initialized by a constant expression}} + // expected-note@+1 {{not initialized}} + constexpr M m = bit_cast(bf); + + constexpr auto f = []() constexpr { + // bits<24, unsigned int, LITTLE_END ? 0 : 8> B = {0xc0ffee}; + constexpr struct { unsigned short b1; unsigned char b0; } B = {0xc0ff, 0xee}; + return bit_cast>(B); + }; + + static_assert(f()[0] + f()[1] + f()[2] == 0xc0 + 0xff + 0xee); + { + // expected-error@+2 {{initialized by a constant expression}} + // expected-note@+1 {{in call to}} + constexpr auto _bad = f()[3]; + } + + struct B { + unsigned short s0 : 8; + unsigned short s1 : 8; + std::byte b0 : 4; + std::byte b1 : 4; + std::byte b2 : 4; + }; + constexpr auto g = [f]() constexpr { + return bit_cast(f()); + }; + static_assert(g().s0 + g().s1 + g().b0 + g().b1 == 0xc0 + 0xff + 0xe + 0xe); + { + // expected-error@+2 {{initialized by a constant expression}} + // expected-note@+1 {{read of uninitialized object is not allowed in a constant expression}} + constexpr auto _bad = g().b2; + } + } +} + +namespace BoolVectors { + typedef bool bool32 __attribute__((ext_vector_type(32))); + constexpr auto v = bit_cast(0xa1c0ffee); +#if LITTLE_END + static_assert(!v[0]); + static_assert(v[1]); + static_assert(v[2]); + static_assert(v[3]); + static_assert(!v[4]); + static_assert(v[5]); + static_assert(v[6]); + static_assert(v[7]); + + static_assert(v[8]); + static_assert(v[9]); + static_assert(v[10]); + static_assert(v[11]); + static_assert(v[12]); + static_assert(v[13]); + static_assert(v[14]); + static_assert(v[15]); + + static_assert(!v[16]); + static_assert(!v[17]); + static_assert(!v[18]); + static_assert(!v[19]); + static_assert(!v[20]); + static_assert(!v[21]); + static_assert(v[22]); + static_assert(v[23]); + + static_assert(v[24]); + static_assert(!v[25]); + static_assert(!v[26]); + static_assert(!v[27]); + static_assert(!v[28]); + static_assert(v[29]); + static_assert(!v[30]); + static_assert(v[31]); + +#else + static_assert(v[0]); + static_assert(!v[1]); + static_assert(v[2]); + static_assert(!v[3]); + static_assert(!v[4]); + static_assert(!v[5]); + static_assert(!v[6]); + static_assert(v[7]); + + static_assert(v[8]); + static_assert(v[9]); + static_assert(!v[10]); + static_assert(!v[11]); + static_assert(!v[12]); + static_assert(!v[13]); + static_assert(!v[14]); + static_assert(!v[15]); + + static_assert(v[16]); + static_assert(v[17]); + static_assert(v[18]); + static_assert(v[19]); + static_assert(v[20]); + static_assert(v[21]); + static_assert(v[22]); + static_assert(v[23]); + + static_assert(v[24]); + static_assert(v[25]); + static_assert(v[26]); + static_assert(!v[27]); + static_assert(v[28]); + static_assert(v[29]); + static_assert(v[30]); + static_assert(!v[31]); +#endif + + struct pad { + unsigned short s; + unsigned char c; + }; + + constexpr auto p = bit_cast(v); + static_assert(p.s == (LITTLE_END ? 0xffee : 0xa1c0)); + static_assert(p.c == (LITTLE_END ? 0xc0 : 0xff)); +} + +namespace TwoShorts { + struct B { + unsigned short s0 : 8; + unsigned short s1 : 8; + }; + constexpr struct { unsigned short b1;} T = {0xc0ff}; + constexpr B MB = __builtin_bit_cast(B, T); +#if LITTLE_END + static_assert(MB.s0 == 0xff); + static_assert(MB.s1 == 0xc0); +#else + static_assert(MB.s0 == 0xc0); + static_assert(MB.s1 == 0xff); + +#endif +} + +typedef bool bool8 __attribute__((ext_vector_type(8))); +typedef bool bool9 __attribute__((ext_vector_type(9))); +typedef bool bool16 __attribute__((ext_vector_type(16))); +typedef bool bool17 __attribute__((ext_vector_type(17))); +typedef bool bool32 __attribute__((ext_vector_type(32))); +typedef bool bool128 __attribute__((ext_vector_type(128))); + +static_assert(bit_cast(bool8{1,0,1,0,1,0,1,0}) == (LITTLE_END ? 0x55 : 0xAA), ""); +constexpr bool8 b8 = __builtin_bit_cast(bool8, 0x55); // both-error {{'__builtin_bit_cast' source type 'int' does not match destination type 'bool8' (vector of 8 'bool' values) (4 vs 1 bytes)}} +static_assert(check_round_trip(static_cast(0)), ""); +static_assert(check_round_trip(static_cast(1)), ""); +static_assert(check_round_trip(static_cast(0x55)), ""); + +static_assert(bit_cast(bool16{1,1,1,1,1,0,0,0, 1,1,1,1,0,1,0,0}) == (LITTLE_END ? 0x2F1F : 0xF8F4), ""); + +static_assert(check_round_trip(static_cast(0xCAFE)), ""); +static_assert(check_round_trip(static_cast(0xCAFEBABE)), ""); + +#ifdef __SIZEOF_INT128__ +static_assert(check_round_trip(static_cast<__int128_t>(0xCAFEBABE0C05FEFEULL)), ""); +#endif + +static_assert(bit_cast, uint16_t>(0xcafe) == (LITTLE_END ? 0x95 : 0x7f)); +static_assert(bit_cast, uint16_t>(0xcafe) == (LITTLE_END ? 0x2 : 0xf)); +static_assert(bit_cast, uint32_t>(0xa1cafe) == (LITTLE_END ? 0x4 : 0x5)); + +struct S { + // little endian: + // MSB .... .... LSB + // |y| |x| + // + // big endian + // MSB .... .... LSB + // |x| |y| + + unsigned char x : 4; + unsigned char y : 4; + + constexpr bool operator==(S const &other) const { + return x == other.x && y == other.y; + } +}; + +constexpr S s{0xa, 0xb}; +static_assert(bit_cast>(s) == (LITTLE_END ? 0xba : 0xab)); +static_assert(bit_cast>(s) == (LITTLE_END + ? 0xba & 0x7f + : (0xab & 0xfe) >> 1)); + +static_assert(round_trip>(s) == s); + +struct R { + unsigned int r : 31; + unsigned int : 0; + unsigned int : 32; + constexpr bool operator==(R const &other) const { + return r == other.r; + } + }; +using T = bits<31, signed long long>; +constexpr R r{0x4ac0ffee}; +constexpr T t = bit_cast(r); +static_assert(t == ((0xFFFFFFFF8 << 28) | 0x4ac0ffee)); // sign extension + +static_assert(round_trip(r) == r); +static_assert(round_trip(t) == t); + + +/// The oversized bitfield is an error on Windows and not just a warning. +#if !defined(_WIN32) +struct U { + // expected-warning@+1 {{exceeds the width of its type}} + uint32_t trunc : 33; + uint32_t u : 31; + constexpr bool operator==(U const &other) const { + return trunc == other.trunc && u == other.u; + } +}; +struct V { + uint64_t notrunc : 32; + uint64_t : 1; + uint64_t v : 31; + constexpr bool operator==(V const &other) const { + return notrunc == other.notrunc && v == other.v; + } +}; + +constexpr U u{static_cast(~0), 0x4ac0ffee}; +constexpr V v = bit_cast(u); +static_assert(v.v == 0x4ac0ffee); + +static_assert(round_trip(u) == u); +static_assert(round_trip(v) == v); + +constexpr auto w = bit_cast>(u); +static_assert(w == (LITTLE_END + ? 0x4ac0ffee & 0xFFF + : (0x4ac0ffee & (0xFFF << (31 - 12))) >> (31-12) + )); +#endif + + +namespace NestedStructures { + struct J { + struct { + uint16_t k : 12; + } K; + struct { + uint16_t l : 4; + } L; + }; + + static_assert(sizeof(J) == 4); + constexpr J j = bit_cast(0x8c0ffee5); + + static_assert(j.K.k == (LITTLE_END ? 0xee5 : 0x8c0)); + static_assert(j.L.l == 0xf /* yay symmetry */); + static_assert(bit_cast>(j) == 0xf); + struct N { + bits<12, uint16_t> k; + uint16_t : 16; + }; + static_assert(bit_cast(j).k == j.K.k); + + struct M { + bits<4, uint16_t, 0> m[2]; + constexpr bool operator==(const M& rhs) const { + return m[0] == rhs.m[0] && m[1] == rhs.m[1]; + }; + }; + #if LITTLE_END == 1 + constexpr uint16_t want[2] = {0x5, 0xf}; + #else + constexpr uint16_t want[2] = {0x8000, 0xf000}; + #endif + + static_assert(bit_cast(j) == bit_cast(want)); +} + +namespace Enums { + // ensure we're packed into the top 2 bits + constexpr int pad = LITTLE_END ? 6 : 0; + struct X + { + char : pad; + enum class direction: char { left, right, up, down } direction : 2; + }; + + constexpr X x = { X::direction::down }; + static_assert(bit_cast>(x) == -1); + static_assert(bit_cast>(x) == 3); + static_assert( + bit_cast((unsigned char)0x40).direction == X::direction::right); +} + +namespace IndeterminateBits { + struct S { + unsigned a : 13; + unsigned : 17; + unsigned b : 2; + }; + constexpr unsigned A = __builtin_bit_cast(unsigned, S{12, 3}); // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{indeterminate value can only initialize an object of type 'unsigned char' or 'std::byte'; 'unsigned int' is invalid}} + + + /// GCC refuses to compile this as soon as we access the indeterminate bits + /// in the static_assert. MSVC accepts it. + struct S2 { + unsigned char a : 2; + }; + constexpr unsigned char B = __builtin_bit_cast(unsigned char, S2{3}); + static_assert(B == (LITTLE_END ? 3 : 192)); + + + + struct S3 { + unsigned a : 13; + unsigned : 17; + unsigned b : 2; + }; + + struct D { + unsigned a; + }; + constexpr D s = __builtin_bit_cast(D, S3{12, 3}); // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{indeterminate value can only initialize an object of type 'unsigned char' or 'std::byte'; 'unsigned int' is invalid}} + +} diff --git a/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp b/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp index 0929f7cb70b74..710612bef8fd0 100644 --- a/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp +++ b/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp @@ -6,7 +6,10 @@ // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fno-signed-char -fexperimental-new-constant-interpreter // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s -fexperimental-new-constant-interpreter +#if !__x86_64 // both-no-diagnostics +#endif + typedef decltype(nullptr) nullptr_t; typedef __INTPTR_TYPE__ intptr_t; @@ -35,6 +38,7 @@ constexpr Init round_trip(const Init &init) { namespace test_long_double { #if __x86_64 +/// FIXME: We could enable this, but since it aborts, it causes the usual mempory leak. #if 0 constexpr __int128_t test_cast_to_int128 = bit_cast<__int128_t>((long double)0); // expected-error{{must be initialized by a constant expression}}\ // expected-note{{in call}} @@ -49,7 +53,13 @@ static_assert(round_trip(ld), ""); static_assert(round_trip(10.0L)); -#if 0 +constexpr long double foo() { + bytes A = __builtin_bit_cast(bytes, ld); + long double ld = __builtin_bit_cast(long double, A); + return ld; +} +static_assert(foo() == ld); + constexpr bool f(bool read_uninit) { bytes b = bit_cast(ld); unsigned char ld_bytes[10] = { @@ -61,16 +71,15 @@ constexpr bool f(bool read_uninit) { if (ld_bytes[i] != b.d[i]) return false; - if (read_uninit && b.d[10]) // expected-note{{read of uninitialized object is not allowed in a constant expression}} + if (read_uninit && b.d[10]) // both-note{{read of uninitialized object is not allowed in a constant expression}} return false; return true; } static_assert(f(/*read_uninit=*/false), ""); -static_assert(f(/*read_uninit=*/true), ""); // expected-error{{static assertion expression is not an integral constant expression}} \ - // expected-note{{in call to 'f(true)'}} -#endif +static_assert(f(/*read_uninit=*/true), ""); // both-error{{static assertion expression is not an integral constant expression}} \ + // both-note{{in call to 'f(true)'}} constexpr bytes ld539 = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0x86, diff --git a/clang/test/AST/ByteCode/builtin-bit-cast.cpp b/clang/test/AST/ByteCode/builtin-bit-cast.cpp index 0fecde59cd57c..e99ab3904c339 100644 --- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp +++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp @@ -130,11 +130,13 @@ namespace simple { static_assert(check_round_trip((int)0x0C05FEFE)); static_assert(round_trip((int)0x0C05FEFE)); + static_assert(__builtin_bit_cast(intptr_t, nullptr) == 0); // both-error {{not an integral constant expression}} \ + // both-note {{indeterminate value can only initialize an object}} - /// This works in GCC and in the bytecode interpreter, but the current interpreter - /// diagnoses it. - static_assert(__builtin_bit_cast(intptr_t, nullptr) == 0); // ref-error {{not an integral constant expression}} \ - // ref-note {{indeterminate value can only initialize an object}} + constexpr int test_from_nullptr_pass = (__builtin_bit_cast(unsigned char[sizeof(nullptr)], nullptr), 0); + constexpr unsigned char NPData[sizeof(nullptr)] = {1,2,3,4}; + constexpr nullptr_t NP = __builtin_bit_cast(nullptr_t, NPData); + static_assert(NP == nullptr); } namespace Fail { @@ -186,72 +188,6 @@ namespace bitint { // ref-note {{initializer of 'IB' is not a constant expression}} } -namespace BitFields { - struct BitFields { - unsigned a : 2; - unsigned b : 30; - }; - - constexpr unsigned A = __builtin_bit_cast(unsigned, BitFields{3, 16}); // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{not yet supported}} \ - // ref-note {{declared here}} - static_assert(A == (LITTLE_END ? 67 : 3221225488)); // ref-error {{not an integral constant expression}} \ - // ref-note {{initializer of 'A'}} - - - void bitfield_indeterminate() { - struct BF { unsigned char z : 2; }; - enum byte : unsigned char {}; - - constexpr BF bf = {0x3}; - /// Requires bitcasts to composite types. - // static_assert(bit_cast>(bf).bits == bf.z); - // static_assert(bit_cast(bf)); - -#if 0 - // static_assert(__builtin_bit_cast(byte, bf)); - - struct M { - // expected-note@+1 {{subobject declared here}} - unsigned char mem[sizeof(BF)]; - }; - // expected-error@+2 {{initialized by a constant expression}} - // expected-note@+1 {{not initialized}} - constexpr M m = bit_cast(bf); - - constexpr auto f = []() constexpr { - // bits<24, unsigned int, LITTLE_END ? 0 : 8> B = {0xc0ffee}; - constexpr struct { unsigned short b1; unsigned char b0; } B = {0xc0ff, 0xee}; - return bit_cast>(B); - }; - - static_assert(f()[0] + f()[1] + f()[2] == 0xc0 + 0xff + 0xee); - { - // expected-error@+2 {{initialized by a constant expression}} - // expected-note@+1 {{read of uninitialized object is not allowed in a constant expression}} - constexpr auto _bad = f()[3]; - } - - struct B { - unsigned short s0 : 8; - unsigned short s1 : 8; - std::byte b0 : 4; - std::byte b1 : 4; - std::byte b2 : 4; - }; - constexpr auto g = [f]() constexpr { - return bit_cast(f()); - }; - static_assert(g().s0 + g().s1 + g().b0 + g().b1 == 0xc0 + 0xff + 0xe + 0xe); - { - // expected-error@+2 {{initialized by a constant expression}} - // expected-note@+1 {{read of uninitialized object is not allowed in a constant expression}} - constexpr auto _bad = g().b2; - } -#endif - } -} - namespace Classes { class A { public: @@ -331,6 +267,21 @@ static_assert(check_round_trip(splice)); #endif +namespace Overread { + /// This used to crash becaus we were reading all elements of the + /// source array even though we should only be reading 1. + constexpr int a[] = {2,3, 4, 5}; + constexpr int b = __builtin_bit_cast(int, *(a + 1)); + static_assert(b == 3); + + struct S { + int a; + }; + constexpr S ss[] = {{1},{2}}; + constexpr int c = __builtin_bit_cast(int, *(ss + 1)); + static_assert(c == 2); +} + /// --------------------------------------------------------------------------- /// From here on, it's things copied from test/SemaCXX/constexpr-builtin-bit.cast.cpp @@ -401,9 +352,8 @@ void test_record() { static_assert(t4 == tuple4{1, 2, 3, 4}); static_assert(check_round_trip(b)); - /// FIXME: We need to initialize the base pointers in the pointer we're bitcasting to. -// constexpr auto b2 = bit_cast(t4); -// static_assert(t4 == b2); + constexpr auto b2 = bit_cast(t4); + static_assert(t4 == b2); } void test_partially_initialized() { @@ -440,7 +390,6 @@ void bad_types() { }; static_assert(__builtin_bit_cast(int, X{0}) == 0); // both-error {{not an integral constant expression}} \ // both-note {{bit_cast from a union type is not allowed in a constant expression}} -#if 1 struct G { int g; @@ -451,19 +400,17 @@ void bad_types() { // both-error@+2 {{constexpr variable 'x' must be initialized by a constant expression}} // both-note@+1 {{bit_cast to a union type is not allowed in a constant expression}} constexpr X x = __builtin_bit_cast(X, G{0}); -#endif + struct has_pointer { - int *ptr; // both-note {{invalid type 'int *' is a member of 'has_pointer'}} + int *ptr; // both-note 2{{invalid type 'int *' is a member of 'has_pointer'}} }; constexpr intptr_t ptr = __builtin_bit_cast(intptr_t, has_pointer{0}); // both-error {{constexpr variable 'ptr' must be initialized by a constant expression}} \ // both-note {{bit_cast from a pointer type is not allowed in a constant expression}} -#if 0 - // expected-error@+2 {{constexpr variable 'hptr' must be initialized by a constant expression}} - // expected-note@+1 {{bit_cast to a pointer type is not allowed in a constant expression}} - constexpr has_pointer hptr = __builtin_bit_cast(has_pointer, 0ul); -#endif + // both-error@+2 {{constexpr variable 'hptr' must be initialized by a constant expression}} + // both-note@+1 {{bit_cast to a pointer type is not allowed in a constant expression}} + constexpr has_pointer hptr = __builtin_bit_cast(has_pointer, (intptr_t)0); } void test_array_fill() { @@ -510,27 +457,6 @@ static_assert(bit_cast(test_vector) == (LITTLE_END static_assert(check_round_trip(0xCAFEBABE0C05FEFEULL), ""); static_assert(check_round_trip(0xCAFEBABE0C05FEFEULL), ""); -typedef bool bool8 __attribute__((ext_vector_type(8))); -typedef bool bool9 __attribute__((ext_vector_type(9))); -typedef bool bool16 __attribute__((ext_vector_type(16))); -typedef bool bool17 __attribute__((ext_vector_type(17))); -typedef bool bool32 __attribute__((ext_vector_type(32))); -typedef bool bool128 __attribute__((ext_vector_type(128))); - -static_assert(bit_cast(bool8{1,0,1,0,1,0,1,0}) == (LITTLE_END ? 0x55 : 0xAA), ""); -constexpr bool8 b8 = __builtin_bit_cast(bool8, 0x55); // both-error {{'__builtin_bit_cast' source type 'int' does not match destination type 'bool8' (vector of 8 'bool' values) (4 vs 1 bytes)}} -#if 0 -static_assert(check_round_trip(static_cast(0)), ""); -static_assert(check_round_trip(static_cast(1)), ""); -static_assert(check_round_trip(static_cast(0x55)), ""); - -static_assert(bit_cast(bool16{1,1,1,1,1,0,0,0, 1,1,1,1,0,1,0,0}) == (LITTLE_END ? 0x2F1F : 0xF8F4), ""); - -static_assert(check_round_trip(static_cast(0xCAFE)), ""); -static_assert(check_round_trip(static_cast(0xCAFEBABE)), ""); -static_assert(check_round_trip(static_cast<__int128_t>(0xCAFEBABE0C05FEFEULL)), ""); -#endif - #if 0 // expected-error@+2 {{constexpr variable 'bad_bool9_to_short' must be initialized by a constant expression}} // expected-note@+1 {{bit_cast involving type 'bool __attribute__((ext_vector_type(9)))' (vector of 9 'bool' values) is not allowed in a constant expression; element size 1 * element count 9 is not a multiple of the byte size 8}} @@ -559,3 +485,20 @@ namespace test_complex { constexpr double D = __builtin_bit_cast(double, test_float_complex); constexpr int M = __builtin_bit_cast(int, test_int_complex); // both-error {{size of '__builtin_bit_cast' source type 'const _Complex unsigned int' does not match destination type 'int' (8 vs 4 bytes)}} } + + +namespace OversizedBitField { +#if defined(_WIN32) + /// This is an error (not just a warning) on Windows and the field ends up with a size of 1 instead of 4. +#else + typedef unsigned __INT16_TYPE__ uint16_t; + typedef unsigned __INT32_TYPE__ uint32_t; + struct S { + uint16_t a : 20; // both-warning {{exceeds the width of its type}} + }; + + static_assert(sizeof(S) == 4); + static_assert(__builtin_bit_cast(S, (uint32_t)32).a == (LITTLE_END ? 32 : 0)); // ref-error {{not an integral constant expression}} \ + // ref-note {{constexpr bit_cast involving bit-field is not yet supported}} +#endif +} diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp index f70b77fe74636..a67b6b665f379 100644 --- a/clang/test/AST/ByteCode/builtin-functions.cpp +++ b/clang/test/AST/ByteCode/builtin-functions.cpp @@ -15,6 +15,10 @@ #error "huh?" #endif +extern "C" { + typedef decltype(sizeof(int)) size_t; + extern size_t wcslen(const wchar_t *p); +} namespace strcmp { constexpr char kFoobar[6] = {'f','o','o','b','a','r'}; @@ -47,6 +51,15 @@ namespace strcmp { return __builtin_strcmp(buffer, "mutable") == 0; } static_assert(char_memchr_mutable(), ""); + + static_assert(__builtin_strncmp("abaa", "abba", 5) == -1); + static_assert(__builtin_strncmp("abaa", "abba", 4) == -1); + static_assert(__builtin_strncmp("abaa", "abba", 3) == -1); + static_assert(__builtin_strncmp("abaa", "abba", 2) == 0); + static_assert(__builtin_strncmp("abaa", "abba", 1) == 0); + static_assert(__builtin_strncmp("abaa", "abba", 0) == 0); + static_assert(__builtin_strncmp(0, 0, 0) == 0); + static_assert(__builtin_strncmp("abab\0banana", "abab\0canada", 100) == 0); } /// Copied from constant-expression-cxx11.cpp @@ -93,6 +106,14 @@ constexpr const char *a = "foo\0quux"; constexpr char d[] = { 'f', 'o', 'o' }; // no nul terminator. constexpr int bad = __builtin_strlen(d); // both-error {{constant expression}} \ // both-note {{one-past-the-end}} + + constexpr int wn = __builtin_wcslen(L"hello"); + static_assert(wn == 5); + constexpr int wm = wcslen(L"hello"); // both-error {{constant expression}} \ + // both-note {{non-constexpr function 'wcslen' cannot be used in a constant expression}} + + int arr[3]; // both-note {{here}} + int wk = arr[wcslen(L"hello")]; // both-warning {{array index 5}} } namespace nan { @@ -1151,6 +1172,13 @@ namespace BuiltinMemcpy { } static_assert(simple() == 12); + constexpr bool arrayMemcpy() { + char src[] = "abc"; + char dst[4] = {}; + __builtin_memcpy(dst, src, 4); + return dst[0] == 'a' && dst[1] == 'b' && dst[2] == 'c' && dst[3] == '\0'; + } + static_assert(arrayMemcpy()); extern struct Incomplete incomplete; constexpr struct Incomplete *null_incomplete = 0; @@ -1169,4 +1197,14 @@ namespace BuiltinMemcpy { return b; } static_assert(simpleMove() == 12); + + constexpr int memcpyTypeRem() { // ref-error {{never produces a constant expression}} + int a = 12; + int b = 0; + __builtin_memmove(&b, &a, 1); // both-note {{'memmove' not supported: size to copy (1) is not a multiple of size of element type 'int'}} \ + // ref-note {{not supported}} + return b; + } + static_assert(memcpyTypeRem() == 12); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} } diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl new file mode 100644 index 0000000000000..909cce17e344c --- /dev/null +++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \ +// RUN: -DRESOURCE=ByteAddressBuffer %s | FileCheck -DRESOURCE=ByteAddressBuffer \ +// RUN: -check-prefix=EMPTY %s +// +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \ +// RUN: -DRESOURCE=ByteAddressBuffer %s | FileCheck -DRESOURCE=ByteAddressBuffer \ +// RUN: -check-prefixes=CHECK,CHECK-SRV,CHECK-NOSUBSCRIPT %s +// +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \ +// RUN: -DRESOURCE=RWByteAddressBuffer %s | FileCheck -DRESOURCE=RWByteAddressBuffer \ +// RUN: -check-prefix=EMPTY %s +// +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \ +// RUN: -DRESOURCE=RWByteAddressBuffer %s | FileCheck -DRESOURCE=RWByteAddressBuffer \ +// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-NOSUBSCRIPT %s +// +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \ +// RUN: -DRESOURCE=RasterizerOrderedByteAddressBuffer %s | FileCheck -DRESOURCE=RasterizerOrderedByteAddressBuffer \ +// RUN: -check-prefix=EMPTY %s +// +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \ +// RUN: -DRESOURCE=RasterizerOrderedByteAddressBuffer %s | FileCheck -DRESOURCE=RasterizerOrderedByteAddressBuffer \ +// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-NOSUBSCRIPT %s + +// EMPTY: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class [[RESOURCE]] +// EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final + +// There should be no more occurrences of RESOURCE +// EMPTY-NOT: {{[^[:alnum:]]}}[[RESOURCE]] + +#ifndef EMPTY + +RESOURCE Buffer; + +#endif + +// CHECK: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit referenced class [[RESOURCE]] definition + + +// CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit __handle '__hlsl_resource_t +// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] +// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] +// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(char8_t)]] +// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit RawBuffer + +// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'const element_type &(unsigned int) const' +// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'element_type &(unsigned int)' diff --git a/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp b/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp index 04cff07376885..1b385e0fc3331 100644 --- a/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp +++ b/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp @@ -9,7 +9,7 @@ int main() { S s; int x = s.f(); // CHECK: CallExpr 0x{{[^ ]*}} 'int - // CHECK-NEXT: |-ImplicitCastExpr 0x{{[^ ]*}} 'int (*)(S &)' - // CHECK-NEXT: | `-DeclRefExpr 0x{{[^ ]*}} 'int (S &)' lvalue CXXMethod 0x{{[^ ]*}} 'f' 'int (S &)' + // CHECK-NEXT: |-ImplicitCastExpr 0x{{[^ ]*}} 'int (*)(S &)' + // CHECK-NEXT: | `-DeclRefExpr 0x{{[^ ]*}} 'int (S &)' lvalue CXXMethod 0x{{[^ ]*}} 'f' 'int (S &)' } } diff --git a/clang/test/AST/ast-dump-types-json.cpp b/clang/test/AST/ast-dump-types-json.cpp index c1bb9266fa869..fa1fb53df0e85 100644 --- a/clang/test/AST/ast-dump-types-json.cpp +++ b/clang/test/AST/ast-dump-types-json.cpp @@ -248,15 +248,24 @@ using ::TestUsingShadowDeclType; // CHECK-NEXT: "inner": [ // CHECK-NEXT: { // CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "RecordType", +// CHECK-NEXT: "kind": "ElaboratedType", // CHECK-NEXT: "type": { // CHECK-NEXT: "qualType": "T" // CHECK-NEXT: }, -// CHECK-NEXT: "decl": { -// CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "CXXRecordDecl", -// CHECK-NEXT: "name": "T" -// CHECK-NEXT: } +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "RecordType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "T" +// CHECK-NEXT: }, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "name": "T" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "id": "0x{{.*}}", @@ -325,15 +334,24 @@ using ::TestUsingShadowDeclType; // CHECK-NEXT: "inner": [ // CHECK-NEXT: { // CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "RecordType", +// CHECK-NEXT: "kind": "ElaboratedType", // CHECK-NEXT: "type": { // CHECK-NEXT: "qualType": "T" // CHECK-NEXT: }, -// CHECK-NEXT: "decl": { -// CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "CXXRecordDecl", -// CHECK-NEXT: "name": "T" -// CHECK-NEXT: } +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "RecordType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "T" +// CHECK-NEXT: }, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "name": "T" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "id": "0x{{.*}}", diff --git a/clang/test/AST/ast-print-openacc-combined-construct.cpp b/clang/test/AST/ast-print-openacc-combined-construct.cpp index 435c770c7457d..1a11f036b07ae 100644 --- a/clang/test/AST/ast-print-openacc-combined-construct.cpp +++ b/clang/test/AST/ast-print-openacc-combined-construct.cpp @@ -242,4 +242,148 @@ void foo() { #pragma acc parallel loop vector_length((int)array[1]) for(int i = 0;i<5;++i); +// CHECK: #pragma acc parallel loop gang(dim: 2) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop gang(dim:2) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc serial loop gang(static: i) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc serial loop gang(static:i) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc parallel loop gang(static: i) gang(dim: 2) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop gang(static:i) gang(dim:2) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc parallel loop gang(static: i, dim: 2) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop gang(static:i, dim:2) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc parallel loop gang(dim: 2) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop gang(dim:2) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc parallel loop gang(static: i) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop gang(static:i) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc parallel loop gang(static: i) gang(dim: 2) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop gang(static:i) gang(dim:2) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc parallel loop gang(static: i, dim: 2) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop gang(static:i, dim:2) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc kernels loop gang(num: i) gang(static: i) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels loop gang(i) gang(static:i) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc kernels loop gang(num: i) gang(static: i) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels loop gang(num:i) gang(static:i) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc serial loop gang(static: i) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc serial loop gang(static:i) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc serial loop gang(static: *) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc serial loop gang(static:*) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc parallel loop worker +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop worker + for(int i = 0;i<5;++i); + +// CHECK-NEXT: #pragma acc parallel loop worker +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop worker + for(int i = 0;i<5;++i); + +// CHECK-NEXT: #pragma acc serial loop worker +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc serial loop worker + for(int i = 0;i<5;++i); + +// CHECK-NEXT: #pragma acc kernels loop worker(num: 5) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels loop worker(5) + for(int i = 0;i<5;++i); + +// CHECK-NEXT: #pragma acc kernels loop worker(num: 5) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels loop worker(num:5) + for(int i = 0;i<5;++i); + + // CHECK: #pragma acc parallel loop vector +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop vector + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc parallel loop vector(length: 5) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop vector(5) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc parallel loop vector(length: 5) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop vector(length:5) + for(int i = 0;i<5;++i); + +// CHECK-NEXT: #pragma acc kernels loop vector +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels loop vector + for(int i = 0;i<5;++i); + +// CHECK-NEXT: #pragma acc kernels loop vector(length: 5) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels loop vector(5) + for(int i = 0;i<5;++i); + +// CHECK-NEXT: #pragma acc kernels loop vector(length: 5) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels loop vector(length:5) + for(int i = 0;i<5;++i); + +// CHECK-NEXT: #pragma acc serial loop vector +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc serial loop vector + for(int i = 0;i<5;++i); + } diff --git a/clang/test/AST/ms-constexpr-new.cpp b/clang/test/AST/ms-constexpr-new.cpp new file mode 100644 index 0000000000000..4b534cf020764 --- /dev/null +++ b/clang/test/AST/ms-constexpr-new.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -ast-dump %s | FileCheck %s + +// CHECK: used operator new +// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} +[[nodiscard]] [[msvc::constexpr]] inline void* __cdecl operator new(decltype(sizeof(void*)), void* p) noexcept { return p; } + +// CHECK: used constexpr construct_at +// CHECK: AttributedStmt 0x{{[0-9a-f]+}} +// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} +// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} +constexpr int* construct_at(int* p, int v) { [[msvc::constexpr]] return ::new (p) int(v); } +constexpr bool check_construct_at() { int x; return *construct_at(&x, 42) == 42; } +static_assert(check_construct_at()); diff --git a/clang/test/Analysis/Checkers/WebKit/memory-unsafe-cast.cpp b/clang/test/Analysis/Checkers/WebKit/memory-unsafe-cast.cpp new file mode 100644 index 0000000000000..62c945c7a2c24 --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/memory-unsafe-cast.cpp @@ -0,0 +1,266 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.MemoryUnsafeCastChecker -verify %s + +class Base { }; +class Derived : public Base { }; + +template +Target& downcast_ref(Source& source){ + [[clang::suppress]] + return static_cast(source); +} + +template +Target* downcast_ptr(Source* source){ + [[clang::suppress]] + return static_cast(source); +} + +void test_pointers(Base *base) { + Derived *derived_static = static_cast(base); + // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}} + Derived *derived_reinterpret = reinterpret_cast(base); + // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}} + Derived *derived_c = (Derived*)base; + // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}} + Derived *derived_d = downcast_ptr(base); // no warning +} + +void test_non_pointers(Derived derived) { + Base base_static = static_cast(derived); // no warning +} + +void test_refs(Base &base) { + Derived &derived_static = static_cast(base); + // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}} + Derived &derived_reinterpret = reinterpret_cast(base); + // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}} + Derived &derived_c = (Derived&)base; + // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}} + Derived &derived_d = downcast_ref(base); // no warning +} + +class BaseVirtual { + virtual void virtual_base_function(); +}; + +class DerivedVirtual : public BaseVirtual { + void virtual_base_function() override { } +}; + +void test_dynamic_casts(BaseVirtual *base_ptr, BaseVirtual &base_ref) { + DerivedVirtual *derived_dynamic_ptr = dynamic_cast(base_ptr); + // expected-warning@-1{{Unsafe cast from base type 'BaseVirtual' to derived type 'DerivedVirtual'}} + DerivedVirtual &derived_dynamic_ref = dynamic_cast(base_ref); + // expected-warning@-1{{Unsafe cast from base type 'BaseVirtual' to derived type 'DerivedVirtual'}} +} + +struct BaseStruct { }; +struct DerivedStruct : BaseStruct { }; + +void test_struct_pointers(struct BaseStruct *base_struct) { + struct DerivedStruct *derived_static = static_cast(base_struct); + // expected-warning@-1{{Unsafe cast from base type 'BaseStruct' to derived type 'DerivedStruct'}} + struct DerivedStruct *derived_reinterpret = reinterpret_cast(base_struct); + // expected-warning@-1{{Unsafe cast from base type 'BaseStruct' to derived type 'DerivedStruct'}} + struct DerivedStruct *derived_c = (struct DerivedStruct*)base_struct; + // expected-warning@-1{{Unsafe cast from base type 'BaseStruct' to derived type 'DerivedStruct'}} +} + +typedef struct BaseStruct BStruct; +typedef struct DerivedStruct DStruct; + +void test_struct_refs(BStruct &base_struct) { + DStruct &derived_static = static_cast(base_struct); + // expected-warning@-1{{Unsafe cast from base type 'BaseStruct' to derived type 'DerivedStruct'}} + DStruct &derived_reinterpret = reinterpret_cast(base_struct); + // expected-warning@-1{{Unsafe cast from base type 'BaseStruct' to derived type 'DerivedStruct'}} + DStruct &derived_c = (DStruct&)base_struct; + // expected-warning@-1{{Unsafe cast from base type 'BaseStruct' to derived type 'DerivedStruct'}} +} + +int counter = 0; +void test_recursive(BStruct &base_struct) { + if (counter == 5) + return; + counter++; + DStruct &derived_static = static_cast(base_struct); + // expected-warning@-1{{Unsafe cast from base type 'BaseStruct' to derived type 'DerivedStruct'}} +} + +template +class BaseTemplate { }; + +template +class DerivedTemplate : public BaseTemplate { }; + +void test_templates(BaseTemplate *base, BaseTemplate &base_ref) { + DerivedTemplate *derived_static = static_cast*>(base); + // expected-warning@-1{{Unsafe cast from base type 'BaseTemplate' to derived type 'DerivedTemplate'}} + DerivedTemplate *derived_reinterpret = reinterpret_cast*>(base); + // expected-warning@-1{{Unsafe cast from base type 'BaseTemplate' to derived type 'DerivedTemplate'}} + DerivedTemplate *derived_c = (DerivedTemplate*)base; + // expected-warning@-1{{Unsafe cast from base type 'BaseTemplate' to derived type 'DerivedTemplate'}} + DerivedTemplate &derived_static_ref = static_cast&>(base_ref); + // expected-warning@-1{{Unsafe cast from base type 'BaseTemplate' to derived type 'DerivedTemplate'}} + DerivedTemplate &derived_reinterpret_ref = reinterpret_cast&>(base_ref); + // expected-warning@-1{{Unsafe cast from base type 'BaseTemplate' to derived type 'DerivedTemplate'}} + DerivedTemplate &derived_c_ref = (DerivedTemplate&)base_ref; + // expected-warning@-1{{Unsafe cast from base type 'BaseTemplate' to derived type 'DerivedTemplate'}} +} + +#define CAST_MACRO_STATIC(X,Y) (static_cast(X)) +#define CAST_MACRO_REINTERPRET(X,Y) (reinterpret_cast(X)) +#define CAST_MACRO_C(X,Y) ((Y)X) + +void test_macro_static(Base *base, Derived *derived, Base &base_ref) { + Derived *derived_static = CAST_MACRO_STATIC(base, Derived*); + // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}} + Derived &derived_static_ref = CAST_MACRO_STATIC(base_ref, Derived&); + // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}} + Base *base_static_same = CAST_MACRO_STATIC(base, Base*); // no warning + Base *base_static_upcast = CAST_MACRO_STATIC(derived, Base*); // no warning +} + +void test_macro_reinterpret(Base *base, Derived *derived, Base &base_ref) { + Derived *derived_reinterpret = CAST_MACRO_REINTERPRET(base, Derived*); + // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}} + Derived &derived_reinterpret_ref = CAST_MACRO_REINTERPRET(base_ref, Derived&); + // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}} + Base *base_reinterpret_same = CAST_MACRO_REINTERPRET(base, Base*); // no warning + Base *base_reinterpret_upcast = CAST_MACRO_REINTERPRET(derived, Base*); // no warning +} + +void test_macro_c(Base *base, Derived *derived, Base &base_ref) { + Derived *derived_c = CAST_MACRO_C(base, Derived*); + // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}} + Derived &derived_c_ref = CAST_MACRO_C(base_ref, Derived&); + // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}} + Base *base_c_same = CAST_MACRO_C(base, Base*); // no warning + Base *base_c_upcast = CAST_MACRO_C(derived, Base*); // no warning +} + +struct BaseStructCpp { + int t; + void increment() { t++; } +}; +struct DerivedStructCpp : BaseStructCpp { + void increment_t() {increment();} +}; + +void test_struct_cpp_pointers(struct BaseStructCpp *base_struct) { + struct DerivedStructCpp *derived_static = static_cast(base_struct); + // expected-warning@-1{{Unsafe cast from base type 'BaseStructCpp' to derived type 'DerivedStructCpp'}} + struct DerivedStructCpp *derived_reinterpret = reinterpret_cast(base_struct); + // expected-warning@-1{{Unsafe cast from base type 'BaseStructCpp' to derived type 'DerivedStructCpp'}} + struct DerivedStructCpp *derived_c = (struct DerivedStructCpp*)base_struct; + // expected-warning@-1{{Unsafe cast from base type 'BaseStructCpp' to derived type 'DerivedStructCpp'}} +} + +typedef struct BaseStructCpp BStructCpp; +typedef struct DerivedStructCpp DStructCpp; + +void test_struct_cpp_refs(BStructCpp &base_struct, DStructCpp &derived_struct) { + DStructCpp &derived_static = static_cast(base_struct); + // expected-warning@-1{{Unsafe cast from base type 'BaseStructCpp' to derived type 'DerivedStructCpp'}} + DStructCpp &derived_reinterpret = reinterpret_cast(base_struct); + // expected-warning@-1{{Unsafe cast from base type 'BaseStructCpp' to derived type 'DerivedStructCpp'}} + DStructCpp &derived_c = (DStructCpp&)base_struct; + // expected-warning@-1{{Unsafe cast from base type 'BaseStructCpp' to derived type 'DerivedStructCpp'}} + BStructCpp &base = (BStructCpp&)derived_struct; // no warning + BStructCpp &base_static = static_cast(derived_struct); // no warning + BStructCpp &base_reinterpret = reinterpret_cast(derived_struct); // no warning +} + +struct stack_st { }; + +#define STACK_OF(type) struct stack_st_##type + +void test_stack(stack_st *base) { + STACK_OF(void) *derived = (STACK_OF(void)*)base; + // expected-warning@-1{{Unsafe cast from type 'stack_st' to an unrelated type 'stack_st_void'}} +} + +class Parent { }; +class Child1 : public Parent { }; +class Child2 : public Parent { }; + +void test_common_parent(Child1 *c1, Child2 *c2) { + Child2 *c2_cstyle = (Child2 *)c1; + // expected-warning@-1{{Unsafe cast from type 'Child1' to an unrelated type 'Child2'}} + Child2 *c2_reinterpret = reinterpret_cast(c1); + // expected-warning@-1{{Unsafe cast from type 'Child1' to an unrelated type 'Child2'}} +} + +class Type1 { }; +class Type2 { }; + +void test_unrelated_ref(Type1 &t1, Type2 &t2) { + Type2 &t2_cstyle = (Type2 &)t1; + // expected-warning@-1{{Unsafe cast from type 'Type1' to an unrelated type 'Type2'}} + Type2 &t2_reinterpret = reinterpret_cast(t1); + // expected-warning@-1{{Unsafe cast from type 'Type1' to an unrelated type 'Type2'}} + Type2 &t2_same = reinterpret_cast(t2); // no warning +} + + +class VirtualClass1 { + virtual void virtual_base_function(); +}; + +class VirtualClass2 { + void virtual_base_function(); +}; + +void test_unrelated_virtual(VirtualClass1 &v1) { + VirtualClass2 &v2 = dynamic_cast(v1); + // expected-warning@-1{{Unsafe cast from type 'VirtualClass1' to an unrelated type 'VirtualClass2'}} +} + +struct StructA { }; +struct StructB { }; + +typedef struct StructA StA; +typedef struct StructB StB; + +void test_struct_unrelated_refs(StA &a, StB &b) { + StB &b_reinterpret = reinterpret_cast(a); + // expected-warning@-1{{Unsafe cast from type 'StructA' to an unrelated type 'StructB'}} + StB &b_c = (StB&)a; + // expected-warning@-1{{Unsafe cast from type 'StructA' to an unrelated type 'StructB'}} + StA &a_local = (StA&)b; + // expected-warning@-1{{Unsafe cast from type 'StructB' to an unrelated type 'StructA'}} + StA &a_reinterpret = reinterpret_cast(b); + // expected-warning@-1{{Unsafe cast from type 'StructB' to an unrelated type 'StructA'}} + StA &a_same = (StA&)a; // no warning +} + +template +class DeferrableRefCounted { +public: + void deref() const { + auto this_to_T = static_cast(this); // no warning + } +}; + +class SomeArrayClass : public DeferrableRefCounted { }; + +void test_this_to_template(SomeArrayClass *ptr) { + ptr->deref(); +}; + +template +class CanMakeWeakPtrBase { +public: + void initializeWeakPtrFactory() const { + auto &this_to_T = static_cast(*this); + } +}; + +template +using CanMakeWeakPtr = CanMakeWeakPtrBase; + +class EventLoop : public CanMakeWeakPtr { }; + +void test_this_to_template_ref(EventLoop *ptr) { + ptr->initializeWeakPtrFactory(); +}; diff --git a/clang/test/Analysis/Checkers/WebKit/memory-unsafe-cast.mm b/clang/test/Analysis/Checkers/WebKit/memory-unsafe-cast.mm new file mode 100644 index 0000000000000..f9046d7981784 --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/memory-unsafe-cast.mm @@ -0,0 +1,64 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.MemoryUnsafeCastChecker -verify %s + +@protocol NSObject ++alloc; +-init; +@end + +@interface NSObject {} +@end + +@interface BaseClass : NSObject +@end + +@interface DerivedClass : BaseClass +-(void)testCasts:(BaseClass*)base; +@end + +@implementation DerivedClass +-(void)testCasts:(BaseClass*)base { + DerivedClass *derived = (DerivedClass*)base; + // expected-warning@-1{{Unsafe cast from base type 'BaseClass' to derived type 'DerivedClass'}} + DerivedClass *derived_static = static_cast(base); + // expected-warning@-1{{Unsafe cast from base type 'BaseClass' to derived type 'DerivedClass'}} + DerivedClass *derived_reinterpret = reinterpret_cast(base); + // expected-warning@-1{{Unsafe cast from base type 'BaseClass' to derived type 'DerivedClass'}} + base = (BaseClass*)derived; // no warning + base = (BaseClass*)base; // no warning +} +@end + +template +class WrappedObject +{ +public: + T get() const { return mMetalObject; } + T mMetalObject = nullptr; +}; + +@protocol MTLCommandEncoder +@end +@protocol MTLRenderCommandEncoder +@end +class CommandEncoder : public WrappedObject> { }; + +class RenderCommandEncoder final : public CommandEncoder +{ +private: + id get() + { + return static_cast>(CommandEncoder::get()); + } +}; + +@interface Class1 +@end + +@interface Class2 +@end + +void testUnrelated(Class1 *c1) { + Class2 *c2 = (Class2*)c1; + // expected-warning@-1{{Unsafe cast from type 'Class1' to an unrelated type 'Class2'}} + Class1 *c1_same = reinterpret_cast(c1); // no warning +} diff --git a/clang/test/Analysis/reference.cpp b/clang/test/Analysis/reference.cpp index b893aec2a7d54..91ba3cd23249a 100644 --- a/clang/test/Analysis/reference.cpp +++ b/clang/test/Analysis/reference.cpp @@ -89,8 +89,8 @@ namespace PR13440 { S s = { a }; S2 s2 = { a }; - if (s.x != a) return; - if (s2.x != a) return; + if (s.x != a) return; // expected-warning {{comparison between two arrays}} + if (s2.x != a) return; // expected-warning {{comparison between two arrays}} a[0] = 42; clang_analyzer_eval(s.x[0] == 42); // expected-warning{{TRUE}} diff --git a/clang/test/CIR/global-var-simple.cpp b/clang/test/CIR/global-var-simple.cpp new file mode 100644 index 0000000000000..5230ff53f87d7 --- /dev/null +++ b/clang/test/CIR/global-var-simple.cpp @@ -0,0 +1,59 @@ +// Global variables of intergal types +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s + +char c; +// CHECK: cir.global @c : !cir.int + +signed char sc; +// CHECK: cir.global @sc : !cir.int + +unsigned char uc; +// CHECK: cir.global @uc : !cir.int + +short ss; +// CHECK: cir.global @ss : !cir.int + +unsigned short us; +// CHECK: cir.global @us : !cir.int + +int si; +// CHECK: cir.global @si : !cir.int + +unsigned ui; +// CHECK: cir.global @ui : !cir.int + +long sl; +// CHECK: cir.global @sl : !cir.int + +unsigned long ul; +// CHECK: cir.global @ul : !cir.int + +long long sll; +// CHECK: cir.global @sll : !cir.int + +unsigned long long ull; +// CHECK: cir.global @ull : !cir.int + +__int128 s128; +// CHECK: cir.global @s128 : !cir.int + +unsigned __int128 u128; +// CHECK: cir.global @u128 : !cir.int + +wchar_t wc; +// CHECK: cir.global @wc : !cir.int + +char8_t c8; +// CHECK: cir.global @c8 : !cir.int + +char16_t c16; +// CHECK: cir.global @c16 : !cir.int + +char32_t c32; +// CHECK: cir.global @c32 : !cir.int + +_BitInt(20) sb20; +// CHECK: cir.global @sb20 : !cir.int + +unsigned _BitInt(48) ub48; +// CHECK: cir.global @ub48 : !cir.int diff --git a/clang/test/CXX/conv/conv.mem/p4.cpp b/clang/test/CXX/conv/conv.mem/p4.cpp index d052b7927b32d..552c908a6610b 100644 --- a/clang/test/CXX/conv/conv.mem/p4.cpp +++ b/clang/test/CXX/conv/conv.mem/p4.cpp @@ -19,8 +19,8 @@ namespace test0 { namespace test1 { struct Derived : private Base {}; // expected-note 2 {{declared private here}} void test() { - int (Derived::*d) = data_ptr; // expected-error {{cannot cast private base class 'Base' to 'test1::Derived'}} - int (Derived::*m)() = method_ptr; // expected-error {{cannot cast private base class 'Base' to 'test1::Derived'}} + int (Derived::*d) = data_ptr; // expected-error {{cannot cast private base class 'Base' to 'Derived'}} + int (Derived::*m)() = method_ptr; // expected-error {{cannot cast private base class 'Base' to 'Derived'}} } }; @@ -30,8 +30,8 @@ namespace test2 { struct B : Base {}; struct Derived : A, B {}; void test() { - int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test2::Derived':}} - int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test2::Derived':}} + int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'Derived':}} + int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'Derived':}} } } @@ -39,8 +39,8 @@ namespace test2 { namespace test3 { struct Derived : virtual Base {}; void test() { - int (Derived::*d) = data_ptr; // expected-error {{conversion from pointer to member of class 'Base' to pointer to member of class 'test3::Derived' via virtual base 'Base' is not allowed}} - int (Derived::*m)() = method_ptr; // expected-error {{conversion from pointer to member of class 'Base' to pointer to member of class 'test3::Derived' via virtual base 'Base' is not allowed}} + int (Derived::*d) = data_ptr; // expected-error {{conversion from pointer to member of class 'Base' to pointer to member of class 'Derived' via virtual base 'Base' is not allowed}} + int (Derived::*m)() = method_ptr; // expected-error {{conversion from pointer to member of class 'Base' to pointer to member of class 'Derived' via virtual base 'Base' is not allowed}} } } @@ -49,8 +49,8 @@ namespace test4 { struct A : Base {}; struct Derived : Base, virtual A {}; // expected-warning {{direct base 'Base' is inaccessible due to ambiguity:\n struct test4::Derived -> Base\n struct test4::Derived -> A -> Base}} void test() { - int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test4::Derived':}} - int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test4::Derived':}} + int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'Derived':}} + int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'Derived':}} } } diff --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp index fe3e0cfc1d421..993b6f2923859 100644 --- a/clang/test/CXX/drs/cwg0xx.cpp +++ b/clang/test/CXX/drs/cwg0xx.cpp @@ -858,7 +858,7 @@ namespace cwg54 { // cwg54: 2.8 // expected-error@-1 {{cannot cast 'struct B' to its private base class 'A'}} // expected-note@#cwg54-B {{declared private here}} int A::*smab = static_cast(&B::b); - // expected-error@-1 {{cannot cast 'cwg54::B' to its private base class 'cwg54::A'}} + // expected-error@-1 {{cannot cast 'cwg54::B' to its private base class 'A'}} // expected-note@#cwg54-B {{declared private here}} B &sba = static_cast(a); // expected-error@-1 {{cannot cast private base class 'cwg54::A' to 'cwg54::B'}} @@ -867,19 +867,19 @@ namespace cwg54 { // cwg54: 2.8 // expected-error@-1 {{cannot cast private base class 'cwg54::A' to 'cwg54::B'}} // expected-note@#cwg54-B {{declared private here}} int B::*smba = static_cast(&A::a); - // expected-error@-1 {{cannot cast private base class 'cwg54::A' to 'cwg54::B'}} + // expected-error@-1 {{cannot cast private base class 'cwg54::A' to 'B'}} // expected-note@#cwg54-B {{declared private here}} V &svb = static_cast(b); V *spvb = static_cast(&b); int V::*smvb = static_cast(&B::b); - // expected-error@-1 {{conversion from pointer to member of class 'cwg54::B' to pointer to member of class 'cwg54::V' via virtual base 'cwg54::V' is not allowed}} + // expected-error@-1 {{conversion from pointer to member of class 'cwg54::B' to pointer to member of class 'V' via virtual base 'cwg54::V' is not allowed}} B &sbv = static_cast(v); // expected-error@-1 {{cannot cast 'struct V' to 'B &' via virtual base 'cwg54::V'}} B *spbv = static_cast(&v); // expected-error@-1 {{cannot cast 'cwg54::V *' to 'B *' via virtual base 'cwg54::V'}} int B::*smbv = static_cast(&V::v); - // expected-error@-1 {{conversion from pointer to member of class 'cwg54::V' to pointer to member of class 'cwg54::B' via virtual base 'cwg54::V' is not allowed}} + // expected-error@-1 {{conversion from pointer to member of class 'cwg54::V' to pointer to member of class 'B' via virtual base 'cwg54::V' is not allowed}} A &cab = (A&)(b); A *cpab = (A*)(&b); @@ -891,13 +891,13 @@ namespace cwg54 { // cwg54: 2.8 V &cvb = (V&)(b); V *cpvb = (V*)(&b); int V::*cmvb = (int V::*)(&B::b); - // expected-error@-1 {{conversion from pointer to member of class 'cwg54::B' to pointer to member of class 'cwg54::V' via virtual base 'cwg54::V' is not allowed}} + // expected-error@-1 {{conversion from pointer to member of class 'cwg54::B' to pointer to member of class 'V' via virtual base 'cwg54::V' is not allowed}} B &cbv = (B&)(v); // expected-error@-1 {{cannot cast 'struct V' to 'B &' via virtual base 'cwg54::V'}} B *cpbv = (B*)(&v); // expected-error@-1 {{cannot cast 'cwg54::V *' to 'B *' via virtual base 'cwg54::V'}} int B::*cmbv = (int B::*)(&V::v); - // expected-error@-1 {{conversion from pointer to member of class 'cwg54::V' to pointer to member of class 'cwg54::B' via virtual base 'cwg54::V' is not allowed}} + // expected-error@-1 {{conversion from pointer to member of class 'cwg54::V' to pointer to member of class 'B' via virtual base 'cwg54::V' is not allowed}} } namespace cwg55 { // cwg55: yes diff --git a/clang/test/CXX/drs/cwg13xx.cpp b/clang/test/CXX/drs/cwg13xx.cpp index 416de7c536b1a..980fcb4eb18ac 100644 --- a/clang/test/CXX/drs/cwg13xx.cpp +++ b/clang/test/CXX/drs/cwg13xx.cpp @@ -204,7 +204,7 @@ namespace cwg1330 { // cwg1330: 4 c++11 // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} void (A::*af2)() throw() = &A::f; // cxx98-14-error@-1 {{target exception specification is not superset of source}} - // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (cwg1330::A::*)() throw()' with an rvalue of type 'void (cwg1330::A::*)() throw(T)': different exception specifications}} + // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (A::*)() throw()' with an rvalue of type 'void (cwg1330::A::*)() throw(T)': different exception specifications}} #if __cplusplus >= 201103L static_assert(noexcept(A().g()), ""); diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp index 10c8d86ed16a0..26b0f975effa1 100644 --- a/clang/test/CXX/drs/cwg3xx.cpp +++ b/clang/test/CXX/drs/cwg3xx.cpp @@ -537,9 +537,9 @@ namespace cwg330 { // cwg330: 7 void f(A *a) { (void) reinterpret_cast(a); (void) reinterpret_cast(a); - // expected-error@-1 {{ISO C++ does not allow reinterpret_cast from 'A *' (aka 'const volatile int (*)[1][2][3]') to 'B2 *' (aka 'int *const cwg330::swift_17882::X::***') because it casts away qualifiers, even though the source and destination types are unrelated}} + // expected-error@-1 {{ISO C++ does not allow reinterpret_cast from 'A *' (aka 'const volatile int (*)[1][2][3]') to 'B2 *' (aka 'int *const X::***') because it casts away qualifiers, even though the source and destination types are unrelated}} (void) reinterpret_cast(a); - // expected-error@-1 {{ISO C++ does not allow reinterpret_cast from 'A *' (aka 'const volatile int (*)[1][2][3]') to 'B3 *' (aka 'int *cwg330::swift_17882::X::*volatile **') because it casts away qualifiers, even though the source and destination types are unrelated}} + // expected-error@-1 {{ISO C++ does not allow reinterpret_cast from 'A *' (aka 'const volatile int (*)[1][2][3]') to 'B3 *' (aka 'int *X::*volatile **') because it casts away qualifiers, even though the source and destination types are unrelated}} (void) reinterpret_cast(a); } } @@ -971,9 +971,9 @@ namespace cwg354 { // cwg354: yes c++11 ptr<(int S::*)0> p3; // #cwg354-p3 // cxx98-error@#cwg354-p3 {{non-type template argument does not refer to any declaration}} // cxx98-note@#cwg354-ptr {{template parameter is declared here}} - // cxx11-14-error@#cwg354-p3 {{null non-type template argument of type 'int cwg354::S::*' does not match template parameter of type 'int *'}} + // cxx11-14-error@#cwg354-p3 {{null non-type template argument of type 'int S::*' does not match template parameter of type 'int *'}} // cxx11-14-note@#cwg354-ptr {{template parameter is declared here}} - // since-cxx17-error@#cwg354-p3 {{value of type 'int cwg354::S::*' is not implicitly convertible to 'int *'}} + // since-cxx17-error@#cwg354-p3 {{value of type 'int S::*' is not implicitly convertible to 'int *'}} template int both(); // #cwg354-both-int-ptr template int both(); // #cwg354-both-int @@ -985,25 +985,25 @@ namespace cwg354 { // cwg354: yes c++11 template struct ptr_mem {}; // #cwg354-ptr_mem ptr_mem<0> m0; // #cwg354-m0 - // cxx98-error@#cwg354-m0 {{non-type template argument of type 'int' cannot be converted to a value of type 'int cwg354::S::*'}} + // cxx98-error@#cwg354-m0 {{non-type template argument of type 'int' cannot be converted to a value of type 'int S::*'}} // cxx98-note@#cwg354-ptr_mem {{template parameter is declared here}} - // cxx11-14-error@#cwg354-m0 {{null non-type template argument must be cast to template parameter type 'int cwg354::S::*'}} + // cxx11-14-error@#cwg354-m0 {{null non-type template argument must be cast to template parameter type 'int S::*'}} // cxx11-14-note@#cwg354-ptr_mem {{template parameter is declared here}} - // since-cxx17-error@#cwg354-m0 {{conversion from 'int' to 'int cwg354::S::*' is not allowed in a converted constant expression}} + // since-cxx17-error@#cwg354-m0 {{conversion from 'int' to 'int S::*' is not allowed in a converted constant expression}} ptr_mem<(int S::*)0> m1; // cxx98-error@-1 {{non-type template argument is not a pointer to member constant}} ptr_mem<(float S::*)0> m2; // #cwg354-m2 - // cxx98-error@#cwg354-m2 {{non-type template argument of type 'float cwg354::S::*' cannot be converted to a value of type 'int cwg354::S::*'}} + // cxx98-error@#cwg354-m2 {{non-type template argument of type 'float S::*' cannot be converted to a value of type 'int S::*'}} // cxx98-note@#cwg354-ptr_mem {{template parameter is declared here}} - // cxx11-14-error@#cwg354-m2 {{null non-type template argument of type 'float cwg354::S::*' does not match template parameter of type 'int cwg354::S::*'}} + // cxx11-14-error@#cwg354-m2 {{null non-type template argument of type 'float S::*' does not match template parameter of type 'int S::*'}} // cxx11-14-note@#cwg354-ptr_mem {{template parameter is declared here}} - // since-cxx17-error@#cwg354-m2 {{value of type 'float cwg354::S::*' is not implicitly convertible to 'int cwg354::S::*'}} + // since-cxx17-error@#cwg354-m2 {{value of type 'float S::*' is not implicitly convertible to 'int S::*'}} ptr_mem<(int *)0> m3; // #cwg354-m3 - // cxx98-error@#cwg354-m3 {{non-type template argument of type 'int *' cannot be converted to a value of type 'int cwg354::S::*'}} + // cxx98-error@#cwg354-m3 {{non-type template argument of type 'int *' cannot be converted to a value of type 'int S::*'}} // cxx98-note@#cwg354-ptr_mem {{template parameter is declared here}} - // cxx11-14-error@#cwg354-m3 {{null non-type template argument of type 'int *' does not match template parameter of type 'int cwg354::S::*'}} + // cxx11-14-error@#cwg354-m3 {{null non-type template argument of type 'int *' does not match template parameter of type 'int S::*'}} // cxx11-14-note@#cwg354-ptr_mem {{template parameter is declared here}} - // since-cxx17-error@#cwg354-m3 {{value of type 'int *' is not implicitly convertible to 'int cwg354::S::*'}} + // since-cxx17-error@#cwg354-m3 {{value of type 'int *' is not implicitly convertible to 'int S::*'}} } struct cwg355_S; // cwg355: yes @@ -1701,7 +1701,7 @@ namespace cwg395 { // cwg395: 3.0 } } null1; int (S::*p)() = null1; - // expected-error@-1 {{no viable conversion from 'struct null1_t' to 'int (cwg395::S::*)()'}} + // expected-error@-1 {{no viable conversion from 'struct null1_t' to 'int (S::*)()'}} // expected-note@#cwg395-conv-func {{candidate template ignored: couldn't infer template argument 'T'}} template using id = T; diff --git a/clang/test/CXX/drs/cwg4xx.cpp b/clang/test/CXX/drs/cwg4xx.cpp index 98ff7553d989b..825065840f118 100644 --- a/clang/test/CXX/drs/cwg4xx.cpp +++ b/clang/test/CXX/drs/cwg4xx.cpp @@ -1172,11 +1172,11 @@ namespace cwg480 { // cwg480: yes int A::*a = &A::n; int D::*b = a; - // expected-error@-1 {{conversion from pointer to member of class 'cwg480::A' to pointer to member of class 'cwg480::D' via virtual base 'cwg480::B' is not allowed}} + // expected-error@-1 {{conversion from pointer to member of class 'A' to pointer to member of class 'D' via virtual base 'cwg480::B' is not allowed}} extern int D::*c; int A::*d = static_cast(c); - // expected-error@-1 {{conversion from pointer to member of class 'cwg480::D' to pointer to member of class 'cwg480::A' via virtual base 'cwg480::B' is not allowed}} + // expected-error@-1 {{conversion from pointer to member of class 'cwg480::D' to pointer to member of class 'A' via virtual base 'cwg480::B' is not allowed}} D *e; A *f = e; diff --git a/clang/test/CXX/drs/cwg5xx.cpp b/clang/test/CXX/drs/cwg5xx.cpp index 91a76fd2adbb6..9219a4c857b12 100644 --- a/clang/test/CXX/drs/cwg5xx.cpp +++ b/clang/test/CXX/drs/cwg5xx.cpp @@ -184,7 +184,7 @@ namespace cwg522 { // cwg522: yes b2(am); b2a(am); // expected-error@-1 {{no matching function for call to 'b2a'}} - // expected-note@#cwg522-b2a {{candidate template ignored: deduced type 'volatile int *cwg522::S::*const *' of 1st parameter does not match adjusted type 'int *cwg522::S::**' of argument}} + // expected-note@#cwg522-b2a {{candidate template ignored: deduced type 'volatile int *S::*const *' of 1st parameter does not match adjusted type 'int *S::**' of argument}} b3(d); b3(cd); } @@ -1209,6 +1209,11 @@ namespace cwg591 { // cwg591: 20 }; }; + template struct M { + class P; + int M; + }; + template struct A::B::C : A { M m; }; @@ -1224,6 +1229,10 @@ namespace cwg591 { // cwg591: 20 M m; }; + template class M::P : M { + int foo() { (void) M; } + }; + template struct A::B::D : A { M m; // expected-error@-1 {{field has incomplete type 'M' (aka 'void'}} diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp index 170ca0a3f1c6b..e49f396143ad6 100644 --- a/clang/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp +++ b/clang/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp @@ -6,7 +6,7 @@ namespace test0 { template void g(T); void test() { - foo(&g); // expected-error-re {{cannot form member pointer of type 'void (test0::A::*)(int){{( __attribute__\(\(thiscall\)\))?}}' without '&' and class name}} + foo(&g); // expected-error-re {{cannot form member pointer of type 'void (A::*)(int){{( __attribute__\(\(thiscall\)\))?}}' without '&' and class name}} } }; } diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp index 5341290a1446e..034ad49d0715c 100644 --- a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp +++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp @@ -223,7 +223,7 @@ namespace pointer_to_member_function { template struct X0 {}; // expected-note 0-1{{template parameter is declared here}} X0<&Y::f> x0a; X0<&Y::g> x0b; - X0<&Y::h> x0c; // expected-error-re{{type 'float (pointer_to_member_function::Y::*)(float){{( __attribute__\(\(thiscall\)\))?}}' {{.*}} convert{{.*}} 'int (pointer_to_member_function::Y::*)(int){{( __attribute__\(\(thiscall\)\))?}}'}} + X0<&Y::h> x0c; // expected-error-re{{type 'float (pointer_to_member_function::Y::*)(float){{( __attribute__\(\(thiscall\)\))?}}' {{.*}} convert{{.*}} 'int (Y::*)(int){{( __attribute__\(\(thiscall\)\))?}}'}} } // -- For a non-type template-parameter of type pointer to data member, @@ -238,9 +238,9 @@ namespace pointer_to_member_data { X0<&Y::y> x0a; X0<&Y::x> x0b; #if __cplusplus <= 201402L - // expected-error@-2 {{non-type template argument of type 'int pointer_to_member_data::X::*' cannot be converted to a value of type 'int pointer_to_member_data::Y::*'}} + // expected-error@-2 {{non-type template argument of type 'int pointer_to_member_data::X::*' cannot be converted to a value of type 'int Y::*'}} #else - // expected-error@-4 {{conversion from 'int pointer_to_member_data::X::*' to 'int pointer_to_member_data::Y::*' is not allowed in a converted constant expression}} + // expected-error@-4 {{conversion from 'int pointer_to_member_data::X::*' to 'int Y::*' is not allowed in a converted constant expression}} #endif // Test qualification conversions diff --git a/clang/test/CodeGen/AArch64/fixed-register-global.c b/clang/test/CodeGen/AArch64/fixed-register-global.c new file mode 100644 index 0000000000000..a5e634310ec94 --- /dev/null +++ b/clang/test/CodeGen/AArch64/fixed-register-global.c @@ -0,0 +1,23 @@ +/// Check that -ffixed register handled for globals. +/// Regression test for #76426, #109778 +// REQUIRES: aarch64-registered-target + +// RUN: %clang -c --target=aarch64-none-gnu -ffixed-x15 %s 2>&1 | count 0 + +// RUN: not %clang -c --target=aarch64-none-gnu %s 2>&1 | \ +// RUN: FileCheck %s --check-prefix=ERR_INVREG +// ERR_INVREG: error: register 'x15' unsuitable for global register variables on this target + +// RUN: not %clang -c --target=aarch64-none-gnu -ffixed-x15 -DTYPE=short %s 2>&1 | \ +// RUN: FileCheck %s --check-prefix=ERR_SIZE +// ERR_SIZE: error: size of register 'x15' does not match variable size + +#ifndef TYPE +#define TYPE long +#endif + +register TYPE x15 __asm__("x15"); + +TYPE foo() { + return x15; +} diff --git a/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sme2_fp8_cvt.c b/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sme2_fp8_cvt.c index 5ba76671ff5d5..13609f034da33 100644 --- a/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sme2_fp8_cvt.c +++ b/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sme2_fp8_cvt.c @@ -16,6 +16,70 @@ #define SVE_ACLE_FUNC(A1,A2,A3) A1##A2##A3 #endif +// CHECK-LABEL: @test_cvt1_f16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]]) +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.fp8.cvt1.x2.nxv8f16( [[ZN:%.*]]) +// CHECK-NEXT: ret { , } [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z16test_cvt1_f16_x2u13__SVMfloat8_tm( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]]) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.fp8.cvt1.x2.nxv8f16( [[ZN:%.*]]) +// CPP-CHECK-NEXT: ret { , } [[TMP0]] +// +svfloat16x2_t test_cvt1_f16_x2(svmfloat8_t zn, fpm_t fpmr) __arm_streaming { + return SVE_ACLE_FUNC(svcvt1_f16,_mf8,_x2_fpm)(zn, fpmr); +} + +// CHECK-LABEL: @test_cvt2_f16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]]) +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.fp8.cvt2.x2.nxv8f16( [[ZN:%.*]]) +// CHECK-NEXT: ret { , } [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z16test_cvt2_f16_x2u13__SVMfloat8_tm( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]]) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.fp8.cvt2.x2.nxv8f16( [[ZN:%.*]]) +// CPP-CHECK-NEXT: ret { , } [[TMP0]] +// +svfloat16x2_t test_cvt2_f16_x2(svmfloat8_t zn, fpm_t fpmr) __arm_streaming { + return SVE_ACLE_FUNC(svcvt2_f16,_mf8,_x2_fpm)(zn, fpmr); +} + +// CHECK-LABEL: @test_cvt1_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]]) +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.fp8.cvt1.x2.nxv8bf16( [[ZN:%.*]]) +// CHECK-NEXT: ret { , } [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z17test_cvt1_bf16_x2u13__SVMfloat8_tm( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]]) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.fp8.cvt1.x2.nxv8bf16( [[ZN:%.*]]) +// CPP-CHECK-NEXT: ret { , } [[TMP0]] +// +svbfloat16x2_t test_cvt1_bf16_x2(svmfloat8_t zn, fpm_t fpmr) __arm_streaming { + return SVE_ACLE_FUNC(svcvt1_bf16,_mf8,_x2_fpm)(zn, fpmr); +} + +// CHECK-LABEL: @test_cvt2_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]]) +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.fp8.cvt2.x2.nxv8bf16( [[ZN:%.*]]) +// CHECK-NEXT: ret { , } [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z17test_cvt2_bf16_x2u13__SVMfloat8_tm( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]]) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.fp8.cvt2.x2.nxv8bf16( [[ZN:%.*]]) +// CPP-CHECK-NEXT: ret { , } [[TMP0]] +// +svbfloat16x2_t test_cvt2_bf16_x2(svmfloat8_t zn, fpm_t fpmr) __arm_streaming { + return SVE_ACLE_FUNC(svcvt2_bf16,_mf8,_x2_fpm)(zn, fpmr); +} + // CHECK-LABEL: @test_cvtl1_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]]) diff --git a/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sme2_fp8_fmopa.c b/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sme2_fp8_fmopa.c new file mode 100644 index 0000000000000..95d6383ab30ef --- /dev/null +++ b/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sme2_fp8_fmopa.c @@ -0,0 +1,55 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sme-f8f16 -target-feature +sme-f8f32 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s + +#include + +#ifdef SVE_OVERLOADED_FORMS +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3) A1##A2##A3 +#endif + + +// CHECK-LABEL: define dso_local void @test_svmopa_za16_mf8_m( +// CHECK-SAME: [[PN:%.*]], [[PM:%.*]], [[ZN:%.*]], [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmopa.za16(i32 1, [[PN]], [[PM]], [[ZN]], [[ZM]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: define dso_local void @_Z22test_svmopa_za16_mf8_mu10__SVBool_tS_u13__SVMfloat8_tS0_m( +// CPP-CHECK-SAME: [[PN:%.*]], [[PM:%.*]], [[ZN:%.*]], [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0:[0-9]+]] { +// CPP-CHECK-NEXT: [[ENTRY:.*:]] +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmopa.za16(i32 1, [[PN]], [[PM]], [[ZN]], [[ZM]]) +// CPP-CHECK-NEXT: ret void +// +void test_svmopa_za16_mf8_m(svbool_t pn, svbool_t pm, svmfloat8_t zn, + svmfloat8_t zm, fpm_t fpmr) __arm_streaming __arm_inout("za") { + SVE_ACLE_FUNC(svmopa_za16,_mf8,_m_fpm)(1, pn, pm, zn, zm, fpmr); +} + +// CHECK-LABEL: define dso_local void @test_svmopa_za32_mf8_m( +// CHECK-SAME: [[PN:%.*]], [[PM:%.*]], [[ZN:%.*]], [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmopa.za32(i32 3, [[PN]], [[PM]], [[ZN]], [[ZM]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: define dso_local void @_Z22test_svmopa_za32_mf8_mu10__SVBool_tS_u13__SVMfloat8_tS0_m( +// CPP-CHECK-SAME: [[PN:%.*]], [[PM:%.*]], [[ZN:%.*]], [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] { +// CPP-CHECK-NEXT: [[ENTRY:.*:]] +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmopa.za32(i32 3, [[PN]], [[PM]], [[ZN]], [[ZM]]) +// CPP-CHECK-NEXT: ret void +// +void test_svmopa_za32_mf8_m(svbool_t pn, svbool_t pm, svmfloat8_t zn, + svmfloat8_t zm, fpm_t fpmr) __arm_streaming __arm_inout("za") { + SVE_ACLE_FUNC(svmopa_za32,_mf8,_m_fpm)(3, pn, pm, zn, zm, fpmr); +} diff --git a/clang/test/CodeGen/AArch64/ls64-inline-asm.c b/clang/test/CodeGen/AArch64/ls64-inline-asm.c index a01393525bcd4..8aa0684dba14d 100644 --- a/clang/test/CodeGen/AArch64/ls64-inline-asm.c +++ b/clang/test/CodeGen/AArch64/ls64-inline-asm.c @@ -5,7 +5,7 @@ struct foo { unsigned long long x[8]; }; // CHECK-LABEL: @load( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call i512 asm sideeffect "ld64b $0,[$1]", "=r,r,~{memory}"(ptr [[ADDR:%.*]]) #[[ATTR1:[0-9]+]], !srcloc !2 +// CHECK-NEXT: [[TMP0:%.*]] = tail call i512 asm sideeffect "ld64b $0,[$1]", "=r,r,~{memory}"(ptr [[ADDR:%.*]]) #[[ATTR1:[0-9]+]], !srcloc [[META2:![0-9]+]] // CHECK-NEXT: store i512 [[TMP0]], ptr [[OUTPUT:%.*]], align 8 // CHECK-NEXT: ret void // @@ -17,7 +17,7 @@ void load(struct foo *output, void *addr) // CHECK-LABEL: @store( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load i512, ptr [[INPUT:%.*]], align 8 -// CHECK-NEXT: tail call void asm sideeffect "st64b $0,[$1]", "r,r,~{memory}"(i512 [[TMP0]], ptr [[ADDR:%.*]]) #[[ATTR1]], !srcloc !3 +// CHECK-NEXT: tail call void asm sideeffect "st64b $0,[$1]", "r,r,~{memory}"(i512 [[TMP0]], ptr [[ADDR:%.*]]) #[[ATTR1]], !srcloc [[META3:![0-9]+]] // CHECK-NEXT: ret void // void store(const struct foo *input, void *addr) @@ -29,25 +29,25 @@ void store(const struct foo *input, void *addr) // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[IN:%.*]], align 4, !tbaa [[TBAA4:![0-9]+]] // CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64 -// CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[IN]], i64 4 +// CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i8, ptr [[IN]], i64 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX1]], align 4, !tbaa [[TBAA4]] // CHECK-NEXT: [[CONV2:%.*]] = sext i32 [[TMP1]] to i64 -// CHECK-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds i8, ptr [[IN]], i64 16 +// CHECK-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds nuw i8, ptr [[IN]], i64 16 // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX4]], align 4, !tbaa [[TBAA4]] // CHECK-NEXT: [[CONV5:%.*]] = sext i32 [[TMP2]] to i64 -// CHECK-NEXT: [[ARRAYIDX7:%.*]] = getelementptr inbounds i8, ptr [[IN]], i64 64 +// CHECK-NEXT: [[ARRAYIDX7:%.*]] = getelementptr inbounds nuw i8, ptr [[IN]], i64 64 // CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX7]], align 4, !tbaa [[TBAA4]] // CHECK-NEXT: [[CONV8:%.*]] = sext i32 [[TMP3]] to i64 -// CHECK-NEXT: [[ARRAYIDX10:%.*]] = getelementptr inbounds i8, ptr [[IN]], i64 100 +// CHECK-NEXT: [[ARRAYIDX10:%.*]] = getelementptr inbounds nuw i8, ptr [[IN]], i64 100 // CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[ARRAYIDX10]], align 4, !tbaa [[TBAA4]] // CHECK-NEXT: [[CONV11:%.*]] = sext i32 [[TMP4]] to i64 -// CHECK-NEXT: [[ARRAYIDX13:%.*]] = getelementptr inbounds i8, ptr [[IN]], i64 144 +// CHECK-NEXT: [[ARRAYIDX13:%.*]] = getelementptr inbounds nuw i8, ptr [[IN]], i64 144 // CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[ARRAYIDX13]], align 4, !tbaa [[TBAA4]] // CHECK-NEXT: [[CONV14:%.*]] = sext i32 [[TMP5]] to i64 -// CHECK-NEXT: [[ARRAYIDX16:%.*]] = getelementptr inbounds i8, ptr [[IN]], i64 196 +// CHECK-NEXT: [[ARRAYIDX16:%.*]] = getelementptr inbounds nuw i8, ptr [[IN]], i64 196 // CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[ARRAYIDX16]], align 4, !tbaa [[TBAA4]] // CHECK-NEXT: [[CONV17:%.*]] = sext i32 [[TMP6]] to i64 -// CHECK-NEXT: [[ARRAYIDX19:%.*]] = getelementptr inbounds i8, ptr [[IN]], i64 256 +// CHECK-NEXT: [[ARRAYIDX19:%.*]] = getelementptr inbounds nuw i8, ptr [[IN]], i64 256 // CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[ARRAYIDX19]], align 4, !tbaa [[TBAA4]] // CHECK-NEXT: [[CONV20:%.*]] = sext i32 [[TMP7]] to i64 // CHECK-NEXT: [[S_SROA_10_0_INSERT_EXT:%.*]] = zext i64 [[CONV20]] to i512 @@ -72,7 +72,7 @@ void store(const struct foo *input, void *addr) // CHECK-NEXT: [[S_SROA_0_0_INSERT_EXT:%.*]] = zext i64 [[CONV]] to i512 // CHECK-NEXT: [[S_SROA_0_0_INSERT_MASK:%.*]] = or disjoint i512 [[S_SROA_4_0_INSERT_MASK]], [[S_SROA_4_0_INSERT_SHIFT]] // CHECK-NEXT: [[S_SROA_0_0_INSERT_INSERT:%.*]] = or i512 [[S_SROA_0_0_INSERT_MASK]], [[S_SROA_0_0_INSERT_EXT]] -// CHECK-NEXT: tail call void asm sideeffect "st64b $0,[$1]", "r,r,~{memory}"(i512 [[S_SROA_0_0_INSERT_INSERT]], ptr [[ADDR:%.*]]) #[[ATTR1]], !srcloc !8 +// CHECK-NEXT: tail call void asm sideeffect "st64b $0,[$1]", "r,r,~{memory}"(i512 [[S_SROA_0_0_INSERT_INSERT]], ptr [[ADDR:%.*]]) #[[ATTR1]], !srcloc [[META8:![0-9]+]] // CHECK-NEXT: ret void // void store2(int *in, void *addr) diff --git a/clang/test/CodeGen/AArch64/pure-scalable-args.c b/clang/test/CodeGen/AArch64/pure-scalable-args.c index f40c944335e4a..a8c3dd9288a5b 100644 --- a/clang/test/CodeGen/AArch64/pure-scalable-args.c +++ b/clang/test/CodeGen/AArch64/pure-scalable-args.c @@ -417,7 +417,7 @@ void test_va_arg(int n, ...) { // CHECK-AAPCS-EMPTY: // CHECK-AAPCS-NEXT: vaarg.on_stack: ; preds = %vaarg.maybe_reg, %entry // CHECK-AAPCS-NEXT: %stack = load ptr, ptr %ap, align 8 -// CHECK-AAPCS-NEXT: %new_stack = getelementptr inbounds i8, ptr %stack, i64 8 +// CHECK-AAPCS-NEXT: %new_stack = getelementptr inbounds nuw i8, ptr %stack, i64 8 // CHECK-AAPCS-NEXT: store ptr %new_stack, ptr %ap, align 8 // CHECK-AAPCS-NEXT: br label %vaarg.end // CHECK-AAPCS-EMPTY: @@ -428,7 +428,7 @@ void test_va_arg(int n, ...) { // CHECK-AAPCS-NEXT: %vaarg.addr = load ptr, ptr %vaargs.addr, align 8 // CHECK-AAPCS-NEXT: %v.sroa.0.0.copyload = load <2 x i8>, ptr %vaarg.addr, align 16 -// CHECK-AAPCS-NEXT: %v.sroa.43.0.vaarg.addr.sroa_idx = getelementptr inbounds i8, ptr %vaarg.addr, i64 48 +// CHECK-AAPCS-NEXT: %v.sroa.43.0.vaarg.addr.sroa_idx = getelementptr inbounds nuw i8, ptr %vaarg.addr, i64 48 // CHECK-AAPCS-NEXT: %v.sroa.43.0.copyload = load <4 x float>, ptr %v.sroa.43.0.vaarg.addr.sroa_idx, align 16 // CHECK-AAPCS-NEXT: call void @llvm.va_end.p0(ptr nonnull %ap) // CHECK-AAPCS-NEXT: %cast.scalable = call @llvm.vector.insert.nxv2i8.v2i8( poison, <2 x i8> %v.sroa.0.0.copyload, i64 0) @@ -445,11 +445,11 @@ void test_va_arg(int n, ...) { // CHECK-DARWIN-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr nonnull %ap) // CHECK-DARWIN-NEXT: call void @llvm.va_start.p0(ptr nonnull %ap) // CHECK-DARWIN-NEXT: %argp.cur = load ptr, ptr %ap, align 8 -// CHECK-DARWIN-NEXT: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i64 8 +// CHECK-DARWIN-NEXT: %argp.next = getelementptr inbounds nuw i8, ptr %argp.cur, i64 8 // CHECK-DARWIN-NEXT: store ptr %argp.next, ptr %ap, align 8 // CHECK-DARWIN-NEXT: %0 = load ptr, ptr %argp.cur, align 8 // CHECK-DARWIN-NEXT: %v.sroa.0.0.copyload = load <2 x i8>, ptr %0, align 16 -// CHECK-DARWIN-NEXT: %v.sroa.43.0..sroa_idx = getelementptr inbounds i8, ptr %0, i64 48 +// CHECK-DARWIN-NEXT: %v.sroa.43.0..sroa_idx = getelementptr inbounds nuw i8, ptr %0, i64 48 // CHECK-DARWIN-NEXT: %v.sroa.43.0.copyload = load <4 x float>, ptr %v.sroa.43.0..sroa_idx, align 16 // CHECK-DARWIN-NEXT: call void @llvm.va_end.p0(ptr nonnull %ap) // CHECK-DARWIN-NEXT: %cast.scalable = call @llvm.vector.insert.nxv2i8.v2i8( poison, <2 x i8> %v.sroa.0.0.copyload, i64 0) diff --git a/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_ld1_vnum.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_ld1_vnum.c index fcbd17559dc70..fb86690f07f1d 100644 --- a/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_ld1_vnum.c +++ b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_ld1_vnum.c @@ -12,9 +12,12 @@ // CHECK-C-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP0]], [[VNUM]] // CHECK-C-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 15 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP2:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP3:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP3]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[ADD]], 15 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP4]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z23test_svld1_hor_vnum_za8ju10__SVBool_tPKvl( @@ -23,9 +26,12 @@ // CHECK-CXX-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP0]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 15 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP2:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP3:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP3]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[ADD]], 15 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP4]]) // CHECK-CXX-NEXT: ret void // void test_svld1_hor_vnum_za8(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming __arm_out("za") { @@ -40,9 +46,12 @@ void test_svld1_hor_vnum_za8(uint32_t slice_base, svbool_t pg, const void *ptr, // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1h.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 7 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1h.horiz( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1h.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 7 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1h.horiz( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[TMP5]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z24test_svld1_hor_vnum_za16ju10__SVBool_tPKvl( @@ -52,9 +61,12 @@ void test_svld1_hor_vnum_za8(uint32_t slice_base, svbool_t pg, const void *ptr, // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1h.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 7 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1h.horiz( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1h.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 7 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1h.horiz( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[TMP5]]) // CHECK-CXX-NEXT: ret void // void test_svld1_hor_vnum_za16(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming __arm_out("za") { @@ -69,9 +81,12 @@ void test_svld1_hor_vnum_za16(uint32_t slice_base, svbool_t pg, const void *ptr, // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1w.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 3 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1w.horiz( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1w.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 3 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1w.horiz( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[TMP5]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z24test_svld1_hor_vnum_za32ju10__SVBool_tPKvl( @@ -81,9 +96,12 @@ void test_svld1_hor_vnum_za16(uint32_t slice_base, svbool_t pg, const void *ptr, // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1w.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 3 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1w.horiz( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1w.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 3 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1w.horiz( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[TMP5]]) // CHECK-CXX-NEXT: ret void // void test_svld1_hor_vnum_za32(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming __arm_out("za") { @@ -98,9 +116,12 @@ void test_svld1_hor_vnum_za32(uint32_t slice_base, svbool_t pg, const void *ptr, // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1d.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 1 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1d.horiz( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1d.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 1 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1d.horiz( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[TMP5]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z24test_svld1_hor_vnum_za64ju10__SVBool_tPKvl( @@ -110,9 +131,12 @@ void test_svld1_hor_vnum_za32(uint32_t slice_base, svbool_t pg, const void *ptr, // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1d.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 1 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1d.horiz( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1d.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 1 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1d.horiz( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[TMP5]]) // CHECK-CXX-NEXT: ret void // void test_svld1_hor_vnum_za64(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming __arm_out("za") { @@ -127,8 +151,10 @@ void test_svld1_hor_vnum_za64(uint32_t slice_base, svbool_t pg, const void *ptr, // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1q.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1q.horiz( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1q.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1q.horiz( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[TMP4]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z25test_svld1_hor_vnum_za128ju10__SVBool_tPKvl( @@ -138,8 +164,10 @@ void test_svld1_hor_vnum_za64(uint32_t slice_base, svbool_t pg, const void *ptr, // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1q.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1q.horiz( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1q.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1q.horiz( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[TMP4]]) // CHECK-CXX-NEXT: ret void // void test_svld1_hor_vnum_za128(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming __arm_out("za") { @@ -153,9 +181,12 @@ void test_svld1_hor_vnum_za128(uint32_t slice_base, svbool_t pg, const void *ptr // CHECK-C-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP0]], [[VNUM]] // CHECK-C-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 15 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP2:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP3:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP3]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[ADD]], 15 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP4]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z22test_svld1_ver_hor_za8ju10__SVBool_tPKvl( @@ -164,9 +195,12 @@ void test_svld1_hor_vnum_za128(uint32_t slice_base, svbool_t pg, const void *ptr // CHECK-CXX-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP0]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 15 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP2:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP3:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP3]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[ADD]], 15 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP4]]) // CHECK-CXX-NEXT: ret void // void test_svld1_ver_hor_za8(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming __arm_out("za") { @@ -181,9 +215,12 @@ void test_svld1_ver_hor_za8(uint32_t slice_base, svbool_t pg, const void *ptr, i // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1h.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 7 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1h.vert( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1h.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 7 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1h.vert( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[TMP5]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z24test_svld1_ver_vnum_za16ju10__SVBool_tPKvl( @@ -193,9 +230,12 @@ void test_svld1_ver_hor_za8(uint32_t slice_base, svbool_t pg, const void *ptr, i // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1h.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 7 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1h.vert( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1h.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 7 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1h.vert( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[TMP5]]) // CHECK-CXX-NEXT: ret void // void test_svld1_ver_vnum_za16(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming __arm_out("za") { @@ -210,9 +250,12 @@ void test_svld1_ver_vnum_za16(uint32_t slice_base, svbool_t pg, const void *ptr, // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1w.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 3 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1w.vert( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1w.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 3 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1w.vert( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[TMP5]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z24test_svld1_ver_vnum_za32ju10__SVBool_tPKvl( @@ -222,9 +265,12 @@ void test_svld1_ver_vnum_za16(uint32_t slice_base, svbool_t pg, const void *ptr, // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1w.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 3 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1w.vert( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1w.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 3 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1w.vert( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[TMP5]]) // CHECK-CXX-NEXT: ret void // void test_svld1_ver_vnum_za32(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming __arm_out("za") { @@ -239,9 +285,12 @@ void test_svld1_ver_vnum_za32(uint32_t slice_base, svbool_t pg, const void *ptr, // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1d.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 1 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1d.vert( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1d.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 1 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1d.vert( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[TMP5]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z24test_svld1_ver_vnum_za64ju10__SVBool_tPKvl( @@ -251,9 +300,12 @@ void test_svld1_ver_vnum_za32(uint32_t slice_base, svbool_t pg, const void *ptr, // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1d.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 1 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1d.vert( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1d.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 1 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1d.vert( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[TMP5]]) // CHECK-CXX-NEXT: ret void // void test_svld1_ver_vnum_za64(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming __arm_out("za") { @@ -268,8 +320,10 @@ void test_svld1_ver_vnum_za64(uint32_t slice_base, svbool_t pg, const void *ptr, // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1q.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1q.vert( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1q.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.ld1q.vert( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[TMP4]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z25test_svld1_ver_vnum_za128ju10__SVBool_tPKvl( @@ -279,8 +333,10 @@ void test_svld1_ver_vnum_za64(uint32_t slice_base, svbool_t pg, const void *ptr, // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1q.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1q.vert( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1q.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1q.vert( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[TMP4]]) // CHECK-CXX-NEXT: ret void // void test_svld1_ver_vnum_za128(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming __arm_out("za") { diff --git a/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_st1_vnum.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_st1_vnum.c index b2c609b7c2242..dafc3d61a05f1 100644 --- a/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_st1_vnum.c +++ b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_st1_vnum.c @@ -12,9 +12,12 @@ // CHECK-C-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP0]], [[VNUM]] // CHECK-C-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 15 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP2:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP3:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP3]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[ADD]], 15 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP4]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z23test_svst1_hor_vnum_za8ju10__SVBool_tPvl( @@ -23,9 +26,12 @@ // CHECK-CXX-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP0]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 15 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP2:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP3:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP3]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[ADD]], 15 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP4]]) // CHECK-CXX-NEXT: ret void // void test_svst1_hor_vnum_za8(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming __arm_in("za") { @@ -40,9 +46,12 @@ void test_svst1_hor_vnum_za8(uint32_t slice_base, svbool_t pg, void *ptr, int64_ // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1h.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 7 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1h.horiz( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1h.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 7 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1h.horiz( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[TMP5]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z24test_svst1_hor_vnum_za16ju10__SVBool_tPvl( @@ -52,9 +61,12 @@ void test_svst1_hor_vnum_za8(uint32_t slice_base, svbool_t pg, void *ptr, int64_ // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1h.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 7 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1h.horiz( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1h.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 7 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1h.horiz( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[TMP5]]) // CHECK-CXX-NEXT: ret void // void test_svst1_hor_vnum_za16(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming __arm_in("za") { @@ -69,9 +81,12 @@ void test_svst1_hor_vnum_za16(uint32_t slice_base, svbool_t pg, void *ptr, int64 // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1w.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 3 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1w.horiz( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1w.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 3 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1w.horiz( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[TMP5]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z24test_svst1_hor_vnum_za32ju10__SVBool_tPvl( @@ -81,9 +96,12 @@ void test_svst1_hor_vnum_za16(uint32_t slice_base, svbool_t pg, void *ptr, int64 // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1w.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 3 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1w.horiz( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1w.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 3 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1w.horiz( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[TMP5]]) // CHECK-CXX-NEXT: ret void // void test_svst1_hor_vnum_za32(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming __arm_in("za") { @@ -98,9 +116,12 @@ void test_svst1_hor_vnum_za32(uint32_t slice_base, svbool_t pg, void *ptr, int64 // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1d.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 1 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1d.horiz( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1d.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 1 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1d.horiz( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[TMP5]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z24test_svst1_hor_vnum_za64ju10__SVBool_tPvl( @@ -110,9 +131,12 @@ void test_svst1_hor_vnum_za32(uint32_t slice_base, svbool_t pg, void *ptr, int64 // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1d.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 1 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1d.horiz( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1d.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 1 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1d.horiz( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[TMP5]]) // CHECK-CXX-NEXT: ret void // void test_svst1_hor_vnum_za64(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming __arm_in("za") { @@ -127,8 +151,10 @@ void test_svst1_hor_vnum_za64(uint32_t slice_base, svbool_t pg, void *ptr, int64 // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1q.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1q.horiz( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1q.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1q.horiz( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[TMP4]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z25test_svst1_hor_vnum_za128ju10__SVBool_tPvl( @@ -138,8 +164,10 @@ void test_svst1_hor_vnum_za64(uint32_t slice_base, svbool_t pg, void *ptr, int64 // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1q.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1q.horiz( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1q.horiz( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1q.horiz( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[TMP4]]) // CHECK-CXX-NEXT: ret void // void test_svst1_hor_vnum_za128(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming __arm_in("za") { @@ -153,9 +181,12 @@ void test_svst1_hor_vnum_za128(uint32_t slice_base, svbool_t pg, void *ptr, int6 // CHECK-C-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP0]], [[VNUM]] // CHECK-C-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 15 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP2:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP3:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP3]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[ADD]], 15 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP4]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z23test_svst1_ver_vnum_za8ju10__SVBool_tPvl( @@ -164,9 +195,12 @@ void test_svst1_hor_vnum_za128(uint32_t slice_base, svbool_t pg, void *ptr, int6 // CHECK-CXX-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP0]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 15 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP2:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP3:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP3]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP2]] +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[ADD]], 15 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[TMP4]]) // CHECK-CXX-NEXT: ret void // void test_svst1_ver_vnum_za8(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming __arm_in("za") { @@ -181,9 +215,12 @@ void test_svst1_ver_vnum_za8(uint32_t slice_base, svbool_t pg, void *ptr, int64_ // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1h.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 7 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1h.vert( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1h.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 7 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1h.vert( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[TMP5]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z24test_svst1_ver_vnum_za16ju10__SVBool_tPvl( @@ -193,9 +230,12 @@ void test_svst1_ver_vnum_za8(uint32_t slice_base, svbool_t pg, void *ptr, int64_ // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1h.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 7 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1h.vert( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1h.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 7 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1h.vert( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[TMP5]]) // CHECK-CXX-NEXT: ret void // void test_svst1_ver_vnum_za16(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming __arm_in("za") { @@ -210,9 +250,12 @@ void test_svst1_ver_vnum_za16(uint32_t slice_base, svbool_t pg, void *ptr, int64 // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1w.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 3 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1w.vert( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1w.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 3 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1w.vert( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[TMP5]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z24test_svst1_ver_vnum_za32ju10__SVBool_tPvl( @@ -222,9 +265,12 @@ void test_svst1_ver_vnum_za16(uint32_t slice_base, svbool_t pg, void *ptr, int64 // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1w.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 3 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1w.vert( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1w.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 3 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1w.vert( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[TMP5]]) // CHECK-CXX-NEXT: ret void // void test_svst1_ver_vnum_za32(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming __arm_in("za") { @@ -239,9 +285,12 @@ void test_svst1_ver_vnum_za32(uint32_t slice_base, svbool_t pg, void *ptr, int64 // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1d.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 1 -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1d.vert( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[ADD]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1d.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 1 +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1d.vert( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[TMP5]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z24test_svst1_ver_vnum_za64ju10__SVBool_tPvl( @@ -251,9 +300,12 @@ void test_svst1_ver_vnum_za32(uint32_t slice_base, svbool_t pg, void *ptr, int64 // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1d.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], 1 -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1d.vert( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[ADD]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1d.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: [[ADD:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: [[TMP5:%.*]] = add i32 [[ADD]], 1 +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1d.vert( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[TMP5]]) // CHECK-CXX-NEXT: ret void // void test_svst1_ver_vnum_za64(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming __arm_in("za") { @@ -268,8 +320,10 @@ void test_svst1_ver_vnum_za64(uint32_t slice_base, svbool_t pg, void *ptr, int64 // CHECK-C-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-C-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-C-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1q.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1q.vert( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) +// CHECK-C-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-C-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1q.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.st1q.vert( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[TMP4]]) // CHECK-C-NEXT: ret void // // CHECK-CXX-LABEL: define dso_local void @_Z25test_svst1_ver_vnum_za128ju10__SVBool_tPvl( @@ -279,8 +333,10 @@ void test_svst1_ver_vnum_za64(uint32_t slice_base, svbool_t pg, void *ptr, int64 // CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.aarch64.sme.cntsb() // CHECK-CXX-NEXT: [[MULVL:%.*]] = mul i64 [[TMP1]], [[VNUM]] // CHECK-CXX-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[MULVL]] -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1q.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[SLICE_BASE]]) -// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1q.vert( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = trunc i64 [[VNUM]] to i32 +// CHECK-CXX-NEXT: [[TMP4:%.*]] = add i32 [[SLICE_BASE]], [[TMP3]] +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1q.vert( [[TMP0]], ptr [[TMP2]], i32 0, i32 [[TMP4]]) +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1q.vert( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[TMP4]]) // CHECK-CXX-NEXT: ret void // void test_svst1_ver_vnum_za128(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming __arm_in("za") { diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-pair-mma.c b/clang/test/CodeGen/PowerPC/builtins-ppc-pair-mma.c index 5422d993ff157..08ff936a0a797 100644 --- a/clang/test/CodeGen/PowerPC/builtins-ppc-pair-mma.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-pair-mma.c @@ -25,13 +25,13 @@ void test1(unsigned char *vqp, unsigned char *vpp, vector unsigned char vc, unsi // CHECK-NEXT: [[TMP2:%.*]] = extractvalue { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[TMP1]], 0 // CHECK-NEXT: store <16 x i8> [[TMP2]], ptr [[RESP:%.*]], align 16 // CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[TMP1]], 1 -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[RESP]], i64 16 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw i8, ptr [[RESP]], i64 16 // CHECK-NEXT: store <16 x i8> [[TMP3]], ptr [[TMP4]], align 16 // CHECK-NEXT: [[TMP5:%.*]] = extractvalue { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[TMP1]], 2 -// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, ptr [[RESP]], i64 32 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw i8, ptr [[RESP]], i64 32 // CHECK-NEXT: store <16 x i8> [[TMP5]], ptr [[TMP6]], align 16 // CHECK-NEXT: [[TMP7:%.*]] = extractvalue { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[TMP1]], 3 -// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i8, ptr [[RESP]], i64 48 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw i8, ptr [[RESP]], i64 48 // CHECK-NEXT: store <16 x i8> [[TMP7]], ptr [[TMP8]], align 16 // CHECK-NEXT: ret void // @@ -60,7 +60,7 @@ void test3(unsigned char *vqp, unsigned char *vpp, vector unsigned char vc, unsi // CHECK-NEXT: [[TMP2:%.*]] = extractvalue { <16 x i8>, <16 x i8> } [[TMP1]], 0 // CHECK-NEXT: store <16 x i8> [[TMP2]], ptr [[RESP:%.*]], align 16 // CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <16 x i8>, <16 x i8> } [[TMP1]], 1 -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[RESP]], i64 16 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw i8, ptr [[RESP]], i64 16 // CHECK-NEXT: store <16 x i8> [[TMP3]], ptr [[TMP4]], align 16 // CHECK-NEXT: ret void // @@ -1072,7 +1072,7 @@ void test76(unsigned char *vqp, unsigned char *vpp, vector unsigned char vc, uns // CHECK-NEXT: [[TMP2:%.*]] = extractvalue { <16 x i8>, <16 x i8> } [[TMP1]], 0 // CHECK-NEXT: store <16 x i8> [[TMP2]], ptr [[RESP:%.*]], align 16 // CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <16 x i8>, <16 x i8> } [[TMP1]], 1 -// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[RESP]], i64 16 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw i8, ptr [[RESP]], i64 16 // CHECK-NEXT: store <16 x i8> [[TMP3]], ptr [[TMP4]], align 16 // CHECK-NEXT: ret void // diff --git a/clang/test/CodeGen/RISCV/riscv-inline-asm.c b/clang/test/CodeGen/RISCV/riscv-inline-asm.c index de90e513ea1ff..9da306807ed0d 100644 --- a/clang/test/CodeGen/RISCV/riscv-inline-asm.c +++ b/clang/test/CodeGen/RISCV/riscv-inline-asm.c @@ -90,9 +90,9 @@ extern int var, arr[2][2]; struct Pair { int a, b; } pair; // CHECK-LABEL: test_s( -// CHECK: call void asm sideeffect "// $0 $1 $2", "s,s,s"(ptr nonnull @var, ptr nonnull getelementptr inbounds (i8, ptr @arr, {{.*}}), ptr nonnull @test_s) +// CHECK: call void asm sideeffect "// $0 $1 $2", "s,s,s"(ptr nonnull @var, ptr nonnull getelementptr inbounds nuw (i8, ptr @arr, {{.*}}), ptr nonnull @test_s) // CHECK: call void asm sideeffect "// $0", "s"(ptr nonnull getelementptr inbounds nuw (i8, ptr @pair, {{.*}})) -// CHECK: call void asm sideeffect "// $0 $1 $2", "S,S,S"(ptr nonnull @var, ptr nonnull getelementptr inbounds (i8, ptr @arr, {{.*}}), ptr nonnull @test_s) +// CHECK: call void asm sideeffect "// $0 $1 $2", "S,S,S"(ptr nonnull @var, ptr nonnull getelementptr inbounds nuw (i8, ptr @arr, {{.*}}), ptr nonnull @test_s) void test_s(void) { asm("// %0 %1 %2" :: "s"(&var), "s"(&arr[1][1]), "s"(test_s)); asm("// %0" :: "s"(&pair.b)); diff --git a/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes.c b/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes.c index 82bb7a52d05d1..33cf0ddb47236 100644 --- a/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes.c +++ b/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes.c @@ -48,21 +48,21 @@ void test_indexing(struct Foo *f) { void test_indexing_2(struct Foo *f) { // X64-LABEL: define void @test_indexing_2(ptr noundef initializes((16, 24)) %f) - // X64: getelementptr inbounds i8, ptr addrspace(1) {{%[0-9]}}, i32 16 - // X64: getelementptr inbounds i8, ptr {{%[0-9]}}, i64 24 + // X64: getelementptr inbounds nuw i8, ptr addrspace(1) {{%[0-9]}}, i32 16 + // X64: getelementptr inbounds nuw i8, ptr {{%[0-9]}}, i64 24 f->cp64 = ((char *** __ptr32 *)1028)[1][2][3]; use_foo(f); } unsigned long* test_misc() { // X64-LABEL: define ptr @test_misc() - // X64: %arrayidx = getelementptr inbounds i8, ptr addrspace(1) %0, i32 88 + // X64: %arrayidx = getelementptr inbounds nuw i8, ptr addrspace(1) %0, i32 88 // X64-NEXT: %1 = load ptr, ptr addrspace(1) %arrayidx - // X64-NEXT: %arrayidx1 = getelementptr inbounds i8, ptr %1, i64 8 + // X64-NEXT: %arrayidx1 = getelementptr inbounds nuw i8, ptr %1, i64 8 // X64-NEXT: %2 = load ptr, ptr %arrayidx1 - // X64-NEXT: %arrayidx2 = getelementptr inbounds i8, ptr %2, i64 904 + // X64-NEXT: %arrayidx2 = getelementptr inbounds nuw i8, ptr %2, i64 904 // X64-NEXT: %3 = load ptr, ptr %arrayidx2 - // X64-NEXT: %arrayidx3 = getelementptr inbounds i8, ptr %3, i64 1192 + // X64-NEXT: %arrayidx3 = getelementptr inbounds nuw i8, ptr %3, i64 1192 unsigned long* x = (unsigned long*)((char***** __ptr32*)1208)[0][11][1][113][149]; return x; } @@ -71,9 +71,9 @@ char* __ptr32* __ptr32 test_misc_2() { // X64-LABEL: define ptr addrspace(1) @test_misc_2() // X64: br i1 %cmp, label %if.then, label %if.end // X64: %1 = load ptr addrspace(1), ptr inttoptr (i64 16 to ptr) - // X64-NEXT: %arrayidx = getelementptr inbounds i8, ptr addrspace(1) %1, i32 544 + // X64-NEXT: %arrayidx = getelementptr inbounds nuw i8, ptr addrspace(1) %1, i32 544 // X64-NEXT: %2 = load ptr addrspace(1), ptr addrspace(1) %arrayidx - // X64-NEXT: %arrayidx1 = getelementptr inbounds i8, ptr addrspace(1) %2, i32 24 + // X64-NEXT: %arrayidx1 = getelementptr inbounds nuw i8, ptr addrspace(1) %2, i32 24 // X64-NEXT: %3 = load ptr addrspace(1), ptr addrspace(1) %arrayidx1 // X64-NEXT: store ptr addrspace(1) %3, ptr @test_misc_2.res // X64: ret ptr addrspace(1) @@ -88,7 +88,7 @@ unsigned short test_misc_3() { // X64-LABEL: define zeroext i16 @test_misc_3() // X64: %0 = load ptr addrspace(1), ptr inttoptr (i64 548 to ptr) // X64-NEXT: %1 = addrspacecast ptr addrspace(1) %0 to ptr - // X64-NEXT: %arrayidx = getelementptr inbounds i8, ptr %1, i64 36 + // X64-NEXT: %arrayidx = getelementptr inbounds nuw i8, ptr %1, i64 36 // X64-NEXT: %2 = load i16, ptr %arrayidx, align 2 // X64-NEXT: ret i16 %2 unsigned short this_asid = ((unsigned short*)(*(char* __ptr32*)(0x224)))[18]; @@ -97,10 +97,10 @@ unsigned short test_misc_3() { int test_misc_4() { // X64-LABEL: define signext range(i32 0, 2) i32 @test_misc_4() - // X64: getelementptr inbounds i8, ptr addrspace(1) {{%[0-9]}}, i32 88 - // X64: getelementptr inbounds i8, ptr {{%[0-9]}}, i64 8 - // X64: getelementptr inbounds i8, ptr {{%[0-9]}}, i64 984 - // X64: getelementptr inbounds i8, ptr %3, i64 80 + // X64: getelementptr inbounds nuw i8, ptr addrspace(1) {{%[0-9]}}, i32 88 + // X64: getelementptr inbounds nuw i8, ptr {{%[0-9]}}, i64 8 + // X64: getelementptr inbounds nuw i8, ptr {{%[0-9]}}, i64 984 + // X64: getelementptr inbounds nuw i8, ptr %3, i64 80 // X64: icmp sgt i32 {{.*[0-9]}}, 67240703 // X64: ret i32 int a = (*(int*)(80 + ((char**** __ptr32*)1208)[0][11][1][123]) > 0x040202FF); @@ -189,7 +189,7 @@ int test_function_ptr32_is_32bit() { int get_processor_count() { // X64-LABEL: define signext range(i32 -128, 128) i32 @get_processor_count() // X64: load ptr addrspace(1), ptr inttoptr (i64 16 to ptr) - // X64-NEXT: [[ARR_IDX1:%[a-z].*]] = getelementptr inbounds i8, ptr addrspace(1) %0, i32 660 + // X64-NEXT: [[ARR_IDX1:%[a-z].*]] = getelementptr inbounds nuw i8, ptr addrspace(1) %0, i32 660 // X64: load ptr addrspace(1), ptr addrspace(1) [[ARR_IDX1]] // X64: load i8, ptr addrspace(1) {{%[a-z].*}} // X64: sext i8 {{%[0-9]}} to i32 diff --git a/clang/test/CodeGen/X86/cx-complex-range.c b/clang/test/CodeGen/X86/cx-complex-range.c index a0e6dc219b36f..f87091427df71 100644 --- a/clang/test/CodeGen/X86/cx-complex-range.c +++ b/clang/test/CodeGen/X86/cx-complex-range.c @@ -266,14 +266,14 @@ // BASIC_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 // BASIC_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 // BASIC_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 -// BASIC_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float -// BASIC_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// BASIC_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_REAL]] to float +// BASIC_FAST-NEXT: [[EXT1:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_IMAG]] to float // BASIC_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 // BASIC_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 // BASIC_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 // BASIC_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 -// BASIC_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float -// BASIC_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// BASIC_FAST-NEXT: [[EXT2:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_REAL]] to float +// BASIC_FAST-NEXT: [[EXT3:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_IMAG]] to float // BASIC_FAST-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT2]] // BASIC_FAST-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT3]] // BASIC_FAST-NEXT: [[TMP2:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP0]], [[TMP1]] @@ -285,8 +285,8 @@ // BASIC_FAST-NEXT: [[TMP8:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[TMP6]], [[TMP7]] // BASIC_FAST-NEXT: [[TMP9:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP2]], [[TMP5]] // BASIC_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP8]], [[TMP5]] -// BASIC_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP9]] to half -// BASIC_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[TMP10]] to half +// BASIC_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[TMP9]] to half +// BASIC_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[TMP10]] to half // BASIC_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // BASIC_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // BASIC_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 @@ -307,22 +307,22 @@ // FULL_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 // FULL_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 // FULL_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 -// FULL_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float -// FULL_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// FULL_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_REAL]] to float +// FULL_FAST-NEXT: [[EXT1:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_IMAG]] to float // FULL_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 // FULL_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 // FULL_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 // FULL_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 -// FULL_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float -// FULL_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// FULL_FAST-NEXT: [[EXT2:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_REAL]] to float +// FULL_FAST-NEXT: [[EXT3:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_IMAG]] to float // FULL_FAST-NEXT: [[CALL:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) <2 x float> @__divsc3(float noundef nofpclass(nan inf) [[EXT]], float noundef nofpclass(nan inf) [[EXT1]], float noundef nofpclass(nan inf) [[EXT2]], float noundef nofpclass(nan inf) [[EXT3]]) #[[ATTR1:[0-9]+]] // FULL_FAST-NEXT: store <2 x float> [[CALL]], ptr [[COERCE]], align 4 // FULL_FAST-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 0 // FULL_FAST-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 // FULL_FAST-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1 // FULL_FAST-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 -// FULL_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[COERCE_REAL]] to half -// FULL_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[COERCE_IMAG]] to half +// FULL_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[COERCE_REAL]] to half +// FULL_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[COERCE_IMAG]] to half // FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // FULL_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // FULL_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 @@ -342,14 +342,14 @@ // IMPRVD_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 // IMPRVD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 // IMPRVD_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 -// IMPRVD_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float -// IMPRVD_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// IMPRVD_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_REAL]] to float +// IMPRVD_FAST-NEXT: [[EXT1:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_IMAG]] to float // IMPRVD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 // IMPRVD_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 // IMPRVD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 // IMPRVD_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 -// IMPRVD_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float -// IMPRVD_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// IMPRVD_FAST-NEXT: [[EXT2:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_REAL]] to float +// IMPRVD_FAST-NEXT: [[EXT3:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_IMAG]] to float // IMPRVD_FAST-NEXT: [[TMP0:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fabs.f32(float [[EXT2]]) // IMPRVD_FAST-NEXT: [[TMP1:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fabs.f32(float [[EXT3]]) // IMPRVD_FAST-NEXT: [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt float [[TMP0]], [[TMP1]] @@ -379,8 +379,8 @@ // IMPRVD_FAST: complex_div: // IMPRVD_FAST-NEXT: [[TMP20:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] // IMPRVD_FAST-NEXT: [[TMP21:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] -// IMPRVD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP20]] to half -// IMPRVD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[TMP21]] to half +// IMPRVD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[TMP20]] to half +// IMPRVD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[TMP21]] to half // IMPRVD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // IMPRVD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // IMPRVD_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 @@ -400,14 +400,14 @@ // PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 // PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 // PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 -// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float -// PRMTD_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_REAL]] to float +// PRMTD_FAST-NEXT: [[EXT1:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_IMAG]] to float // PRMTD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 // PRMTD_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 // PRMTD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 // PRMTD_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 -// PRMTD_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float -// PRMTD_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// PRMTD_FAST-NEXT: [[EXT2:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_REAL]] to float +// PRMTD_FAST-NEXT: [[EXT3:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_IMAG]] to float // PRMTD_FAST-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT2]] // PRMTD_FAST-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT3]] // PRMTD_FAST-NEXT: [[TMP2:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP0]], [[TMP1]] @@ -419,8 +419,8 @@ // PRMTD_FAST-NEXT: [[TMP8:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[TMP6]], [[TMP7]] // PRMTD_FAST-NEXT: [[TMP9:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP2]], [[TMP5]] // PRMTD_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP8]], [[TMP5]] -// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP9]] to half -// PRMTD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[TMP10]] to half +// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[TMP9]] to half +// PRMTD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[TMP10]] to half // PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // PRMTD_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 @@ -636,22 +636,22 @@ _Complex _Float16 divf16(_Complex _Float16 a, _Complex _Float16 b) { // BASIC_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 // BASIC_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 // BASIC_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 -// BASIC_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float -// BASIC_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// BASIC_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_REAL]] to float +// BASIC_FAST-NEXT: [[EXT1:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_IMAG]] to float // BASIC_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 // BASIC_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 // BASIC_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 // BASIC_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 -// BASIC_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float -// BASIC_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// BASIC_FAST-NEXT: [[EXT2:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_REAL]] to float +// BASIC_FAST-NEXT: [[EXT3:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_IMAG]] to float // BASIC_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT2]] // BASIC_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT3]] // BASIC_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT3]] // BASIC_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT2]] // BASIC_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MUL_AC]], [[MUL_BD]] // BASIC_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[MUL_AD]], [[MUL_BC]] -// BASIC_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[MUL_R]] to half -// BASIC_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[MUL_I]] to half +// BASIC_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[MUL_R]] to half +// BASIC_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[MUL_I]] to half // BASIC_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // BASIC_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // BASIC_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 @@ -672,14 +672,14 @@ _Complex _Float16 divf16(_Complex _Float16 a, _Complex _Float16 b) { // FULL_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 // FULL_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 // FULL_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 -// FULL_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float -// FULL_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// FULL_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_REAL]] to float +// FULL_FAST-NEXT: [[EXT1:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_IMAG]] to float // FULL_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 // FULL_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 // FULL_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 // FULL_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 -// FULL_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float -// FULL_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// FULL_FAST-NEXT: [[EXT2:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_REAL]] to float +// FULL_FAST-NEXT: [[EXT3:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_IMAG]] to float // FULL_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT2]] // FULL_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT3]] // FULL_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT3]] @@ -702,8 +702,8 @@ _Complex _Float16 divf16(_Complex _Float16 a, _Complex _Float16 b) { // FULL_FAST: complex_mul_cont: // FULL_FAST-NEXT: [[REAL_MUL_PHI:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_REAL]], [[COMPLEX_MUL_LIBCALL]] ] // FULL_FAST-NEXT: [[IMAG_MUL_PHI:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_IMAG]], [[COMPLEX_MUL_LIBCALL]] ] -// FULL_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[REAL_MUL_PHI]] to half -// FULL_FAST-NEXT: [[UNPROMOTION5:%.*]] = fptrunc float [[IMAG_MUL_PHI]] to half +// FULL_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[REAL_MUL_PHI]] to half +// FULL_FAST-NEXT: [[UNPROMOTION5:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[IMAG_MUL_PHI]] to half // FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // FULL_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // FULL_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 @@ -723,22 +723,22 @@ _Complex _Float16 divf16(_Complex _Float16 a, _Complex _Float16 b) { // IMPRVD_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 // IMPRVD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 // IMPRVD_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 -// IMPRVD_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float -// IMPRVD_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// IMPRVD_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_REAL]] to float +// IMPRVD_FAST-NEXT: [[EXT1:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_IMAG]] to float // IMPRVD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 // IMPRVD_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 // IMPRVD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 // IMPRVD_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 -// IMPRVD_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float -// IMPRVD_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// IMPRVD_FAST-NEXT: [[EXT2:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_REAL]] to float +// IMPRVD_FAST-NEXT: [[EXT3:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_IMAG]] to float // IMPRVD_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT2]] // IMPRVD_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT3]] // IMPRVD_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT3]] // IMPRVD_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT2]] // IMPRVD_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MUL_AC]], [[MUL_BD]] // IMPRVD_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[MUL_AD]], [[MUL_BC]] -// IMPRVD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[MUL_R]] to half -// IMPRVD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[MUL_I]] to half +// IMPRVD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[MUL_R]] to half +// IMPRVD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[MUL_I]] to half // IMPRVD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // IMPRVD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // IMPRVD_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 @@ -758,22 +758,22 @@ _Complex _Float16 divf16(_Complex _Float16 a, _Complex _Float16 b) { // PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 // PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 // PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 -// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float -// PRMTD_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_REAL]] to float +// PRMTD_FAST-NEXT: [[EXT1:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_IMAG]] to float // PRMTD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 // PRMTD_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 // PRMTD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 // PRMTD_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 -// PRMTD_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float -// PRMTD_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// PRMTD_FAST-NEXT: [[EXT2:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_REAL]] to float +// PRMTD_FAST-NEXT: [[EXT3:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[B_IMAG]] to float // PRMTD_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT2]] // PRMTD_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT3]] // PRMTD_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT3]] // PRMTD_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT2]] // PRMTD_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MUL_AC]], [[MUL_BD]] // PRMTD_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[MUL_AD]], [[MUL_BC]] -// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[MUL_R]] to half -// PRMTD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[MUL_I]] to half +// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[MUL_R]] to half +// PRMTD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[MUL_I]] to half // PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // PRMTD_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 @@ -1158,8 +1158,8 @@ _Complex _Float16 mulf16(_Complex _Float16 a, _Complex _Float16 b) { // BASIC_FAST-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 // BASIC_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 // BASIC_FAST-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 -// BASIC_FAST-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to x86_fp80 -// BASIC_FAST-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to x86_fp80 +// BASIC_FAST-NEXT: [[CONV:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[C_REAL]] to x86_fp80 +// BASIC_FAST-NEXT: [[CONV1:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[C_IMAG]] to x86_fp80 // BASIC_FAST-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[CONV]] // BASIC_FAST-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[CONV1]] // BASIC_FAST-NEXT: [[TMP2:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP0]], [[TMP1]] @@ -1171,16 +1171,16 @@ _Complex _Float16 mulf16(_Complex _Float16 a, _Complex _Float16 b) { // BASIC_FAST-NEXT: [[TMP8:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP6]], [[TMP7]] // BASIC_FAST-NEXT: [[TMP9:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP2]], [[TMP5]] // BASIC_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP8]], [[TMP5]] -// BASIC_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP9]] to half -// BASIC_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP10]] to half -// BASIC_FAST-NEXT: [[EXT:%.*]] = fpext half [[CONV2]] to float -// BASIC_FAST-NEXT: [[EXT4:%.*]] = fpext half [[CONV3]] to float +// BASIC_FAST-NEXT: [[CONV2:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP9]] to half +// BASIC_FAST-NEXT: [[CONV3:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP10]] to half +// BASIC_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[CONV2]] to float +// BASIC_FAST-NEXT: [[EXT4:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[CONV3]] to float // BASIC_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 // BASIC_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 // BASIC_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 // BASIC_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 -// BASIC_FAST-NEXT: [[EXT5:%.*]] = fpext half [[A_REAL]] to float -// BASIC_FAST-NEXT: [[EXT6:%.*]] = fpext half [[A_IMAG]] to float +// BASIC_FAST-NEXT: [[EXT5:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_REAL]] to float +// BASIC_FAST-NEXT: [[EXT6:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_IMAG]] to float // BASIC_FAST-NEXT: [[TMP11:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT5]] // BASIC_FAST-NEXT: [[TMP12:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT4]], [[EXT6]] // BASIC_FAST-NEXT: [[TMP13:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP11]], [[TMP12]] @@ -1192,8 +1192,8 @@ _Complex _Float16 mulf16(_Complex _Float16 a, _Complex _Float16 b) { // BASIC_FAST-NEXT: [[TMP19:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[TMP17]], [[TMP18]] // BASIC_FAST-NEXT: [[TMP20:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP13]], [[TMP16]] // BASIC_FAST-NEXT: [[TMP21:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP19]], [[TMP16]] -// BASIC_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP20]] to half -// BASIC_FAST-NEXT: [[UNPROMOTION7:%.*]] = fptrunc float [[TMP21]] to half +// BASIC_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[TMP20]] to half +// BASIC_FAST-NEXT: [[UNPROMOTION7:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[TMP21]] to half // BASIC_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // BASIC_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // BASIC_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 @@ -1218,29 +1218,29 @@ _Complex _Float16 mulf16(_Complex _Float16 a, _Complex _Float16 b) { // FULL_FAST-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 // FULL_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 // FULL_FAST-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 -// FULL_FAST-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to x86_fp80 -// FULL_FAST-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to x86_fp80 +// FULL_FAST-NEXT: [[CONV:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[C_REAL]] to x86_fp80 +// FULL_FAST-NEXT: [[CONV1:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[C_IMAG]] to x86_fp80 // FULL_FAST-NEXT: [[CALL:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) { x86_fp80, x86_fp80 } @__divxc3(x86_fp80 noundef nofpclass(nan inf) [[B_REAL]], x86_fp80 noundef nofpclass(nan inf) [[B_IMAG]], x86_fp80 noundef nofpclass(nan inf) [[CONV]], x86_fp80 noundef nofpclass(nan inf) [[CONV1]]) #[[ATTR1]] // FULL_FAST-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0 // FULL_FAST-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1 -// FULL_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP0]] to half -// FULL_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP1]] to half -// FULL_FAST-NEXT: [[EXT:%.*]] = fpext half [[CONV2]] to float -// FULL_FAST-NEXT: [[EXT4:%.*]] = fpext half [[CONV3]] to float +// FULL_FAST-NEXT: [[CONV2:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP0]] to half +// FULL_FAST-NEXT: [[CONV3:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP1]] to half +// FULL_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[CONV2]] to float +// FULL_FAST-NEXT: [[EXT4:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[CONV3]] to float // FULL_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 // FULL_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 // FULL_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 // FULL_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 -// FULL_FAST-NEXT: [[EXT5:%.*]] = fpext half [[A_REAL]] to float -// FULL_FAST-NEXT: [[EXT6:%.*]] = fpext half [[A_IMAG]] to float +// FULL_FAST-NEXT: [[EXT5:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_REAL]] to float +// FULL_FAST-NEXT: [[EXT6:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_IMAG]] to float // FULL_FAST-NEXT: [[CALL7:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) <2 x float> @__divsc3(float noundef nofpclass(nan inf) [[EXT]], float noundef nofpclass(nan inf) [[EXT4]], float noundef nofpclass(nan inf) [[EXT5]], float noundef nofpclass(nan inf) [[EXT6]]) #[[ATTR1]] // FULL_FAST-NEXT: store <2 x float> [[CALL7]], ptr [[COERCE]], align 4 // FULL_FAST-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 0 // FULL_FAST-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 // FULL_FAST-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1 // FULL_FAST-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 -// FULL_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[COERCE_REAL]] to half -// FULL_FAST-NEXT: [[UNPROMOTION8:%.*]] = fptrunc float [[COERCE_IMAG]] to half +// FULL_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[COERCE_REAL]] to half +// FULL_FAST-NEXT: [[UNPROMOTION8:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[COERCE_IMAG]] to half // FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // FULL_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // FULL_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 @@ -1264,8 +1264,8 @@ _Complex _Float16 mulf16(_Complex _Float16 a, _Complex _Float16 b) { // IMPRVD_FAST-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 // IMPRVD_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 // IMPRVD_FAST-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 -// IMPRVD_FAST-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to x86_fp80 -// IMPRVD_FAST-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to x86_fp80 +// IMPRVD_FAST-NEXT: [[CONV:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[C_REAL]] to x86_fp80 +// IMPRVD_FAST-NEXT: [[CONV1:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[C_IMAG]] to x86_fp80 // IMPRVD_FAST-NEXT: [[TMP0:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV]]) // IMPRVD_FAST-NEXT: [[TMP1:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV1]]) // IMPRVD_FAST-NEXT: [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt x86_fp80 [[TMP0]], [[TMP1]] @@ -1295,16 +1295,16 @@ _Complex _Float16 mulf16(_Complex _Float16 a, _Complex _Float16 b) { // IMPRVD_FAST: complex_div: // IMPRVD_FAST-NEXT: [[TMP20:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] // IMPRVD_FAST-NEXT: [[TMP21:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] -// IMPRVD_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP20]] to half -// IMPRVD_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP21]] to half -// IMPRVD_FAST-NEXT: [[EXT:%.*]] = fpext half [[CONV2]] to float -// IMPRVD_FAST-NEXT: [[EXT4:%.*]] = fpext half [[CONV3]] to float +// IMPRVD_FAST-NEXT: [[CONV2:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP20]] to half +// IMPRVD_FAST-NEXT: [[CONV3:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP21]] to half +// IMPRVD_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[CONV2]] to float +// IMPRVD_FAST-NEXT: [[EXT4:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[CONV3]] to float // IMPRVD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 // IMPRVD_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 // IMPRVD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 // IMPRVD_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 -// IMPRVD_FAST-NEXT: [[EXT5:%.*]] = fpext half [[A_REAL]] to float -// IMPRVD_FAST-NEXT: [[EXT6:%.*]] = fpext half [[A_IMAG]] to float +// IMPRVD_FAST-NEXT: [[EXT5:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_REAL]] to float +// IMPRVD_FAST-NEXT: [[EXT6:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_IMAG]] to float // IMPRVD_FAST-NEXT: [[TMP22:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fabs.f32(float [[EXT5]]) // IMPRVD_FAST-NEXT: [[TMP23:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fabs.f32(float [[EXT6]]) // IMPRVD_FAST-NEXT: [[ABS_CMP7:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt float [[TMP22]], [[TMP23]] @@ -1334,8 +1334,8 @@ _Complex _Float16 mulf16(_Complex _Float16 a, _Complex _Float16 b) { // IMPRVD_FAST: complex_div10: // IMPRVD_FAST-NEXT: [[TMP42:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[TMP29]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI8]] ], [ [[TMP38]], [[ABS_RHSR_LESS_THAN_ABS_RHSI9]] ] // IMPRVD_FAST-NEXT: [[TMP43:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[TMP32]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI8]] ], [ [[TMP41]], [[ABS_RHSR_LESS_THAN_ABS_RHSI9]] ] -// IMPRVD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP42]] to half -// IMPRVD_FAST-NEXT: [[UNPROMOTION11:%.*]] = fptrunc float [[TMP43]] to half +// IMPRVD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[TMP42]] to half +// IMPRVD_FAST-NEXT: [[UNPROMOTION11:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[TMP43]] to half // IMPRVD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // IMPRVD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // IMPRVD_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 @@ -1359,8 +1359,8 @@ _Complex _Float16 mulf16(_Complex _Float16 a, _Complex _Float16 b) { // PRMTD_FAST-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 // PRMTD_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 // PRMTD_FAST-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 -// PRMTD_FAST-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to x86_fp80 -// PRMTD_FAST-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to x86_fp80 +// PRMTD_FAST-NEXT: [[CONV:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[C_REAL]] to x86_fp80 +// PRMTD_FAST-NEXT: [[CONV1:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[C_IMAG]] to x86_fp80 // PRMTD_FAST-NEXT: [[TMP0:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV]]) // PRMTD_FAST-NEXT: [[TMP1:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV1]]) // PRMTD_FAST-NEXT: [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt x86_fp80 [[TMP0]], [[TMP1]] @@ -1390,16 +1390,16 @@ _Complex _Float16 mulf16(_Complex _Float16 a, _Complex _Float16 b) { // PRMTD_FAST: complex_div: // PRMTD_FAST-NEXT: [[TMP20:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] // PRMTD_FAST-NEXT: [[TMP21:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] -// PRMTD_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP20]] to half -// PRMTD_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP21]] to half -// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext half [[CONV2]] to float -// PRMTD_FAST-NEXT: [[EXT4:%.*]] = fpext half [[CONV3]] to float +// PRMTD_FAST-NEXT: [[CONV2:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP20]] to half +// PRMTD_FAST-NEXT: [[CONV3:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP21]] to half +// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[CONV2]] to float +// PRMTD_FAST-NEXT: [[EXT4:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[CONV3]] to float // PRMTD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 // PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 // PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 // PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 -// PRMTD_FAST-NEXT: [[EXT5:%.*]] = fpext half [[A_REAL]] to float -// PRMTD_FAST-NEXT: [[EXT6:%.*]] = fpext half [[A_IMAG]] to float +// PRMTD_FAST-NEXT: [[EXT5:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_REAL]] to float +// PRMTD_FAST-NEXT: [[EXT6:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[A_IMAG]] to float // PRMTD_FAST-NEXT: [[TMP22:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT5]] // PRMTD_FAST-NEXT: [[TMP23:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT4]], [[EXT6]] // PRMTD_FAST-NEXT: [[TMP24:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP22]], [[TMP23]] @@ -1411,8 +1411,8 @@ _Complex _Float16 mulf16(_Complex _Float16 a, _Complex _Float16 b) { // PRMTD_FAST-NEXT: [[TMP30:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[TMP28]], [[TMP29]] // PRMTD_FAST-NEXT: [[TMP31:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP24]], [[TMP27]] // PRMTD_FAST-NEXT: [[TMP32:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP30]], [[TMP27]] -// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP31]] to half -// PRMTD_FAST-NEXT: [[UNPROMOTION7:%.*]] = fptrunc float [[TMP32]] to half +// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[TMP31]] to half +// PRMTD_FAST-NEXT: [[UNPROMOTION7:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn float [[TMP32]] to half // PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // PRMTD_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 diff --git a/clang/test/CodeGen/allow-ubsan-check-inline.c b/clang/test/CodeGen/allow-ubsan-check-inline.c new file mode 100644 index 0000000000000..1de24ab90dac0 --- /dev/null +++ b/clang/test/CodeGen/allow-ubsan-check-inline.c @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s -fsanitize=signed-integer-overflow -mllvm -ubsan-guard-checks -O3 -mllvm -lower-allow-check-random-rate=1 -Rpass=lower-allow-check -Rpass-missed=lower-allow-check -fno-inline 2>&1 | FileCheck %s --check-prefixes=NOINL --implicit-check-not="remark:" +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s -fsanitize=signed-integer-overflow -mllvm -ubsan-guard-checks -O3 -mllvm -lower-allow-check-random-rate=1 -Rpass=lower-allow-check -Rpass-missed=lower-allow-check 2>&1 | FileCheck %s --check-prefixes=INLINE --implicit-check-not="remark:" + +int get(); +void set(int x); + +// We will only make decision in the `overflow` function. +// NOINL-COUNT-1: remark: Allowed check: + +// We will make decision on every inline. +// INLINE-COUNT-5: remark: Allowed check: + +static void overflow() { + set(get() + get()); +} + +void test() { + overflow(); + overflow(); + overflow(); + overflow(); + overflow(); +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vadc.c b/clang/test/CodeGen/arm-mve-intrinsics/vadc.c index 21087b83300c8..29e067d65c6c8 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/vadc.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/vadc.c @@ -92,7 +92,7 @@ int32x4_t test_vadcq_m_s32(int32x4_t inactive, int32x4_t a, int32x4_t b, unsigne // CHECK-LABEL: @test_vsbciq_s32( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = call { <4 x i32>, i32 } @llvm.arm.mve.vsbc.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], i32 0) +// CHECK-NEXT: [[TMP0:%.*]] = call { <4 x i32>, i32 } @llvm.arm.mve.vsbc.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], i32 536870912) // CHECK-NEXT: [[TMP1:%.*]] = extractvalue { <4 x i32>, i32 } [[TMP0]], 1 // CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 29 // CHECK-NEXT: [[TMP3:%.*]] = and i32 1, [[TMP2]] @@ -110,7 +110,7 @@ int32x4_t test_vsbciq_s32(int32x4_t a, int32x4_t b, unsigned *carry_out) { // CHECK-LABEL: @test_vsbciq_u32( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = call { <4 x i32>, i32 } @llvm.arm.mve.vsbc.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], i32 0) +// CHECK-NEXT: [[TMP0:%.*]] = call { <4 x i32>, i32 } @llvm.arm.mve.vsbc.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], i32 536870912) // CHECK-NEXT: [[TMP1:%.*]] = extractvalue { <4 x i32>, i32 } [[TMP0]], 1 // CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 29 // CHECK-NEXT: [[TMP3:%.*]] = and i32 1, [[TMP2]] @@ -170,7 +170,7 @@ uint32x4_t test_vsbcq_u32(uint32x4_t a, uint32x4_t b, unsigned *carry) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 // CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call { <4 x i32>, i32 } @llvm.arm.mve.vsbc.predicated.v4i32.v4i1(<4 x i32> [[INACTIVE:%.*]], <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], i32 0, <4 x i1> [[TMP1]]) +// CHECK-NEXT: [[TMP2:%.*]] = call { <4 x i32>, i32 } @llvm.arm.mve.vsbc.predicated.v4i32.v4i1(<4 x i32> [[INACTIVE:%.*]], <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], i32 536870912, <4 x i1> [[TMP1]]) // CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <4 x i32>, i32 } [[TMP2]], 1 // CHECK-NEXT: [[TMP4:%.*]] = lshr i32 [[TMP3]], 29 // CHECK-NEXT: [[TMP5:%.*]] = and i32 1, [[TMP4]] @@ -190,7 +190,7 @@ int32x4_t test_vsbciq_m_s32(int32x4_t inactive, int32x4_t a, int32x4_t b, unsign // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 // CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call { <4 x i32>, i32 } @llvm.arm.mve.vsbc.predicated.v4i32.v4i1(<4 x i32> [[INACTIVE:%.*]], <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], i32 0, <4 x i1> [[TMP1]]) +// CHECK-NEXT: [[TMP2:%.*]] = call { <4 x i32>, i32 } @llvm.arm.mve.vsbc.predicated.v4i32.v4i1(<4 x i32> [[INACTIVE:%.*]], <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], i32 536870912, <4 x i1> [[TMP1]]) // CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <4 x i32>, i32 } [[TMP2]], 1 // CHECK-NEXT: [[TMP4:%.*]] = lshr i32 [[TMP3]], 29 // CHECK-NEXT: [[TMP5:%.*]] = and i32 1, [[TMP4]] diff --git a/clang/test/CodeGen/arm64-microsoft-intrinsics.c b/clang/test/CodeGen/arm64-microsoft-intrinsics.c index 7953618d2f9d1..74c6f2f79e632 100644 --- a/clang/test/CodeGen/arm64-microsoft-intrinsics.c +++ b/clang/test/CodeGen/arm64-microsoft-intrinsics.c @@ -164,12 +164,12 @@ void check__writex18byte(unsigned LONG offset, unsigned char data) { // CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 // CHECK-MSCOMPAT: store i8 %data, ptr %[[DATA_ADDR]], align 1 // CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i8, ptr %[[DATA_ADDR]], align 1 // CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) // CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr -// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 // CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 // CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] -// CHECK-MSCOMPAT: %[[DATA:.*]] = load i8, ptr %[[DATA_ADDR]], align 1 // CHECK-MSCOMPAT: store i8 %[[DATA]], ptr %[[PTR]], align 1 #ifdef __LP64__ @@ -184,12 +184,12 @@ void check__writex18word(unsigned LONG offset, unsigned short data) { // CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 // CHECK-MSCOMPAT: store i16 %data, ptr %[[DATA_ADDR]], align 2 // CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i16, ptr %[[DATA_ADDR]], align 2 // CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) // CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr -// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 // CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 // CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] -// CHECK-MSCOMPAT: %[[DATA:.*]] = load i16, ptr %[[DATA_ADDR]], align 2 // CHECK-MSCOMPAT: store i16 %[[DATA]], ptr %[[PTR]], align 1 #ifdef __LP64__ @@ -204,12 +204,12 @@ void check__writex18dword(unsigned LONG offset, unsigned LONG data) { // CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 // CHECK-MSCOMPAT: store i32 %data, ptr %[[DATA_ADDR]], align 4 // CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i32, ptr %[[DATA_ADDR]], align 4 // CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) // CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr -// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 // CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 // CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] -// CHECK-MSCOMPAT: %[[DATA:.*]] = load i32, ptr %[[DATA_ADDR]], align 4 // CHECK-MSCOMPAT: store i32 %[[DATA]], ptr %[[PTR]], align 1 #ifdef __LP64__ @@ -224,12 +224,12 @@ void check__writex18qword(unsigned LONG offset, unsigned __int64 data) { // CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 // CHECK-MSCOMPAT: store i64 %data, ptr %[[DATA_ADDR]], align 8 // CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i64, ptr %[[DATA_ADDR]], align 8 // CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) // CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr -// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 // CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 // CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] -// CHECK-MSCOMPAT: %[[DATA:.*]] = load i64, ptr %[[DATA_ADDR]], align 8 // CHECK-MSCOMPAT: store i64 %[[DATA]], ptr %[[PTR]], align 1 unsigned char check__readx18byte(unsigned LONG offset) { @@ -238,9 +238,9 @@ unsigned char check__readx18byte(unsigned LONG offset) { // CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 // CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 // CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) // CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr -// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 // CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 // CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] // CHECK-MSCOMPAT: %[[RETVAL:.*]] = load i8, ptr %[[PTR]], align 1 @@ -252,9 +252,9 @@ unsigned short check__readx18word(unsigned LONG offset) { // CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 // CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 // CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) // CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr -// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 // CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 // CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] // CHECK-MSCOMPAT: %[[RETVAL:.*]] = load i16, ptr %[[PTR]], align 1 @@ -266,9 +266,9 @@ unsigned LONG check__readx18dword(unsigned LONG offset) { // CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 // CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 // CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) // CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr -// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 // CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 // CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] // CHECK-MSCOMPAT: %[[RETVAL:.*]] = load i32, ptr %[[PTR]], align 1 @@ -280,14 +280,162 @@ unsigned __int64 check__readx18qword(unsigned LONG offset) { // CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 // CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 // CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) // CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr -// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 // CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 // CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] // CHECK-MSCOMPAT: %[[RETVAL:.*]] = load i64, ptr %[[PTR]], align 1 // CHECK-MSCOMPAT: ret i64 %[[RETVAL]] +#ifdef __LP64__ +void check__addx18byte(unsigned char data, unsigned LONG offset) { +#else +void check__addx18byte(unsigned LONG offset, unsigned char data) { +#endif + __addx18byte(offset, data); +} + +// CHECK-MSCOMPAT: %[[DATA_ADDR:.*]] = alloca i8, align 1 +// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 +// CHECK-MSCOMPAT: store i8 %data, ptr %[[DATA_ADDR]], align 1 +// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i8, ptr %[[DATA_ADDR]], align 1 +// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) +// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr +// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 +// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] +// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i8, ptr %[[PTR]], align 1 +// CHECK-MSCOMPAT: %[[SUM:.*]] = add i8 %[[ORIG_VAL]], %[[DATA]] +// CHECK-MSCOMPAT: store i8 %[[SUM]], ptr %[[PTR]], align 1 + +#ifdef __LP64__ +void check__addx18word(unsigned short data, unsigned LONG offset) { +#else +void check__addx18word(unsigned LONG offset, unsigned short data) { +#endif + __addx18word(offset, data); +} + +// CHECK-MSCOMPAT: %[[DATA_ADDR:.*]] = alloca i16, align 2 +// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 +// CHECK-MSCOMPAT: store i16 %data, ptr %[[DATA_ADDR]], align 2 +// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i16, ptr %[[DATA_ADDR]], align 2 +// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) +// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr +// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 +// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] +// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i16, ptr %[[PTR]], align 1 +// CHECK-MSCOMPAT: %[[SUM:.*]] = add i16 %[[ORIG_VAL]], %[[DATA]] +// CHECK-MSCOMPAT: store i16 %[[SUM]], ptr %[[PTR]], align 1 + +#ifdef __LP64__ +void check__addx18dword(unsigned LONG data, unsigned LONG offset) { +#else +void check__addx18dword(unsigned LONG offset, unsigned LONG data) { +#endif + __addx18dword(offset, data); +} + +// CHECK-MSCOMPAT: %[[DATA_ADDR:.*]] = alloca i32, align 4 +// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 +// CHECK-MSCOMPAT: store i32 %data, ptr %[[DATA_ADDR]], align 4 +// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i32, ptr %[[DATA_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) +// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr +// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 +// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] +// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i32, ptr %[[PTR]], align 1 +// CHECK-MSCOMPAT: %[[SUM:.*]] = add i32 %[[ORIG_VAL]], %[[DATA]] +// CHECK-MSCOMPAT: store i32 %[[SUM]], ptr %[[PTR]], align 1 + +#ifdef __LP64__ +void check__addx18qword(unsigned __int64 data, unsigned LONG offset) { +#else +void check__addx18qword(unsigned LONG offset, unsigned __int64 data) { +#endif + __addx18qword(offset, data); +} + +// CHECK-MSCOMPAT: %[[DATA_ADDR:.*]] = alloca i64, align 8 +// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 +// CHECK-MSCOMPAT: store i64 %data, ptr %[[DATA_ADDR]], align 8 +// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[DATA:.*]] = load i64, ptr %[[DATA_ADDR]], align 8 +// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) +// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr +// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 +// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] +// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i64, ptr %[[PTR]], align 1 +// CHECK-MSCOMPAT: %[[SUM:.*]] = add i64 %[[ORIG_VAL]], %[[DATA]] +// CHECK-MSCOMPAT: store i64 %[[SUM]], ptr %[[PTR]], align 1 + +void check__incx18byte(unsigned LONG offset) { + __incx18byte(offset); +} + +// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 +// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) +// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr +// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 +// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] +// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i8, ptr %[[PTR]], align 1 +// CHECK-MSCOMPAT: %[[SUM:.*]] = add i8 %[[ORIG_VAL]], 1 +// CHECK-MSCOMPAT: store i8 %[[SUM]], ptr %[[PTR]], align 1 + +void check__incx18word(unsigned LONG offset) { + __incx18word(offset); +} + +// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 +// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) +// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr +// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 +// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] +// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i16, ptr %[[PTR]], align 1 +// CHECK-MSCOMPAT: %[[SUM:.*]] = add i16 %[[ORIG_VAL]], 1 +// CHECK-MSCOMPAT: store i16 %[[SUM]], ptr %[[PTR]], align 1 + +void check__incx18dword(unsigned LONG offset) { + __incx18dword(offset); +} + +// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 +// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) +// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr +// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 +// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] +// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i32, ptr %[[PTR]], align 1 +// CHECK-MSCOMPAT: %[[SUM:.*]] = add i32 %[[ORIG_VAL]], 1 +// CHECK-MSCOMPAT: store i32 %[[SUM]], ptr %[[PTR]], align 1 + +void check__incx18qword(unsigned LONG offset) { + __incx18qword(offset); +} + +// CHECK-MSCOMPAT: %[[OFFSET_ADDR:.*]] = alloca i32, align 4 +// CHECK-MSCOMPAT: store i32 %offset, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[OFFSET:.*]] = load i32, ptr %[[OFFSET_ADDR]], align 4 +// CHECK-MSCOMPAT: %[[X18:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2]]) +// CHECK-MSCOMPAT: %[[X18_AS_PTR:.*]] = inttoptr i64 %[[X18]] to ptr +// CHECK-MSCOMPAT: %[[ZEXT_OFFSET:.*]] = zext i32 %[[OFFSET]] to i64 +// CHECK-MSCOMPAT: %[[PTR:.*]] = getelementptr i8, ptr %[[X18_AS_PTR]], i64 %[[ZEXT_OFFSET]] +// CHECK-MSCOMPAT: %[[ORIG_VAL:.*]] = load i64, ptr %[[PTR]], align 1 +// CHECK-MSCOMPAT: %[[SUM:.*]] = add i64 %[[ORIG_VAL]], 1 +// CHECK-MSCOMPAT: store i64 %[[SUM]], ptr %[[PTR]], align 1 + double check__CopyDoubleFromInt64(__int64 arg1) { return _CopyDoubleFromInt64(arg1); } diff --git a/clang/test/CodeGen/arm64_32-vaarg.c b/clang/test/CodeGen/arm64_32-vaarg.c index 3f1f4443436da..72c23d4967d2d 100644 --- a/clang/test/CodeGen/arm64_32-vaarg.c +++ b/clang/test/CodeGen/arm64_32-vaarg.c @@ -10,7 +10,7 @@ typedef struct { int test_int(OneInt input, va_list *mylist) { // CHECK-LABEL: define{{.*}} i32 @test_int(i32 %input // CHECK: [[START:%.*]] = load ptr, ptr %mylist -// CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, ptr [[START]], i32 4 +// CHECK: [[NEXT:%.*]] = getelementptr inbounds nuw i8, ptr [[START]], i32 4 // CHECK: store ptr [[NEXT]], ptr %mylist // CHECK: [[RES:%.*]] = load i32, ptr [[START]] @@ -28,9 +28,9 @@ typedef struct { long long test_longlong(OneLongLong input, va_list *mylist) { // CHECK-LABEL: define{{.*}} i64 @test_longlong(i64 %input // CHECK: [[STARTPTR:%.*]] = load ptr, ptr %mylist - // CHECK: [[ALIGN_TMP:%.+]] = getelementptr inbounds i8, ptr [[STARTPTR]], i32 7 + // CHECK: [[ALIGN_TMP:%.+]] = getelementptr inbounds nuw i8, ptr [[STARTPTR]], i32 7 // CHECK: [[ALIGNED_ADDR:%.+]] = tail call align 8 ptr @llvm.ptrmask.p0.i32(ptr nonnull [[ALIGN_TMP]], i32 -8) - // CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, ptr [[ALIGNED_ADDR]], i32 8 + // CHECK: [[NEXT:%.*]] = getelementptr inbounds nuw i8, ptr [[ALIGNED_ADDR]], i32 8 // CHECK: store ptr [[NEXT]], ptr %mylist // CHECK: [[RES:%.*]] = load i64, ptr [[ALIGNED_ADDR]] @@ -49,7 +49,7 @@ float test_hfa(va_list *mylist) { // CHECK-LABEL: define{{.*}} float @test_hfa // CHECK: [[START:%.*]] = load ptr, ptr %mylist -// CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, ptr [[START]], i32 16 +// CHECK: [[NEXT:%.*]] = getelementptr inbounds nuw i8, ptr [[START]], i32 16 // CHECK: store ptr [[NEXT]], ptr %mylist // CHECK: [[RES:%.*]] = load float, ptr [[START]] @@ -76,7 +76,7 @@ typedef struct { long long test_bigstruct(BigStruct input, va_list *mylist) { // CHECK-LABEL: define{{.*}} i64 @test_bigstruct(ptr // CHECK: [[START:%.*]] = load ptr, ptr %mylist -// CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, ptr [[START]], i32 4 +// CHECK: [[NEXT:%.*]] = getelementptr inbounds nuw i8, ptr [[START]], i32 4 // CHECK: store ptr [[NEXT]], ptr %mylist // CHECK: [[ADDR:%.*]] = load ptr, ptr [[START]] @@ -97,7 +97,7 @@ short test_threeshorts(ThreeShorts input, va_list *mylist) { // CHECK-LABEL: define{{.*}} signext i16 @test_threeshorts([2 x i32] %input // CHECK: [[START:%.*]] = load ptr, ptr %mylist -// CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, ptr [[START]], i32 8 +// CHECK: [[NEXT:%.*]] = getelementptr inbounds nuw i8, ptr [[START]], i32 8 // CHECK: store ptr [[NEXT]], ptr %mylist // CHECK: [[RES:%.*]] = load i16, ptr [[START]] diff --git a/clang/test/CodeGen/attr-counted-by-pr110385.c b/clang/test/CodeGen/attr-counted-by-pr110385.c index e120dcc583578..c2ff032334fe2 100644 --- a/clang/test/CodeGen/attr-counted-by-pr110385.c +++ b/clang/test/CodeGen/attr-counted-by-pr110385.c @@ -31,7 +31,7 @@ void init(void * __attribute__((pass_dynamic_object_size(0)))); // CHECK-NEXT: [[GROWABLE:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 8 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[GROWABLE]], align 8, !tbaa [[TBAA2:![0-9]+]] // CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 12 -// CHECK-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8 +// CHECK-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 8 // CHECK-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 // CHECK-NEXT: [[TMP2:%.*]] = shl nsw i64 [[TMP1]], 1 @@ -48,7 +48,7 @@ void test1(struct bucket *foo) { // CHECK-SAME: ptr noundef [[FOO:%.*]]) local_unnamed_addr #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 16 -// CHECK-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 12 +// CHECK-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 12 // CHECK-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 // CHECK-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 1 diff --git a/clang/test/CodeGen/attr-counted-by.c b/clang/test/CodeGen/attr-counted-by.c index d3f12bc5e07ab..6b3cad5708835 100644 --- a/clang/test/CodeGen/attr-counted-by.c +++ b/clang/test/CodeGen/attr-counted-by.c @@ -60,17 +60,17 @@ struct anon_struct { // SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[VAL:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2:![0-9]+]] // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP0]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3:![0-9]+]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB1:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR9:[0-9]+]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB1:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8:[0-9]+]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont3: // SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 12 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] // SANITIZE-WITH-ATTR-NEXT: store i32 [[VAL]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4:![0-9]+]] // SANITIZE-WITH-ATTR-NEXT: ret void // @@ -108,13 +108,13 @@ void test1(struct annotated *p, int index, int val) { // SANITIZE-WITH-ATTR-LABEL: define dso_local void @test2( // SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOT_COUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[INDEX]], [[TMP0]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB3:[0-9]+]], i64 [[INDEX]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB3:[0-9]+]], i64 [[INDEX]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont3: // SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 12 @@ -127,7 +127,7 @@ void test1(struct annotated *p, int index, int val) { // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test2( // NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.smax.i32(i32 [[DOT_COUNTED_BY_LOAD]], i32 0) // NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = shl i32 [[TMP0]], 2 @@ -159,7 +159,7 @@ void test2(struct annotated *p, size_t index) { // SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -8589934592, 8589934589) i64 @test2_bdos( // SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 2 @@ -170,7 +170,7 @@ void test2(struct annotated *p, size_t index) { // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -8589934592, 8589934589) i64 @test2_bdos( // NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 2 @@ -195,13 +195,13 @@ size_t test2_bdos(struct annotated *p) { // SANITIZE-WITH-ATTR-LABEL: define dso_local void @test3( // SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[INDEX]], [[TMP0]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[INDEX]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[INDEX]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont3: // SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 12 @@ -266,7 +266,7 @@ size_t test3_bdos(struct annotated *p) { // SANITIZE-WITH-ATTR-LABEL: define dso_local void @test4( // SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[FAM_IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 12 // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 @@ -274,7 +274,7 @@ size_t test3_bdos(struct annotated *p) { // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP0]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT4:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont4: // SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD]], 2 @@ -282,53 +282,50 @@ size_t test3_bdos(struct annotated *p) { // SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = add i32 [[TMP3]], 244 // SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 252 // SANITIZE-WITH-ATTR-NEXT: [[CONV1:%.*]] = select i1 [[TMP2]], i32 [[TMP5]], i32 0 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] // SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV1]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] -// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD6:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[ADD:%.*]] = add nsw i32 [[INDEX]], 1 // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM12:%.*]] = sext i32 [[ADD]] to i64 -// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[DOT_COUNTED_BY_LOAD6]] to i64, !nosanitize [[META2]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = icmp ult i64 [[IDXPROM12]], [[TMP6]], !nosanitize [[META2]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP7]], label [[CONT19:%.*]], label [[HANDLER_OUT_OF_BOUNDS15:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = icmp ult i64 [[IDXPROM12]], [[TMP0]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label [[CONT19:%.*]], label [[HANDLER_OUT_OF_BOUNDS15:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds15: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB6:[0-9]+]], i64 [[IDXPROM12]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB6:[0-9]+]], i64 [[IDXPROM12]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont19: -// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD6]], 3 -// SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = shl i32 [[DOT_COUNTED_BY_LOAD6]], 2 -// SANITIZE-WITH-ATTR-NEXT: [[TMP10:%.*]] = add i32 [[TMP9]], 240 -// SANITIZE-WITH-ATTR-NEXT: [[TMP11:%.*]] = and i32 [[TMP10]], 252 -// SANITIZE-WITH-ATTR-NEXT: [[CONV8:%.*]] = select i1 [[TMP8]], i32 [[TMP11]], i32 0 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX17:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM12]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD]], 3 +// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = add i32 [[TMP3]], 240 +// SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = and i32 [[TMP8]], 252 +// SANITIZE-WITH-ATTR-NEXT: [[CONV8:%.*]] = select i1 [[TMP7]], i32 [[TMP9]], i32 0 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX17:%.*]] = getelementptr inbounds nuw [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM12]] // SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV8]], ptr [[ARRAYIDX17]], align 4, !tbaa [[TBAA4]] // SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD21:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[ADD27:%.*]] = add nsw i32 [[INDEX]], 2 // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM28:%.*]] = sext i32 [[ADD27]] to i64 -// SANITIZE-WITH-ATTR-NEXT: [[TMP12:%.*]] = zext i32 [[DOT_COUNTED_BY_LOAD21]] to i64, !nosanitize [[META2]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP13:%.*]] = icmp ult i64 [[IDXPROM28]], [[TMP12]], !nosanitize [[META2]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP13]], label [[CONT35:%.*]], label [[HANDLER_OUT_OF_BOUNDS31:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP10:%.*]] = zext i32 [[DOT_COUNTED_BY_LOAD21]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP11:%.*]] = icmp ult i64 [[IDXPROM28]], [[TMP10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP11]], label [[CONT35:%.*]], label [[HANDLER_OUT_OF_BOUNDS31:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds31: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[IDXPROM28]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[IDXPROM28]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont35: -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX33:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM28]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP14:%.*]] = icmp sgt i32 [[FAM_IDX]], -1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP15:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD21]] to i64 -// SANITIZE-WITH-ATTR-NEXT: [[TMP16:%.*]] = sext i32 [[FAM_IDX]] to i64 -// SANITIZE-WITH-ATTR-NEXT: [[TMP17:%.*]] = sub nsw i64 [[TMP15]], [[TMP16]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP18:%.*]] = icmp sgt i64 [[TMP17]], -1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP19:%.*]] = and i1 [[TMP14]], [[TMP18]] -// SANITIZE-WITH-ATTR-NEXT: [[DOTTR:%.*]] = trunc i64 [[TMP17]] to i32 -// SANITIZE-WITH-ATTR-NEXT: [[TMP20:%.*]] = shl i32 [[DOTTR]], 2 -// SANITIZE-WITH-ATTR-NEXT: [[TMP21:%.*]] = and i32 [[TMP20]], 252 -// SANITIZE-WITH-ATTR-NEXT: [[CONV23:%.*]] = select i1 [[TMP19]], i32 [[TMP21]], i32 0 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX33:%.*]] = getelementptr inbounds nuw [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM28]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP12:%.*]] = icmp sgt i32 [[FAM_IDX]], -1 +// SANITIZE-WITH-ATTR-NEXT: [[TMP13:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD21]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP14:%.*]] = sext i32 [[FAM_IDX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP15:%.*]] = sub nsw i64 [[TMP13]], [[TMP14]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP16:%.*]] = icmp sgt i64 [[TMP15]], -1 +// SANITIZE-WITH-ATTR-NEXT: [[TMP17:%.*]] = and i1 [[TMP12]], [[TMP16]] +// SANITIZE-WITH-ATTR-NEXT: [[DOTTR:%.*]] = trunc i64 [[TMP15]] to i32 +// SANITIZE-WITH-ATTR-NEXT: [[TMP18:%.*]] = shl i32 [[DOTTR]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[TMP19:%.*]] = and i32 [[TMP18]], 252 +// SANITIZE-WITH-ATTR-NEXT: [[CONV23:%.*]] = select i1 [[TMP17]], i32 [[TMP19]], i32 0 // SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV23]], ptr [[ARRAYIDX33]], align 4, !tbaa [[TBAA4]] // SANITIZE-WITH-ATTR-NEXT: ret void // // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test4( // NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[FAM_IDX:%.*]]) local_unnamed_addr #[[ATTR1]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = shl i32 [[DOT_COUNTED_BY_LOAD]], 2 // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], 244 @@ -410,7 +407,7 @@ void test4(struct annotated *p, int index, int fam_idx) { // SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -17179869180, 17179869181) i64 @test4_bdos( // SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64 @@ -425,7 +422,7 @@ void test4(struct annotated *p, int index, int fam_idx) { // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -17179869180, 17179869181) i64 @test4_bdos( // NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64 @@ -455,12 +452,12 @@ size_t test4_bdos(struct annotated *p, int index) { // SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i64, ptr [[DOTCOUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ugt i64 [[DOTCOUNTED_BY_LOAD]], [[IDXPROM]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB8:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB8:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont3: // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16 @@ -526,13 +523,13 @@ size_t test5_bdos(struct anon_struct *p) { // SANITIZE-WITH-ATTR-LABEL: define dso_local void @test6( // SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i64, ptr [[DOT_COUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ugt i64 [[DOT_COUNTED_BY_LOAD]], [[IDXPROM]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont3: // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16 @@ -546,7 +543,7 @@ size_t test5_bdos(struct anon_struct *p) { // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test6( // NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i64, ptr [[DOT_COUNTED_BY_GEP]], align 4 // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.smax.i64(i64 [[DOT_COUNTED_BY_LOAD]], i64 0) // NO-SANITIZE-WITH-ATTR-NEXT: [[DOTTR:%.*]] = trunc i64 [[TMP0]] to i32 @@ -582,7 +579,7 @@ void test6(struct anon_struct *p, int index) { // SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, -3) i64 @test6_bdos( // SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i64, ptr [[DOT_COUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.smax.i64(i64 [[DOT_COUNTED_BY_LOAD]], i64 0) // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl i64 [[TMP0]], 2 @@ -591,7 +588,7 @@ void test6(struct anon_struct *p, int index) { // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, -3) i64 @test6_bdos( // NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i64, ptr [[DOT_COUNTED_BY_GEP]], align 4 // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.smax.i64(i64 [[DOT_COUNTED_BY_LOAD]], i64 0) // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl i64 [[TMP0]], 2 @@ -614,18 +611,18 @@ size_t test6_bdos(struct anon_struct *p) { // SANITIZE-WITH-ATTR-LABEL: define dso_local void @test7( // SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 // SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i8, ptr [[TMP0]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i8 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP1]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT7:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB11:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB11:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont7: // SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 9 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] // SANITIZE-WITH-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8:![0-9]+]] // SANITIZE-WITH-ATTR-NEXT: ret void // @@ -687,27 +684,27 @@ size_t test7_bdos(struct union_of_fams *p) { // SANITIZE-WITH-ATTR-LABEL: define dso_local void @test8( // SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i8, ptr [[DOT_COUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i8 [[DOT_COUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP0]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT7:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB12:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB12:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont7: -// SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 9 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] // SANITIZE-WITH-ATTR-NEXT: store i8 [[DOT_COUNTED_BY_LOAD]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8]] // SANITIZE-WITH-ATTR-NEXT: ret void // // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test8( // NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i8, ptr [[DOT_COUNTED_BY_GEP]], align 4 -// NO-SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 +// NO-SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 9 // NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 // NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] // NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[DOT_COUNTED_BY_LOAD]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] @@ -738,7 +735,7 @@ void test8(struct union_of_fams *p, int index) { // SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 256) i64 @test8_bdos( // SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i8, ptr [[DOT_COUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i8 [[DOT_COUNTED_BY_LOAD]] to i64 // SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP0]] @@ -746,7 +743,7 @@ void test8(struct union_of_fams *p, int index) { // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 256) i64 @test8_bdos( // NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i8, ptr [[DOT_COUNTED_BY_GEP]], align 4 // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i8 [[DOT_COUNTED_BY_LOAD]] to i64 // NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP0]] @@ -768,18 +765,18 @@ size_t test8_bdos(struct union_of_fams *p) { // SANITIZE-WITH-ATTR-LABEL: define dso_local void @test9( // SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 // SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[TMP0]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP1]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT7:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB14:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB14:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont7: // SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 12 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] // SANITIZE-WITH-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8]] // SANITIZE-WITH-ATTR-NEXT: ret void // @@ -841,18 +838,18 @@ size_t test9_bdos(struct union_of_fams *p) { // SANITIZE-WITH-ATTR-LABEL: define dso_local void @test10( // SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOT_COUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP0]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT7:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB15:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB15:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont7: -// SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 12 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] // SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[DOT_COUNTED_BY_LOAD]], i32 0) // SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = trunc i32 [[NARROW]] to i8 // SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8]] @@ -861,11 +858,11 @@ size_t test9_bdos(struct union_of_fams *p) { // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test10( // NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[DOT_COUNTED_BY_LOAD]], i32 0) // NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = trunc i32 [[NARROW]] to i8 -// NO-SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 +// NO-SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 12 // NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 // NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] // NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] @@ -896,7 +893,7 @@ void test10(struct union_of_fams *p, int index) { // SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 2147483648) i64 @test10_bdos( // SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[DOT_COUNTED_BY_LOAD]], i32 0) // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext nneg i32 [[NARROW]] to i64 @@ -905,7 +902,7 @@ void test10(struct union_of_fams *p, int index) { // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 2147483648) i64 @test10_bdos( // NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[DOT_COUNTED_BY_LOAD]], i32 0) // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext nneg i32 [[NARROW]] to i64 @@ -929,17 +926,17 @@ size_t test10_bdos(struct union_of_fams *p) { // SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP0]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB16:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB16:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont3: // SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 12 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] // SANITIZE-WITH-ATTR-NEXT: store i32 4, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] // SANITIZE-WITH-ATTR-NEXT: ret void // @@ -1017,26 +1014,26 @@ int test12_a, test12_b; // SANITIZE-WITH-ATTR-SAME: i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[BAZ:%.*]] = alloca [[STRUCT_HANG:%.*]], align 4 -// SANITIZE-WITH-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR10:[0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR9:[0-9]+]] // SANITIZE-WITH-ATTR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(24) [[BAZ]], ptr noundef nonnull align 4 dereferenceable(24) @test12_bar, i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT9:![0-9]+]] // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ult i32 [[INDEX]], 6 // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[INDEX]] to i64 // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB18:[0-9]+]], i64 [[TMP1]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB18:[0-9]+]], i64 [[TMP1]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont: -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[TMP1]] +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [6 x i32], ptr [[BAZ]], i64 0, i64 [[TMP1]] // SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] // SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP2]], ptr @test12_b, align 4, !tbaa [[TBAA4]] // SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr @test12_foo, align 4 // SANITIZE-WITH-ATTR-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[DOTCOUNTED_BY_LOAD]], 0 // SANITIZE-WITH-ATTR-NEXT: br i1 [[DOTNOT]], label [[HANDLER_OUT_OF_BOUNDS4:%.*]], label [[HANDLER_TYPE_MISMATCH6:%.*]], !prof [[PROF10:![0-9]+]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds4: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB20:[0-9]+]], i64 0) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB20:[0-9]+]], i64 0) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.type_mismatch6: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB21:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr @test12_foo, i64 4) to i64)) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB21:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr @test12_foo, i64 4) to i64)) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i32 @test12( @@ -1059,26 +1056,26 @@ int test12_a, test12_b; // SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] { // SANITIZE-WITHOUT-ATTR-NEXT: entry: // SANITIZE-WITHOUT-ATTR-NEXT: [[BAZ:%.*]] = alloca [[STRUCT_HANG:%.*]], align 4 -// SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR7:[0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR6:[0-9]+]] // SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(24) [[BAZ]], ptr noundef nonnull align 4 dereferenceable(24) @test12_bar, i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT7:![0-9]+]] // SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = icmp ult i32 [[INDEX]], 6 // SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[INDEX]] to i64 // SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF8:![0-9]+]], !nosanitize [[META9:![0-9]+]] // SANITIZE-WITHOUT-ATTR: handler.out_of_bounds: -// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP1]]) #[[ATTR8:[0-9]+]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP1]]) #[[ATTR7:[0-9]+]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR: cont: -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[TMP1]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [6 x i32], ptr [[BAZ]], i64 0, i64 [[TMP1]] // SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[TMP2]], ptr @test12_b, align 4, !tbaa [[TBAA2]] // SANITIZE-WITHOUT-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr @test12_foo, align 4 // SANITIZE-WITHOUT-ATTR-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[DOTCOUNTED_BY_LOAD]], 0 // SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[DOTNOT]], label [[HANDLER_OUT_OF_BOUNDS4:%.*]], label [[HANDLER_TYPE_MISMATCH6:%.*]], !prof [[PROF10:![0-9]+]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR: handler.out_of_bounds4: -// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 0) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 0) #[[ATTR7]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR: handler.type_mismatch6: -// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr @test12_foo, i64 4) to i64)) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr @test12_foo, i64 4) to i64)) #[[ATTR7]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] // // NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i32 @test12( @@ -1120,18 +1117,18 @@ struct test13_bar { // SANITIZE-WITH-ATTR-SAME: i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr @test13_f, align 8, !tbaa [[TBAA11:![0-9]+]] -// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ult i64 [[INDEX]], [[TMP1]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT5:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB24:[0-9]+]], i64 [[INDEX]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB24:[0-9]+]], i64 [[INDEX]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont5: // SANITIZE-WITH-ATTR-NEXT: [[REVMAP:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 16 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x ptr], ptr [[REVMAP]], i64 0, i64 [[INDEX]] -// SANITIZE-WITH-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA14:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [0 x ptr], ptr [[REVMAP]], i64 0, i64 [[INDEX]] +// SANITIZE-WITH-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA15:![0-9]+]] // SANITIZE-WITH-ATTR-NEXT: ret i32 0 // // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i32 @test13( @@ -1140,25 +1137,25 @@ struct test13_bar { // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr @test13_f, align 8, !tbaa [[TBAA8:![0-9]+]] // NO-SANITIZE-WITH-ATTR-NEXT: [[REVMAP:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 16 // NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x ptr], ptr [[REVMAP]], i64 0, i64 [[INDEX]] -// NO-SANITIZE-WITH-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA11:![0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA12:![0-9]+]] // NO-SANITIZE-WITH-ATTR-NEXT: ret i32 0 // // SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i32 @test13( // SANITIZE-WITHOUT-ATTR-SAME: i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITHOUT-ATTR-NEXT: entry: // SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr @test13_f, align 8, !tbaa [[TBAA11:![0-9]+]] -// SANITIZE-WITHOUT-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8 +// SANITIZE-WITHOUT-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 8 // SANITIZE-WITHOUT-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4 // SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = icmp ult i64 [[INDEX]], [[TMP1]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[TMP2]], label [[CONT5:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF8]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR: handler.out_of_bounds: -// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB8:[0-9]+]], i64 [[INDEX]]) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB8:[0-9]+]], i64 [[INDEX]]) #[[ATTR7]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR: cont5: // SANITIZE-WITHOUT-ATTR-NEXT: [[REVMAP:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 16 -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x ptr], ptr [[REVMAP]], i64 0, i64 [[INDEX]] -// SANITIZE-WITHOUT-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA14:![0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [0 x ptr], ptr [[REVMAP]], i64 0, i64 [[INDEX]] +// SANITIZE-WITHOUT-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA15:![0-9]+]] // SANITIZE-WITHOUT-ATTR-NEXT: ret i32 0 // // NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i32 @test13( @@ -1167,7 +1164,7 @@ struct test13_bar { // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr @test13_f, align 8, !tbaa [[TBAA8:![0-9]+]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[REVMAP:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 16 // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x ptr], ptr [[REVMAP]], i64 0, i64 [[INDEX]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA11:![0-9]+]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA12:![0-9]+]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 0 // int test13(long index) { @@ -1184,14 +1181,13 @@ struct test14_foo { // SANITIZE-WITH-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp eq i32 [[IDX]], 0 -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[TRAP:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB25:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB25:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] -// SANITIZE-WITH-ATTR: trap: -// SANITIZE-WITH-ATTR-NEXT: tail call void @llvm.trap() #[[ATTR9]] -// SANITIZE-WITH-ATTR-NEXT: unreachable +// SANITIZE-WITH-ATTR: cont3: +// SANITIZE-WITH-ATTR-NEXT: ret i32 undef // // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test14( // NO-SANITIZE-WITH-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR3]] { @@ -1210,14 +1206,13 @@ struct test14_foo { // SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITHOUT-ATTR-NEXT: entry: // SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = icmp eq i32 [[IDX]], 0 -// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[TMP0]], label [[TRAP:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[TMP0]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF8]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR: handler.out_of_bounds: // SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 -// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR7]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] -// SANITIZE-WITHOUT-ATTR: trap: -// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @llvm.trap() #[[ATTR8]] -// SANITIZE-WITHOUT-ATTR-NEXT: unreachable +// SANITIZE-WITHOUT-ATTR: cont3: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i32 undef // // NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test14( // NO-SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR1]] { @@ -1240,14 +1235,13 @@ int test14(int idx) { // SANITIZE-WITH-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp eq i32 [[IDX]], 0 -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[TRAP:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[CONT1:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB27:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB27:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] -// SANITIZE-WITH-ATTR: trap: -// SANITIZE-WITH-ATTR-NEXT: tail call void @llvm.trap() #[[ATTR9]] -// SANITIZE-WITH-ATTR-NEXT: unreachable +// SANITIZE-WITH-ATTR: cont1: +// SANITIZE-WITH-ATTR-NEXT: ret i32 undef // // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test15( // NO-SANITIZE-WITH-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR3]] { @@ -1261,14 +1255,13 @@ int test14(int idx) { // SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITHOUT-ATTR-NEXT: entry: // SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = icmp eq i32 [[IDX]], 0 -// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[TMP0]], label [[TRAP:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[TMP0]], label [[CONT1:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF8]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR: handler.out_of_bounds: // SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 -// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB11:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB11:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR7]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] -// SANITIZE-WITHOUT-ATTR: trap: -// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @llvm.trap() #[[ATTR8]] -// SANITIZE-WITHOUT-ATTR-NEXT: unreachable +// SANITIZE-WITHOUT-ATTR: cont1: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i32 undef // // NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test15( // NO-SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR1]] { @@ -1420,36 +1413,36 @@ struct tests_foo { // SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test24( // SANITIZE-WITH-ATTR-SAME: i32 noundef [[C:%.*]], ptr noundef [[VAR:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[VAR]], i64 40 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[VAR]], i64 40 // SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ugt i32 [[DOTCOUNTED_BY_LOAD]], 10 // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[CONT4:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB28:[0-9]+]], i64 10) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB28:[0-9]+]], i64 10) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont4: -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i8, ptr [[VAR]], i64 84 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i8, ptr [[VAR]], i64 84 // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX2]], align 4, !tbaa [[TBAA4]] // SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP1]] // // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test24( // NO-SANITIZE-WITH-ATTR-SAME: i32 noundef [[C:%.*]], ptr nocapture noundef readonly [[VAR:%.*]]) local_unnamed_addr #[[ATTR2]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[VAR]], i64 84 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i8, ptr [[VAR]], i64 84 // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX1]], align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP0]] // // SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test24( // SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[C:%.*]], ptr noundef [[VAR:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[VAR]], i64 84 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i8, ptr [[VAR]], i64 84 // SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX1]], align 4, !tbaa [[TBAA2]] // SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP0]] // // NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test24( // NO-SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[C:%.*]], ptr nocapture noundef readonly [[VAR:%.*]]) local_unnamed_addr #[[ATTR6:[0-9]+]] { // NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[VAR]], i64 84 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i8, ptr [[VAR]], i64 84 // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX1]], align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP0]] // @@ -1461,39 +1454,39 @@ int test24(int c, struct tests_foo *var) { // SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test25( // SANITIZE-WITH-ATTR-SAME: i32 noundef [[C:%.*]], ptr noundef [[VAR:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !tbaa [[TBAA17:![0-9]+]] // SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[TMP0]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[DOTCOUNTED_BY_LOAD]], 10 // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT5:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB29:[0-9]+]], i64 10) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB29:[0-9]+]], i64 10) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont5: -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 44 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 44 // SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] // SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP2]] // // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test25( // NO-SANITIZE-WITH-ATTR-SAME: i32 noundef [[C:%.*]], ptr nocapture noundef readonly [[VAR:%.*]]) local_unnamed_addr #[[ATTR8:[0-9]+]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !tbaa [[TBAA11]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 44 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !tbaa [[TBAA14:![0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 44 // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP1]] // // SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test25( // SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[C:%.*]], ptr noundef [[VAR:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !tbaa [[TBAA14]] -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 44 +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !tbaa [[TBAA17:![0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 44 // SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP1]] // // NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test25( // NO-SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[C:%.*]], ptr nocapture noundef readonly [[VAR:%.*]]) local_unnamed_addr #[[ATTR7:[0-9]+]] { // NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !tbaa [[TBAA11]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 44 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !tbaa [[TBAA14:![0-9]+]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 44 // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP1]] // @@ -1511,18 +1504,18 @@ struct test26_foo { // SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test26( // SANITIZE-WITH-ATTR-SAME: i32 noundef [[C:%.*]], ptr noundef [[FOO:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[S:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 4 +// SANITIZE-WITH-ATTR-NEXT: [[S:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 4 // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[C]] to i64 // SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[S]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP0]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT5:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB30:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB30:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont5: // SANITIZE-WITH-ATTR-NEXT: [[ARR:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 8 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARR]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [0 x i32], ptr [[ARR]], i64 0, i64 [[IDXPROM]] // SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] // SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP2]] // @@ -1583,18 +1576,18 @@ struct test27_foo { // SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[I:%.*]], i32 noundef [[J:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 -// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 12 // SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP0]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB32:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB32:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont3: // SANITIZE-WITH-ATTR-NEXT: [[ENTRIES:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 24 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x ptr], ptr [[ENTRIES]], i64 0, i64 [[IDXPROM]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [0 x ptr], ptr [[ENTRIES]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA19:![0-9]+]] // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM4:%.*]] = sext i32 [[J]] to i64 // SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [[STRUCT_TEST27_BAR:%.*]], ptr [[TMP2]], i64 [[IDXPROM4]] // SANITIZE-WITH-ATTR-NEXT: ret ptr [[ARRAYIDX5]] @@ -1605,7 +1598,7 @@ struct test27_foo { // NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRIES:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 24 // NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 // NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x ptr], ptr [[ENTRIES]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA16:![0-9]+]] // NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM1:%.*]] = sext i32 [[J]] to i64 // NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds [[STRUCT_TEST27_BAR:%.*]], ptr [[TMP0]], i64 [[IDXPROM1]] // NO-SANITIZE-WITH-ATTR-NEXT: ret ptr [[ARRAYIDX2]] @@ -1616,7 +1609,7 @@ struct test27_foo { // SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRIES:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 24 // SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 // SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x ptr], ptr [[ENTRIES]], i64 0, i64 [[IDXPROM]] -// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA19:![0-9]+]] // SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM3:%.*]] = sext i32 [[J]] to i64 // SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds [[STRUCT_TEST27_BAR:%.*]], ptr [[TMP0]], i64 [[IDXPROM3]] // SANITIZE-WITHOUT-ATTR-NEXT: ret ptr [[ARRAYIDX4]] @@ -1627,7 +1620,7 @@ struct test27_foo { // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRIES:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 24 // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x ptr], ptr [[ENTRIES]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA16:![0-9]+]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM1:%.*]] = sext i32 [[J]] to i64 // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds [[STRUCT_TEST27_BAR:%.*]], ptr [[TMP0]], i64 [[IDXPROM1]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: ret ptr [[ARRAYIDX2]] @@ -1645,30 +1638,30 @@ struct test28_foo { // SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test28( // SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[I:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA14]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA14]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA21:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA21]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8, !tbaa [[TBAA21]] // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 -// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP2]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label [[CONT17:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB34:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB34:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont17: // SANITIZE-WITH-ATTR-NEXT: [[ARR:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP2]], i64 12 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARR]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [0 x i32], ptr [[ARR]], i64 0, i64 [[IDXPROM]] // SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] // SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP5]] // // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test28( // NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]], i32 noundef [[I:%.*]]) local_unnamed_addr #[[ATTR8]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA11]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA11]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA18:![0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA18]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8, !tbaa [[TBAA18]] // NO-SANITIZE-WITH-ATTR-NEXT: [[ARR:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP2]], i64 12 // NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 // NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARR]], i64 0, i64 [[IDXPROM]] @@ -1678,9 +1671,9 @@ struct test28_foo { // SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test28( // SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[I:%.*]]) local_unnamed_addr #[[ATTR0]] { // SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA14]] -// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA14]] -// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA21:![0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA21]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8, !tbaa [[TBAA21]] // SANITIZE-WITHOUT-ATTR-NEXT: [[ARR:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP2]], i64 12 // SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 // SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARR]], i64 0, i64 [[IDXPROM]] @@ -1690,9 +1683,9 @@ struct test28_foo { // NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test28( // NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]], i32 noundef [[I:%.*]]) local_unnamed_addr #[[ATTR7]] { // NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA11]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA11]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA18:![0-9]+]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA18]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8, !tbaa [[TBAA18]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARR:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP2]], i64 12 // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARR]], i64 0, i64 [[IDXPROM]] @@ -1717,23 +1710,23 @@ struct annotated_struct_array { // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[IDX1]] to i64 // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB36:[0-9]+]], i64 [[TMP1]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB36:[0-9]+]], i64 [[TMP1]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont3: -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x ptr], ptr [[ANN]], i64 0, i64 [[TMP1]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA14]] -// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [10 x ptr], ptr [[ANN]], i64 0, i64 [[TMP1]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA23:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP2]], i64 8 // SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // SANITIZE-WITH-ATTR-NEXT: [[IDXPROM15:%.*]] = sext i32 [[IDX2]] to i64 // SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[DOT_COUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[IDXPROM15]], [[TMP3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label [[CONT20:%.*]], label [[HANDLER_OUT_OF_BOUNDS16:%.*]], !prof [[PROF3]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.out_of_bounds16: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB37:[0-9]+]], i64 [[IDXPROM15]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB37:[0-9]+]], i64 [[IDXPROM15]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: cont20: // SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP2]], i64 12 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX18:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM15]] +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX18:%.*]] = getelementptr inbounds nuw [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM15]] // SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = tail call i32 @llvm.smax.i32(i32 [[DOT_COUNTED_BY_LOAD]], i32 0) // SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = shl i32 [[TMP5]], 2 // SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX18]], align 4, !tbaa [[TBAA4]] @@ -1744,8 +1737,8 @@ struct annotated_struct_array { // NO-SANITIZE-WITH-ATTR-NEXT: entry: // NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX1]] to i64 // NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x ptr], ptr [[ANN]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA11]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA20:![0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 8 // NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.smax.i32(i32 [[DOT_COUNTED_BY_LOAD]], i32 0) // NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = shl i32 [[TMP1]], 2 @@ -1762,11 +1755,11 @@ struct annotated_struct_array { // SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[IDX1]] to i64 // SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[TMP0]], label [[CONT21:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF8]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR: handler.out_of_bounds: -// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB13:[0-9]+]], i64 [[TMP1]]) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB13:[0-9]+]], i64 [[TMP1]]) #[[ATTR7]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR: cont21: -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x ptr], ptr [[ANN]], i64 0, i64 [[TMP1]] -// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [10 x ptr], ptr [[ANN]], i64 0, i64 [[TMP1]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA23:![0-9]+]] // SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP2]], i64 12 // SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM18:%.*]] = sext i32 [[IDX2]] to i64 // SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX19:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM18]] @@ -1778,7 +1771,7 @@ struct annotated_struct_array { // NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX1]] to i64 // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x ptr], ptr [[ANN]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA20:![0-9]+]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 12 // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM5:%.*]] = sext i32 [[IDX2]] to i64 // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX6:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM5]] @@ -1804,7 +1797,7 @@ struct test30_struct { // SANITIZE-WITH-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR4]] { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[IDX]] to i64, !nosanitize [[META2]] -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB39:[0-9]+]], i64 [[TMP0]]) #[[ATTR9]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB39:[0-9]+]], i64 [[TMP0]]) #[[ATTR8]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test30( @@ -1820,7 +1813,7 @@ struct test30_struct { // SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR3]] { // SANITIZE-WITHOUT-ATTR-NEXT: entry: // SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[IDX]] to i64, !nosanitize [[META9]] -// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB15:[0-9]+]], i64 [[TMP0]]) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB15:[0-9]+]], i64 [[TMP0]]) #[[ATTR7]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] // // NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test30( diff --git a/clang/test/CodeGen/builtins-elementwise-math.c b/clang/test/CodeGen/builtins-elementwise-math.c index 82f82dd1ed794..7f6b5f26eb930 100644 --- a/clang/test/CodeGen/builtins-elementwise-math.c +++ b/clang/test/CodeGen/builtins-elementwise-math.c @@ -112,7 +112,7 @@ void test_builtin_elementwise_add_sat(float f1, float f2, double d1, double d2, // CHECK-NEXT: call i32 @llvm.sadd.sat.i32(i32 [[IAS1]], i32 [[B]]) int_as_one = __builtin_elementwise_add_sat(int_as_one, b); - // CHECK: call i32 @llvm.sadd.sat.i32(i32 1, i32 97) + // CHECK: store i64 98, ptr %i1.addr, align 8 i1 = __builtin_elementwise_add_sat(1, 'a'); } @@ -165,7 +165,7 @@ void test_builtin_elementwise_sub_sat(float f1, float f2, double d1, double d2, // CHECK-NEXT: call i32 @llvm.ssub.sat.i32(i32 [[IAS1]], i32 [[B]]) int_as_one = __builtin_elementwise_sub_sat(int_as_one, b); - // CHECK: call i32 @llvm.ssub.sat.i32(i32 1, i32 97) + // CHECK: store i64 -96, ptr %i1.addr, align 8 i1 = __builtin_elementwise_sub_sat(1, 'a'); } diff --git a/clang/test/CodeGen/cx-complex-range.c b/clang/test/CodeGen/cx-complex-range.c index b2259031d7563..88300041061aa 100644 --- a/clang/test/CodeGen/cx-complex-range.c +++ b/clang/test/CodeGen/cx-complex-range.c @@ -485,14 +485,14 @@ // PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 // PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1 // PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 -// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext float [[A_REAL]] to double -// PRMTD_FAST-NEXT: [[EXT1:%.*]] = fpext float [[A_IMAG]] to double +// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[A_REAL]] to double +// PRMTD_FAST-NEXT: [[EXT1:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[A_IMAG]] to double // PRMTD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[B]], i32 0, i32 0 // PRMTD_FAST-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 // PRMTD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[B]], i32 0, i32 1 // PRMTD_FAST-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 -// PRMTD_FAST-NEXT: [[EXT2:%.*]] = fpext float [[B_REAL]] to double -// PRMTD_FAST-NEXT: [[EXT3:%.*]] = fpext float [[B_IMAG]] to double +// PRMTD_FAST-NEXT: [[EXT2:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[B_REAL]] to double +// PRMTD_FAST-NEXT: [[EXT3:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[B_IMAG]] to double // PRMTD_FAST-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT]], [[EXT2]] // PRMTD_FAST-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT1]], [[EXT3]] // PRMTD_FAST-NEXT: [[TMP2:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[TMP0]], [[TMP1]] @@ -504,8 +504,8 @@ // PRMTD_FAST-NEXT: [[TMP8:%.*]] = fsub reassoc nnan ninf nsz arcp afn double [[TMP6]], [[TMP7]] // PRMTD_FAST-NEXT: [[TMP9:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[TMP2]], [[TMP5]] // PRMTD_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[TMP8]], [[TMP5]] -// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc double [[TMP9]] to float -// PRMTD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc double [[TMP10]] to float +// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn double [[TMP9]] to float +// PRMTD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn double [[TMP10]] to float // PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 0 // PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 1 // PRMTD_FAST-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 4 @@ -1530,14 +1530,14 @@ _Complex float mulf(_Complex float a, _Complex float b) { // PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 // PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 1 // PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 -// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext double [[A_REAL]] to x86_fp80 -// PRMTD_FAST-NEXT: [[EXT1:%.*]] = fpext double [[A_IMAG]] to x86_fp80 +// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn double [[A_REAL]] to x86_fp80 +// PRMTD_FAST-NEXT: [[EXT1:%.*]] = fpext reassoc nnan ninf nsz arcp afn double [[A_IMAG]] to x86_fp80 // PRMTD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 // PRMTD_FAST-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 // PRMTD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 1 // PRMTD_FAST-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 -// PRMTD_FAST-NEXT: [[EXT2:%.*]] = fpext double [[B_REAL]] to x86_fp80 -// PRMTD_FAST-NEXT: [[EXT3:%.*]] = fpext double [[B_IMAG]] to x86_fp80 +// PRMTD_FAST-NEXT: [[EXT2:%.*]] = fpext reassoc nnan ninf nsz arcp afn double [[B_REAL]] to x86_fp80 +// PRMTD_FAST-NEXT: [[EXT3:%.*]] = fpext reassoc nnan ninf nsz arcp afn double [[B_IMAG]] to x86_fp80 // PRMTD_FAST-NEXT: [[TMP4:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[EXT]], [[EXT2]] // PRMTD_FAST-NEXT: [[TMP5:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[EXT1]], [[EXT3]] // PRMTD_FAST-NEXT: [[TMP6:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP4]], [[TMP5]] @@ -1549,8 +1549,8 @@ _Complex float mulf(_Complex float a, _Complex float b) { // PRMTD_FAST-NEXT: [[TMP12:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP10]], [[TMP11]] // PRMTD_FAST-NEXT: [[TMP13:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP6]], [[TMP9]] // PRMTD_FAST-NEXT: [[TMP14:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP12]], [[TMP9]] -// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc x86_fp80 [[TMP13]] to double -// PRMTD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc x86_fp80 [[TMP14]] to double +// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP13]] to double +// PRMTD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP14]] to double // PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 0 // PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 1 // PRMTD_FAST-NEXT: store double [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 8 @@ -3697,8 +3697,8 @@ _Complex long double mulld(_Complex long double a, _Complex long double b) { // BASIC_FAST-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4 // BASIC_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[C]], i32 0, i32 1 // BASIC_FAST-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4 -// BASIC_FAST-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to x86_fp80 -// BASIC_FAST-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to x86_fp80 +// BASIC_FAST-NEXT: [[CONV:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[C_REAL]] to x86_fp80 +// BASIC_FAST-NEXT: [[CONV1:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[C_IMAG]] to x86_fp80 // BASIC_FAST-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[CONV]] // BASIC_FAST-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[CONV1]] // BASIC_FAST-NEXT: [[TMP2:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP0]], [[TMP1]] @@ -3710,8 +3710,8 @@ _Complex long double mulld(_Complex long double a, _Complex long double b) { // BASIC_FAST-NEXT: [[TMP8:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP6]], [[TMP7]] // BASIC_FAST-NEXT: [[TMP9:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP2]], [[TMP5]] // BASIC_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP8]], [[TMP5]] -// BASIC_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP9]] to float -// BASIC_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP10]] to float +// BASIC_FAST-NEXT: [[CONV2:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP9]] to float +// BASIC_FAST-NEXT: [[CONV3:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP10]] to float // BASIC_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 0 // BASIC_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 // BASIC_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1 @@ -3751,13 +3751,13 @@ _Complex long double mulld(_Complex long double a, _Complex long double b) { // FULL_FAST-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4 // FULL_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[C]], i32 0, i32 1 // FULL_FAST-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4 -// FULL_FAST-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to x86_fp80 -// FULL_FAST-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to x86_fp80 +// FULL_FAST-NEXT: [[CONV:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[C_REAL]] to x86_fp80 +// FULL_FAST-NEXT: [[CONV1:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[C_IMAG]] to x86_fp80 // FULL_FAST-NEXT: [[CALL:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) { x86_fp80, x86_fp80 } @__divxc3(x86_fp80 noundef nofpclass(nan inf) [[B_REAL]], x86_fp80 noundef nofpclass(nan inf) [[B_IMAG]], x86_fp80 noundef nofpclass(nan inf) [[CONV]], x86_fp80 noundef nofpclass(nan inf) [[CONV1]]) #[[ATTR2]] // FULL_FAST-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0 // FULL_FAST-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1 -// FULL_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP0]] to float -// FULL_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP1]] to float +// FULL_FAST-NEXT: [[CONV2:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP0]] to float +// FULL_FAST-NEXT: [[CONV3:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP1]] to float // FULL_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 0 // FULL_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 // FULL_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1 @@ -3791,8 +3791,8 @@ _Complex long double mulld(_Complex long double a, _Complex long double b) { // IMPRVD_FAST-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4 // IMPRVD_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[C]], i32 0, i32 1 // IMPRVD_FAST-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4 -// IMPRVD_FAST-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to x86_fp80 -// IMPRVD_FAST-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to x86_fp80 +// IMPRVD_FAST-NEXT: [[CONV:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[C_REAL]] to x86_fp80 +// IMPRVD_FAST-NEXT: [[CONV1:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[C_IMAG]] to x86_fp80 // IMPRVD_FAST-NEXT: [[TMP0:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV]]) // IMPRVD_FAST-NEXT: [[TMP1:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV1]]) // IMPRVD_FAST-NEXT: [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt x86_fp80 [[TMP0]], [[TMP1]] @@ -3822,8 +3822,8 @@ _Complex long double mulld(_Complex long double a, _Complex long double b) { // IMPRVD_FAST: complex_div: // IMPRVD_FAST-NEXT: [[TMP20:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] // IMPRVD_FAST-NEXT: [[TMP21:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] -// IMPRVD_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP20]] to float -// IMPRVD_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP21]] to float +// IMPRVD_FAST-NEXT: [[CONV2:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP20]] to float +// IMPRVD_FAST-NEXT: [[CONV3:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP21]] to float // IMPRVD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 0 // IMPRVD_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 // IMPRVD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1 @@ -3880,8 +3880,8 @@ _Complex long double mulld(_Complex long double a, _Complex long double b) { // PRMTD_FAST-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4 // PRMTD_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[C]], i32 0, i32 1 // PRMTD_FAST-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4 -// PRMTD_FAST-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to x86_fp80 -// PRMTD_FAST-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to x86_fp80 +// PRMTD_FAST-NEXT: [[CONV:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[C_REAL]] to x86_fp80 +// PRMTD_FAST-NEXT: [[CONV1:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[C_IMAG]] to x86_fp80 // PRMTD_FAST-NEXT: [[TMP0:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV]]) // PRMTD_FAST-NEXT: [[TMP1:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV1]]) // PRMTD_FAST-NEXT: [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt x86_fp80 [[TMP0]], [[TMP1]] @@ -3911,16 +3911,16 @@ _Complex long double mulld(_Complex long double a, _Complex long double b) { // PRMTD_FAST: complex_div: // PRMTD_FAST-NEXT: [[TMP20:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] // PRMTD_FAST-NEXT: [[TMP21:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] -// PRMTD_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP20]] to float -// PRMTD_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP21]] to float -// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext float [[CONV2]] to double -// PRMTD_FAST-NEXT: [[EXT4:%.*]] = fpext float [[CONV3]] to double +// PRMTD_FAST-NEXT: [[CONV2:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP20]] to float +// PRMTD_FAST-NEXT: [[CONV3:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP21]] to float +// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[CONV2]] to double +// PRMTD_FAST-NEXT: [[EXT4:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[CONV3]] to double // PRMTD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 0 // PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 // PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1 // PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 -// PRMTD_FAST-NEXT: [[EXT5:%.*]] = fpext float [[A_REAL]] to double -// PRMTD_FAST-NEXT: [[EXT6:%.*]] = fpext float [[A_IMAG]] to double +// PRMTD_FAST-NEXT: [[EXT5:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[A_REAL]] to double +// PRMTD_FAST-NEXT: [[EXT6:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[A_IMAG]] to double // PRMTD_FAST-NEXT: [[TMP22:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT]], [[EXT5]] // PRMTD_FAST-NEXT: [[TMP23:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT4]], [[EXT6]] // PRMTD_FAST-NEXT: [[TMP24:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[TMP22]], [[TMP23]] @@ -3932,8 +3932,8 @@ _Complex long double mulld(_Complex long double a, _Complex long double b) { // PRMTD_FAST-NEXT: [[TMP30:%.*]] = fsub reassoc nnan ninf nsz arcp afn double [[TMP28]], [[TMP29]] // PRMTD_FAST-NEXT: [[TMP31:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[TMP24]], [[TMP27]] // PRMTD_FAST-NEXT: [[TMP32:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[TMP30]], [[TMP27]] -// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc double [[TMP31]] to float -// PRMTD_FAST-NEXT: [[UNPROMOTION7:%.*]] = fptrunc double [[TMP32]] to float +// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn double [[TMP31]] to float +// PRMTD_FAST-NEXT: [[UNPROMOTION7:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn double [[TMP32]] to float // PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 0 // PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 1 // PRMTD_FAST-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 4 diff --git a/clang/test/CodeGen/ignore-overflow-pattern.c b/clang/test/CodeGen/ignore-overflow-pattern.c index c4a9d07b07aaa..4e5ed82d7967e 100644 --- a/clang/test/CodeGen/ignore-overflow-pattern.c +++ b/clang/test/CodeGen/ignore-overflow-pattern.c @@ -21,7 +21,10 @@ // unsigned negation, for example: // unsigned long A = -1UL; +// Skip over parts of the IR containing this file's name. +// CHECK: source_filename = {{.*}} +// Ensure we don't see anything about handling overflow before the tests below. // CHECK-NOT: handle{{.*}}overflow extern unsigned a, b, c; diff --git a/clang/test/CodeGen/math-libcalls-tbaa.c b/clang/test/CodeGen/math-libcalls-tbaa.c index 9c86eea67d14d..17a93ed2aed2d 100644 --- a/clang/test/CodeGen/math-libcalls-tbaa.c +++ b/clang/test/CodeGen/math-libcalls-tbaa.c @@ -16,7 +16,7 @@ float crealf(float _Complex); // CHECK-LABEL: define dso_local float @test_expf( // CHECK-SAME: ptr nocapture noundef readonly [[NUM:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[NUM]], i64 40 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[NUM]], i64 40 // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2:![0-9]+]] // CHECK-NEXT: [[CALL:%.*]] = tail call float @expf(float noundef [[TMP0]]) #[[ATTR9:[0-9]+]], !tbaa [[TBAA6:![0-9]+]] // CHECK-NEXT: [[MUL:%.*]] = fmul float [[TMP0]], [[CALL]] @@ -31,7 +31,7 @@ float test_expf (float num[]) { // CHECK-LABEL: define dso_local float @test_builtin_expf( // CHECK-SAME: ptr nocapture noundef readonly [[NUM:%.*]]) local_unnamed_addr #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[NUM]], i64 40 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[NUM]], i64 40 // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // CHECK-NEXT: [[CALL:%.*]] = tail call float @expf(float noundef [[TMP0]]) #[[ATTR9]], !tbaa [[TBAA6]] // CHECK-NEXT: [[MUL:%.*]] = fmul float [[TMP0]], [[CALL]] @@ -48,7 +48,7 @@ float test_builtin_expf (float num[]) { // CHECK-LABEL: define dso_local double @test_fabs( // CHECK-SAME: ptr nocapture noundef readonly [[NUM:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[NUM]], i64 80 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[NUM]], i64 80 // CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA8:![0-9]+]] // CHECK-NEXT: [[TMP1:%.*]] = tail call double @llvm.fabs.f64(double [[TMP0]]) // CHECK-NEXT: [[MUL:%.*]] = fmul double [[TMP0]], [[TMP1]] @@ -63,7 +63,7 @@ double test_fabs (double num[]) { // CHECK-LABEL: define dso_local double @test_remainder( // CHECK-SAME: ptr nocapture noundef readonly [[NUM:%.*]], double noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[NUM]], i64 80 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[NUM]], i64 80 // CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA8]] // CHECK-NEXT: [[CALL:%.*]] = tail call double @remainder(double noundef [[TMP0]], double noundef [[A]]) #[[ATTR9]], !tbaa [[TBAA6]] // CHECK-NEXT: [[MUL:%.*]] = fmul double [[TMP0]], [[CALL]] @@ -83,7 +83,7 @@ double test_remainder (double num[], double a) { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[E:%.*]] = alloca i32, align 4 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[E]]) #[[ATTR9]] -// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[NUM]], i64 16 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[NUM]], i64 16 // CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA8]] // CHECK-NEXT: [[CALL:%.*]] = call double @frexp(double noundef [[TMP0]], ptr noundef nonnull [[E]]) #[[ATTR9]] // CHECK-NEXT: [[MUL:%.*]] = fmul double [[TMP0]], [[CALL]] @@ -107,7 +107,7 @@ double test_frexp (double num[]) { // CHECK-NEXT: [[COS:%.*]] = alloca float, align 4 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[SIN]]) #[[ATTR9]] // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[COS]]) #[[ATTR9]] -// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[NUM]], i64 8 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[NUM]], i64 8 // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // CHECK-NEXT: call void @sincos(float noundef [[TMP0]], ptr noundef nonnull [[SIN]], ptr noundef nonnull [[COS]]) #[[ATTR9]] // CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[SIN]], align 4, !tbaa [[TBAA2]] @@ -130,7 +130,7 @@ float test_sincos (float num[]) { // CHECK-LABEL: define dso_local float @test_cacoshf( // CHECK-SAME: ptr nocapture noundef readonly [[NUM:%.*]]) local_unnamed_addr #[[ATTR7]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[NUM]], i64 8 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[NUM]], i64 8 // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // CHECK-NEXT: [[DOTFCA_0_INSERT:%.*]] = insertvalue [2 x float] poison, float [[TMP0]], 0 // CHECK-NEXT: [[DOTFCA_1_INSERT:%.*]] = insertvalue [2 x float] [[DOTFCA_0_INSERT]], float 0.000000e+00, 1 diff --git a/clang/test/CodeGen/matrix-type-operators-fast-math.c b/clang/test/CodeGen/matrix-type-operators-fast-math.c index 724b282830286..a5cb2ffdabcc5 100644 --- a/clang/test/CodeGen/matrix-type-operators-fast-math.c +++ b/clang/test/CodeGen/matrix-type-operators-fast-math.c @@ -41,7 +41,7 @@ void add_matrix_scalar_double_float(dx5x5_t a, float vf) { // CHECK-LABEL: define{{.*}} void @add_matrix_scalar_double_float(<25 x double> noundef nofpclass(nan inf) %a, float noundef nofpclass(nan inf) %vf) // CHECK: [[MATRIX:%.*]] = load <25 x double>, ptr {{.*}}, align 8 // CHECK-NEXT: [[SCALAR:%.*]] = load float, ptr %vf.addr, align 4 - // CHECK-NEXT: [[SCALAR_EXT:%.*]] = fpext float [[SCALAR]] to double + // CHECK-NEXT: [[SCALAR_EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[SCALAR]] to double // CHECK-NEXT: [[SCALAR_EMBED:%.*]] = insertelement <25 x double> poison, double [[SCALAR_EXT]], i64 0 // CHECK-NEXT: [[SCALAR_EMBED1:%.*]] = shufflevector <25 x double> [[SCALAR_EMBED]], <25 x double> poison, <25 x i32> zeroinitializer // CHECK-NEXT: [[RES:%.*]] = fadd reassoc nnan ninf nsz arcp afn <25 x double> [[MATRIX]], [[SCALAR_EMBED1]] @@ -53,7 +53,7 @@ void add_matrix_scalar_double_float(dx5x5_t a, float vf) { void add_compound_matrix_scalar_double_float(dx5x5_t a, float vf) { // CHECK-LABEL: define{{.*}} void @add_compound_matrix_scalar_double_float(<25 x double> noundef nofpclass(nan inf) %a, float noundef nofpclass(nan inf) %vf) // CHECK: [[SCALAR:%.*]] = load float, ptr %vf.addr, align 4 - // CHECK-NEXT: [[SCALAR_EXT:%.*]] = fpext float [[SCALAR]] to double + // CHECK-NEXT: [[SCALAR_EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[SCALAR]] to double // CHECK-NEXT: [[MATRIX:%.*]] = load <25 x double>, ptr {{.*}}, align 8 // CHECK-NEXT: [[SCALAR_EMBED:%.*]] = insertelement <25 x double> poison, double [[SCALAR_EXT]], i64 0 // CHECK-NEXT: [[SCALAR_EMBED1:%.*]] = shufflevector <25 x double> [[SCALAR_EMBED]], <25 x double> poison, <25 x i32> zeroinitializer @@ -66,7 +66,7 @@ void add_compound_matrix_scalar_double_float(dx5x5_t a, float vf) { void subtract_compound_matrix_scalar_double_float(dx5x5_t a, float vf) { // CHECK-LABEL: define{{.*}} void @subtract_compound_matrix_scalar_double_float(<25 x double> noundef nofpclass(nan inf) %a, float noundef nofpclass(nan inf) %vf) // CHECK: [[SCALAR:%.*]] = load float, ptr %vf.addr, align 4 - // CHECK-NEXT: [[SCALAR_EXT:%.*]] = fpext float [[SCALAR]] to double + // CHECK-NEXT: [[SCALAR_EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[SCALAR]] to double // CHECK-NEXT: [[MATRIX:%.*]] = load <25 x double>, ptr {{.*}}, align 8 // CHECK-NEXT: [[SCALAR_EMBED:%.*]] = insertelement <25 x double> poison, double [[SCALAR_EXT]], i64 0 // CHECK-NEXT: [[SCALAR_EMBED1:%.*]] = shufflevector <25 x double> [[SCALAR_EMBED]], <25 x double> poison, <25 x i32> zeroinitializer @@ -104,7 +104,7 @@ void multiply_compound_matrix_matrix_double(dx5x5_t b, dx5x5_t c) { // CHECK-LABEL: @multiply_double_matrix_scalar_float( // CHECK: [[A:%.*]] = load <25 x double>, ptr {{.*}}, align 8 // CHECK-NEXT: [[S:%.*]] = load float, ptr %s.addr, align 4 -// CHECK-NEXT: [[S_EXT:%.*]] = fpext float [[S]] to double +// CHECK-NEXT: [[S_EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[S]] to double // CHECK-NEXT: [[VECINSERT:%.*]] = insertelement <25 x double> poison, double [[S_EXT]], i64 0 // CHECK-NEXT: [[VECSPLAT:%.*]] = shufflevector <25 x double> [[VECINSERT]], <25 x double> poison, <25 x i32> zeroinitializer // CHECK-NEXT: [[RES:%.*]] = fmul reassoc nnan ninf nsz arcp afn <25 x double> [[A]], [[VECSPLAT]] @@ -117,7 +117,7 @@ void multiply_double_matrix_scalar_float(dx5x5_t a, float s) { // CHECK-LABEL: @multiply_compound_double_matrix_scalar_float // CHECK: [[S:%.*]] = load float, ptr %s.addr, align 4 -// CHECK-NEXT: [[S_EXT:%.*]] = fpext float [[S]] to double +// CHECK-NEXT: [[S_EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[S]] to double // CHECK-NEXT: [[A:%.*]] = load <25 x double>, ptr {{.*}}, align 8 // CHECK-NEXT: [[VECINSERT:%.*]] = insertelement <25 x double> poison, double [[S_EXT]], i64 0 // CHECK-NEXT: [[VECSPLAT:%.*]] = shufflevector <25 x double> [[VECINSERT]], <25 x double> poison, <25 x i32> zeroinitializer @@ -132,7 +132,7 @@ void multiply_compound_double_matrix_scalar_float(dx5x5_t a, float s) { // CHECK-LABEL: @divide_float_matrix_scalar_double( // CHECK: [[MAT:%.*]] = load <6 x float>, ptr [[MAT_ADDR:%.*]], align 4 // CHECK-NEXT: [[S:%.*]] = load double, ptr %s.addr, align 8 -// CHECK-NEXT: [[S_TRUNC:%.*]] = fptrunc double [[S]] to float +// CHECK-NEXT: [[S_TRUNC:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn double [[S]] to float // CHECK-NEXT: [[VECINSERT:%.*]] = insertelement <6 x float> poison, float [[S_TRUNC]], i64 0 // CHECK-NEXT: [[VECSPLAT:%.*]] = shufflevector <6 x float> [[VECINSERT]], <6 x float> poison, <6 x i32> zeroinitializer // CHECK-NEXT: [[RES:%.*]] = fdiv reassoc nnan ninf nsz arcp afn <6 x float> [[MAT]], [[VECSPLAT]] diff --git a/clang/test/CodeGen/ms-intrinsics.c b/clang/test/CodeGen/ms-intrinsics.c index 459a708d9b2e0..bb1b95fa7521a 100644 --- a/clang/test/CodeGen/ms-intrinsics.c +++ b/clang/test/CodeGen/ms-intrinsics.c @@ -221,6 +221,41 @@ void *test_InterlockedExchangePointer(void * volatile *Target, void *Value) { // CHECK: ret ptr %[[RESULT]] // CHECK: } +#if defined(__arm__) || defined(__aarch64__) +void *test_InterlockedExchangePointer_acq(void * volatile *Target, void *Value) { + return _InterlockedExchangePointer_acq(Target, Value); +} + +// CHECK-ARM-ARM64: define{{.*}}ptr @test_InterlockedExchangePointer_acq(ptr {{[a-z_ ]*}}%Target, ptr {{[a-z_ ]*}}%Value){{.*}}{ +// CHECK-ARM-ARM64: %[[VALUE:[0-9]+]] = ptrtoint ptr %Value to [[iPTR:i[0-9]+]] +// CHECK-ARM-ARM64: %[[EXCHANGE:[0-9]+]] = atomicrmw xchg ptr %Target, [[iPTR]] %[[VALUE]] acquire, align {{4|8}} +// CHECK-ARM-ARM64: %[[RESULT:[0-9]+]] = inttoptr [[iPTR]] %[[EXCHANGE]] to ptr +// CHECK-ARM-ARM64: ret ptr %[[RESULT]] +// CHECK-ARM-ARM64: } + +void *test_InterlockedExchangePointer_nf(void * volatile *Target, void *Value) { + return _InterlockedExchangePointer_nf(Target, Value); +} + +// CHECK-ARM-ARM64: define{{.*}}ptr @test_InterlockedExchangePointer_nf(ptr {{[a-z_ ]*}}%Target, ptr {{[a-z_ ]*}}%Value){{.*}}{ +// CHECK-ARM-ARM64: %[[VALUE:[0-9]+]] = ptrtoint ptr %Value to [[iPTR]] +// CHECK-ARM-ARM64: %[[EXCHANGE:[0-9]+]] = atomicrmw xchg ptr %Target, [[iPTR]] %[[VALUE]] monotonic, align {{4|8}} +// CHECK-ARM-ARM64: %[[RESULT:[0-9]+]] = inttoptr [[iPTR]] %[[EXCHANGE]] to ptr +// CHECK-ARM-ARM64: ret ptr %[[RESULT]] +// CHECK-ARM-ARM64: } + +void *test_InterlockedExchangePointer_rel(void * volatile *Target, void *Value) { + return _InterlockedExchangePointer_rel(Target, Value); +} + +// CHECK-ARM-ARM64: define{{.*}}ptr @test_InterlockedExchangePointer_rel(ptr {{[a-z_ ]*}}%Target, ptr {{[a-z_ ]*}}%Value){{.*}}{ +// CHECK-ARM-ARM64: %[[VALUE:[0-9]+]] = ptrtoint ptr %Value to [[iPTR]] +// CHECK-ARM-ARM64: %[[EXCHANGE:[0-9]+]] = atomicrmw xchg ptr %Target, [[iPTR]] %[[VALUE]] release, align {{4|8}} +// CHECK-ARM-ARM64: %[[RESULT:[0-9]+]] = inttoptr [[iPTR]] %[[EXCHANGE]] to ptr +// CHECK-ARM-ARM64: ret ptr %[[RESULT]] +// CHECK-ARM-ARM64: } +#endif + void *test_InterlockedCompareExchangePointer(void * volatile *Destination, void *Exchange, void *Comparand) { return _InterlockedCompareExchangePointer(Destination, Exchange, Comparand); @@ -249,6 +284,37 @@ void *test_InterlockedCompareExchangePointer_nf(void * volatile *Destination, // CHECK: ret ptr %[[RESULT:[0-9]+]] // CHECK: } +#if defined(__arm__) || defined(__aarch64__) +void *test_InterlockedCompareExchangePointer_acq(void * volatile *Destination, + void *Exchange, void *Comparand) { + return _InterlockedCompareExchangePointer_acq(Destination, Exchange, Comparand); +} + +// CHECK-ARM-ARM64: define{{.*}}ptr @test_InterlockedCompareExchangePointer_acq(ptr {{[a-z_ ]*}}%Destination, ptr {{[a-z_ ]*}}%Exchange, ptr {{[a-z_ ]*}}%Comparand){{.*}}{ +// CHECK-ARM-ARM64: %[[EXCHANGE:[0-9]+]] = ptrtoint ptr %Exchange to [[iPTR]] +// CHECK-ARM-ARM64: %[[COMPARAND:[0-9]+]] = ptrtoint ptr %Comparand to [[iPTR]] +// CHECK-ARM-ARM64: %[[XCHG:[0-9]+]] = cmpxchg volatile ptr %[[DEST:.+]], [[iPTR]] %[[COMPARAND:[0-9]+]], [[iPTR]] %[[EXCHANGE:[0-9]+]] acquire acquire, align {{4|8}} +// CHECK-ARM-ARM64: %[[EXTRACT:[0-9]+]] = extractvalue { [[iPTR]], i1 } %[[XCHG]], 0 +// CHECK-ARM-ARM64: %[[RESULT:[0-9]+]] = inttoptr [[iPTR]] %[[EXTRACT]] to ptr +// CHECK-ARM-ARM64: ret ptr %[[RESULT:[0-9]+]] +// CHECK-ARM-ARM64: } + + +void *test_InterlockedCompareExchangePointer_rel(void * volatile *Destination, + void *Exchange, void *Comparand) { + return _InterlockedCompareExchangePointer_rel(Destination, Exchange, Comparand); +} + +// CHECK-ARM-ARM64: define{{.*}}ptr @test_InterlockedCompareExchangePointer_rel(ptr {{[a-z_ ]*}}%Destination, ptr {{[a-z_ ]*}}%Exchange, ptr {{[a-z_ ]*}}%Comparand){{.*}}{ +// CHECK-ARM-ARM64: %[[EXCHANGE:[0-9]+]] = ptrtoint ptr %Exchange to [[iPTR]] +// CHECK-ARM-ARM64: %[[COMPARAND:[0-9]+]] = ptrtoint ptr %Comparand to [[iPTR]] +// CHECK-ARM-ARM64: %[[XCHG:[0-9]+]] = cmpxchg volatile ptr %[[DEST:.+]], [[iPTR]] %[[COMPARAND:[0-9]+]], [[iPTR]] %[[EXCHANGE:[0-9]+]] release monotonic, align {{4|8}} +// CHECK-ARM-ARM64: %[[EXTRACT:[0-9]+]] = extractvalue { [[iPTR]], i1 } %[[XCHG]], 0 +// CHECK-ARM-ARM64: %[[RESULT:[0-9]+]] = inttoptr [[iPTR]] %[[EXTRACT]] to ptr +// CHECK-ARM-ARM64: ret ptr %[[RESULT:[0-9]+]] +// CHECK-ARM-ARM64: } +#endif + char test_InterlockedExchange8(char volatile *value, char mask) { return _InterlockedExchange8(value, mask); } diff --git a/clang/test/CodeGen/nofpclass.c b/clang/test/CodeGen/nofpclass.c index d9b34c8e383f9..75aa0318421de 100644 --- a/clang/test/CodeGen/nofpclass.c +++ b/clang/test/CodeGen/nofpclass.c @@ -679,14 +679,14 @@ _Complex double defined_complex_func_f64_ret(_Complex double c) { // CFINITEONLY-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 // CFINITEONLY-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 // CFINITEONLY-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 -// CFINITEONLY-NEXT: [[EXT:%.*]] = fpext half [[C_REAL]] to float -// CFINITEONLY-NEXT: [[EXT1:%.*]] = fpext half [[C_IMAG]] to float +// CFINITEONLY-NEXT: [[EXT:%.*]] = fpext nnan ninf half [[C_REAL]] to float +// CFINITEONLY-NEXT: [[EXT1:%.*]] = fpext nnan ninf half [[C_IMAG]] to float // CFINITEONLY-NEXT: [[C_REALP2:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 // CFINITEONLY-NEXT: [[C_REAL3:%.*]] = load half, ptr [[C_REALP2]], align 2 // CFINITEONLY-NEXT: [[C_IMAGP4:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 // CFINITEONLY-NEXT: [[C_IMAG5:%.*]] = load half, ptr [[C_IMAGP4]], align 2 -// CFINITEONLY-NEXT: [[EXT6:%.*]] = fpext half [[C_REAL3]] to float -// CFINITEONLY-NEXT: [[EXT7:%.*]] = fpext half [[C_IMAG5]] to float +// CFINITEONLY-NEXT: [[EXT6:%.*]] = fpext nnan ninf half [[C_REAL3]] to float +// CFINITEONLY-NEXT: [[EXT7:%.*]] = fpext nnan ninf half [[C_IMAG5]] to float // CFINITEONLY-NEXT: [[MUL_AC:%.*]] = fmul nnan ninf float [[EXT]], [[EXT6]] // CFINITEONLY-NEXT: [[MUL_BD:%.*]] = fmul nnan ninf float [[EXT1]], [[EXT7]] // CFINITEONLY-NEXT: [[MUL_AD:%.*]] = fmul nnan ninf float [[EXT]], [[EXT7]] @@ -709,8 +709,8 @@ _Complex double defined_complex_func_f64_ret(_Complex double c) { // CFINITEONLY: complex_mul_cont: // CFINITEONLY-NEXT: [[REAL_MUL_PHI:%.*]] = phi nnan ninf float [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_REAL]], [[COMPLEX_MUL_LIBCALL]] ] // CFINITEONLY-NEXT: [[IMAG_MUL_PHI:%.*]] = phi nnan ninf float [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_IMAG]], [[COMPLEX_MUL_LIBCALL]] ] -// CFINITEONLY-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[REAL_MUL_PHI]] to half -// CFINITEONLY-NEXT: [[UNPROMOTION9:%.*]] = fptrunc float [[IMAG_MUL_PHI]] to half +// CFINITEONLY-NEXT: [[UNPROMOTION:%.*]] = fptrunc nnan ninf float [[REAL_MUL_PHI]] to half +// CFINITEONLY-NEXT: [[UNPROMOTION9:%.*]] = fptrunc nnan ninf float [[IMAG_MUL_PHI]] to half // CFINITEONLY-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // CFINITEONLY-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // CFINITEONLY-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 @@ -723,16 +723,16 @@ _Complex double defined_complex_func_f64_ret(_Complex double c) { // CLFINITEONLY-SAME: (<2 x half> noundef nofpclass(nan inf) [[C_COERCE:%.*]]) local_unnamed_addr #[[ATTR7:[0-9]+]] { // CLFINITEONLY-NEXT: entry: // CLFINITEONLY-NEXT: [[C_SROA_0_0_VEC_EXTRACT:%.*]] = extractelement <2 x half> [[C_COERCE]], i64 0 -// CLFINITEONLY-NEXT: [[EXT:%.*]] = fpext half [[C_SROA_0_0_VEC_EXTRACT]] to float +// CLFINITEONLY-NEXT: [[EXT:%.*]] = fpext nnan ninf half [[C_SROA_0_0_VEC_EXTRACT]] to float // CLFINITEONLY-NEXT: [[C_SROA_0_2_VEC_EXTRACT:%.*]] = extractelement <2 x half> [[C_COERCE]], i64 1 -// CLFINITEONLY-NEXT: [[EXT1:%.*]] = fpext half [[C_SROA_0_2_VEC_EXTRACT]] to float +// CLFINITEONLY-NEXT: [[EXT1:%.*]] = fpext nnan ninf half [[C_SROA_0_2_VEC_EXTRACT]] to float // CLFINITEONLY-NEXT: [[MUL_AD:%.*]] = fmul nnan ninf float [[EXT]], [[EXT1]] // CLFINITEONLY-NEXT: [[MUL_I:%.*]] = fadd nnan ninf float [[MUL_AD]], [[MUL_AD]] // CLFINITEONLY-NEXT: [[MUL_AC:%.*]] = fmul nnan ninf float [[EXT]], [[EXT]] // CLFINITEONLY-NEXT: [[MUL_BD:%.*]] = fmul nnan ninf float [[EXT1]], [[EXT1]] // CLFINITEONLY-NEXT: [[MUL_R:%.*]] = fsub nnan ninf float [[MUL_AC]], [[MUL_BD]] -// CLFINITEONLY-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[MUL_R]] to half -// CLFINITEONLY-NEXT: [[UNPROMOTION9:%.*]] = fptrunc float [[MUL_I]] to half +// CLFINITEONLY-NEXT: [[UNPROMOTION:%.*]] = fptrunc nnan ninf float [[MUL_R]] to half +// CLFINITEONLY-NEXT: [[UNPROMOTION9:%.*]] = fptrunc nnan ninf float [[MUL_I]] to half // CLFINITEONLY-NEXT: [[RETVAL_SROA_0_0_VEC_INSERT:%.*]] = insertelement <2 x half> poison, half [[UNPROMOTION]], i64 0 // CLFINITEONLY-NEXT: [[RETVAL_SROA_0_2_VEC_INSERT:%.*]] = insertelement <2 x half> [[RETVAL_SROA_0_0_VEC_INSERT]], half [[UNPROMOTION9]], i64 1 // CLFINITEONLY-NEXT: ret <2 x half> [[RETVAL_SROA_0_2_VEC_INSERT]] @@ -749,14 +749,14 @@ _Complex double defined_complex_func_f64_ret(_Complex double c) { // NONANS-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 // NONANS-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 // NONANS-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 -// NONANS-NEXT: [[EXT:%.*]] = fpext half [[C_REAL]] to float -// NONANS-NEXT: [[EXT1:%.*]] = fpext half [[C_IMAG]] to float +// NONANS-NEXT: [[EXT:%.*]] = fpext nnan half [[C_REAL]] to float +// NONANS-NEXT: [[EXT1:%.*]] = fpext nnan half [[C_IMAG]] to float // NONANS-NEXT: [[C_REALP2:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 // NONANS-NEXT: [[C_REAL3:%.*]] = load half, ptr [[C_REALP2]], align 2 // NONANS-NEXT: [[C_IMAGP4:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 // NONANS-NEXT: [[C_IMAG5:%.*]] = load half, ptr [[C_IMAGP4]], align 2 -// NONANS-NEXT: [[EXT6:%.*]] = fpext half [[C_REAL3]] to float -// NONANS-NEXT: [[EXT7:%.*]] = fpext half [[C_IMAG5]] to float +// NONANS-NEXT: [[EXT6:%.*]] = fpext nnan half [[C_REAL3]] to float +// NONANS-NEXT: [[EXT7:%.*]] = fpext nnan half [[C_IMAG5]] to float // NONANS-NEXT: [[MUL_AC:%.*]] = fmul nnan float [[EXT]], [[EXT6]] // NONANS-NEXT: [[MUL_BD:%.*]] = fmul nnan float [[EXT1]], [[EXT7]] // NONANS-NEXT: [[MUL_AD:%.*]] = fmul nnan float [[EXT]], [[EXT7]] @@ -779,8 +779,8 @@ _Complex double defined_complex_func_f64_ret(_Complex double c) { // NONANS: complex_mul_cont: // NONANS-NEXT: [[REAL_MUL_PHI:%.*]] = phi nnan float [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_REAL]], [[COMPLEX_MUL_LIBCALL]] ] // NONANS-NEXT: [[IMAG_MUL_PHI:%.*]] = phi nnan float [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_IMAG]], [[COMPLEX_MUL_LIBCALL]] ] -// NONANS-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[REAL_MUL_PHI]] to half -// NONANS-NEXT: [[UNPROMOTION9:%.*]] = fptrunc float [[IMAG_MUL_PHI]] to half +// NONANS-NEXT: [[UNPROMOTION:%.*]] = fptrunc nnan float [[REAL_MUL_PHI]] to half +// NONANS-NEXT: [[UNPROMOTION9:%.*]] = fptrunc nnan float [[IMAG_MUL_PHI]] to half // NONANS-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // NONANS-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // NONANS-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 @@ -800,14 +800,14 @@ _Complex double defined_complex_func_f64_ret(_Complex double c) { // NOINFS-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 // NOINFS-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 // NOINFS-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 -// NOINFS-NEXT: [[EXT:%.*]] = fpext half [[C_REAL]] to float -// NOINFS-NEXT: [[EXT1:%.*]] = fpext half [[C_IMAG]] to float +// NOINFS-NEXT: [[EXT:%.*]] = fpext ninf half [[C_REAL]] to float +// NOINFS-NEXT: [[EXT1:%.*]] = fpext ninf half [[C_IMAG]] to float // NOINFS-NEXT: [[C_REALP2:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 // NOINFS-NEXT: [[C_REAL3:%.*]] = load half, ptr [[C_REALP2]], align 2 // NOINFS-NEXT: [[C_IMAGP4:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 // NOINFS-NEXT: [[C_IMAG5:%.*]] = load half, ptr [[C_IMAGP4]], align 2 -// NOINFS-NEXT: [[EXT6:%.*]] = fpext half [[C_REAL3]] to float -// NOINFS-NEXT: [[EXT7:%.*]] = fpext half [[C_IMAG5]] to float +// NOINFS-NEXT: [[EXT6:%.*]] = fpext ninf half [[C_REAL3]] to float +// NOINFS-NEXT: [[EXT7:%.*]] = fpext ninf half [[C_IMAG5]] to float // NOINFS-NEXT: [[MUL_AC:%.*]] = fmul ninf float [[EXT]], [[EXT6]] // NOINFS-NEXT: [[MUL_BD:%.*]] = fmul ninf float [[EXT1]], [[EXT7]] // NOINFS-NEXT: [[MUL_AD:%.*]] = fmul ninf float [[EXT]], [[EXT7]] @@ -830,8 +830,8 @@ _Complex double defined_complex_func_f64_ret(_Complex double c) { // NOINFS: complex_mul_cont: // NOINFS-NEXT: [[REAL_MUL_PHI:%.*]] = phi ninf float [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_REAL]], [[COMPLEX_MUL_LIBCALL]] ] // NOINFS-NEXT: [[IMAG_MUL_PHI:%.*]] = phi ninf float [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_IMAG]], [[COMPLEX_MUL_LIBCALL]] ] -// NOINFS-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[REAL_MUL_PHI]] to half -// NOINFS-NEXT: [[UNPROMOTION9:%.*]] = fptrunc float [[IMAG_MUL_PHI]] to half +// NOINFS-NEXT: [[UNPROMOTION:%.*]] = fptrunc ninf float [[REAL_MUL_PHI]] to half +// NOINFS-NEXT: [[UNPROMOTION9:%.*]] = fptrunc ninf float [[IMAG_MUL_PHI]] to half // NOINFS-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 // NOINFS-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 // NOINFS-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 @@ -879,7 +879,7 @@ _Complex _Float16 defined_complex_func_f16_ret(_Complex _Float16 c) { // CFINITEONLY-NEXT: store <2 x half> [[V2F162]], ptr [[V2F16_ADDR]], align 4 // CFINITEONLY-NEXT: [[TMP2:%.*]] = load float, ptr [[F32_ADDR]], align 4 // CFINITEONLY-NEXT: [[TMP3:%.*]] = load float, ptr [[F32_ADDR]], align 4 -// CFINITEONLY-NEXT: [[CONV:%.*]] = fpext float [[TMP3]] to double +// CFINITEONLY-NEXT: [[CONV:%.*]] = fpext nnan ninf float [[TMP3]] to double // CFINITEONLY-NEXT: [[TMP4:%.*]] = load double, ptr [[F64_ADDR]], align 8 // CFINITEONLY-NEXT: [[TMP5:%.*]] = load half, ptr [[F16_ADDR]], align 2 // CFINITEONLY-NEXT: [[TMP6:%.*]] = load <2 x float>, ptr [[V2F32_ADDR]], align 8 @@ -923,7 +923,7 @@ _Complex _Float16 defined_complex_func_f16_ret(_Complex _Float16 c) { // CLFINITEONLY-SAME: (float noundef nofpclass(nan inf) [[F32:%.*]], double noundef nofpclass(nan inf) [[F64:%.*]], half noundef nofpclass(nan inf) [[F16:%.*]], double noundef nofpclass(nan inf) [[V2F32_COERCE:%.*]], <2 x double> noundef nofpclass(nan inf) [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef nofpclass(nan inf) [[CF32_COERCE:%.*]], double noundef nofpclass(nan inf) [[CF64_COERCE0:%.*]], double noundef nofpclass(nan inf) [[CF64_COERCE1:%.*]], ptr nocapture noundef readonly byval({ half, half }) align 8 [[CF16:%.*]]) local_unnamed_addr #[[ATTR5]] { // CLFINITEONLY-NEXT: entry: // CLFINITEONLY-NEXT: [[BYVAL_TEMP:%.*]] = alloca { double, double }, align 8 -// CLFINITEONLY-NEXT: [[CONV:%.*]] = fpext float [[F32]] to double +// CLFINITEONLY-NEXT: [[CONV:%.*]] = fpext nnan ninf float [[F32]] to double // CLFINITEONLY-NEXT: [[CF16_REAL:%.*]] = load half, ptr [[CF16]], align 8 // CLFINITEONLY-NEXT: [[CF16_IMAGP:%.*]] = getelementptr inbounds nuw i8, ptr [[CF16]], i64 2 // CLFINITEONLY-NEXT: [[CF16_IMAG:%.*]] = load half, ptr [[CF16_IMAGP]], align 2 @@ -973,7 +973,7 @@ _Complex _Float16 defined_complex_func_f16_ret(_Complex _Float16 c) { // NONANS-NEXT: store <2 x half> [[V2F162]], ptr [[V2F16_ADDR]], align 4 // NONANS-NEXT: [[TMP2:%.*]] = load float, ptr [[F32_ADDR]], align 4 // NONANS-NEXT: [[TMP3:%.*]] = load float, ptr [[F32_ADDR]], align 4 -// NONANS-NEXT: [[CONV:%.*]] = fpext float [[TMP3]] to double +// NONANS-NEXT: [[CONV:%.*]] = fpext nnan float [[TMP3]] to double // NONANS-NEXT: [[TMP4:%.*]] = load double, ptr [[F64_ADDR]], align 8 // NONANS-NEXT: [[TMP5:%.*]] = load half, ptr [[F16_ADDR]], align 2 // NONANS-NEXT: [[TMP6:%.*]] = load <2 x float>, ptr [[V2F32_ADDR]], align 8 @@ -1048,7 +1048,7 @@ _Complex _Float16 defined_complex_func_f16_ret(_Complex _Float16 c) { // NOINFS-NEXT: store <2 x half> [[V2F162]], ptr [[V2F16_ADDR]], align 4 // NOINFS-NEXT: [[TMP2:%.*]] = load float, ptr [[F32_ADDR]], align 4 // NOINFS-NEXT: [[TMP3:%.*]] = load float, ptr [[F32_ADDR]], align 4 -// NOINFS-NEXT: [[CONV:%.*]] = fpext float [[TMP3]] to double +// NOINFS-NEXT: [[CONV:%.*]] = fpext ninf float [[TMP3]] to double // NOINFS-NEXT: [[TMP4:%.*]] = load double, ptr [[F64_ADDR]], align 8 // NOINFS-NEXT: [[TMP5:%.*]] = load half, ptr [[F16_ADDR]], align 2 // NOINFS-NEXT: [[TMP6:%.*]] = load <2 x float>, ptr [[V2F32_ADDR]], align 8 @@ -1132,7 +1132,7 @@ float call_variadic(float f32, double f64, _Float16 f16, // CFINITEONLY-NEXT: [[TMP2:%.*]] = load ptr, ptr [[FPTR_ADDR]], align 8 // CFINITEONLY-NEXT: [[TMP3:%.*]] = load float, ptr [[F32_ADDR]], align 4 // CFINITEONLY-NEXT: [[TMP4:%.*]] = load float, ptr [[F32_ADDR]], align 4 -// CFINITEONLY-NEXT: [[CONV:%.*]] = fpext float [[TMP4]] to double +// CFINITEONLY-NEXT: [[CONV:%.*]] = fpext nnan ninf float [[TMP4]] to double // CFINITEONLY-NEXT: [[TMP5:%.*]] = load double, ptr [[F64_ADDR]], align 8 // CFINITEONLY-NEXT: [[TMP6:%.*]] = load half, ptr [[F16_ADDR]], align 2 // CFINITEONLY-NEXT: [[TMP7:%.*]] = load <2 x float>, ptr [[V2F32_ADDR]], align 8 @@ -1176,7 +1176,7 @@ float call_variadic(float f32, double f64, _Float16 f16, // CLFINITEONLY-SAME: (ptr nocapture noundef readonly [[FPTR:%.*]], float noundef nofpclass(nan inf) [[F32:%.*]], double noundef nofpclass(nan inf) [[F64:%.*]], half noundef nofpclass(nan inf) [[F16:%.*]], double noundef nofpclass(nan inf) [[V2F32_COERCE:%.*]], <2 x double> noundef nofpclass(nan inf) [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef nofpclass(nan inf) [[CF32_COERCE:%.*]], double noundef nofpclass(nan inf) [[CF64_COERCE0:%.*]], double noundef nofpclass(nan inf) [[CF64_COERCE1:%.*]], ptr nocapture noundef readonly byval({ half, half }) align 8 [[CF16:%.*]]) local_unnamed_addr #[[ATTR5]] { // CLFINITEONLY-NEXT: entry: // CLFINITEONLY-NEXT: [[BYVAL_TEMP:%.*]] = alloca { double, double }, align 8 -// CLFINITEONLY-NEXT: [[CONV:%.*]] = fpext float [[F32]] to double +// CLFINITEONLY-NEXT: [[CONV:%.*]] = fpext nnan ninf float [[F32]] to double // CLFINITEONLY-NEXT: [[CF16_REAL:%.*]] = load half, ptr [[CF16]], align 8 // CLFINITEONLY-NEXT: [[CF16_IMAGP:%.*]] = getelementptr inbounds nuw i8, ptr [[CF16]], i64 2 // CLFINITEONLY-NEXT: [[CF16_IMAG:%.*]] = load half, ptr [[CF16_IMAGP]], align 2 @@ -1229,7 +1229,7 @@ float call_variadic(float f32, double f64, _Float16 f16, // NONANS-NEXT: [[TMP2:%.*]] = load ptr, ptr [[FPTR_ADDR]], align 8 // NONANS-NEXT: [[TMP3:%.*]] = load float, ptr [[F32_ADDR]], align 4 // NONANS-NEXT: [[TMP4:%.*]] = load float, ptr [[F32_ADDR]], align 4 -// NONANS-NEXT: [[CONV:%.*]] = fpext float [[TMP4]] to double +// NONANS-NEXT: [[CONV:%.*]] = fpext nnan float [[TMP4]] to double // NONANS-NEXT: [[TMP5:%.*]] = load double, ptr [[F64_ADDR]], align 8 // NONANS-NEXT: [[TMP6:%.*]] = load half, ptr [[F16_ADDR]], align 2 // NONANS-NEXT: [[TMP7:%.*]] = load <2 x float>, ptr [[V2F32_ADDR]], align 8 @@ -1307,7 +1307,7 @@ float call_variadic(float f32, double f64, _Float16 f16, // NOINFS-NEXT: [[TMP2:%.*]] = load ptr, ptr [[FPTR_ADDR]], align 8 // NOINFS-NEXT: [[TMP3:%.*]] = load float, ptr [[F32_ADDR]], align 4 // NOINFS-NEXT: [[TMP4:%.*]] = load float, ptr [[F32_ADDR]], align 4 -// NOINFS-NEXT: [[CONV:%.*]] = fpext float [[TMP4]] to double +// NOINFS-NEXT: [[CONV:%.*]] = fpext ninf float [[TMP4]] to double // NOINFS-NEXT: [[TMP5:%.*]] = load double, ptr [[F64_ADDR]], align 8 // NOINFS-NEXT: [[TMP6:%.*]] = load half, ptr [[F16_ADDR]], align 2 // NOINFS-NEXT: [[TMP7:%.*]] = load <2 x float>, ptr [[V2F32_ADDR]], align 8 diff --git a/clang/test/CodeGen/ptrauth-function-attributes.c b/clang/test/CodeGen/ptrauth-function-attributes.c index e7081f00b4f68..caf613f0c66ab 100644 --- a/clang/test/CodeGen/ptrauth-function-attributes.c +++ b/clang/test/CodeGen/ptrauth-function-attributes.c @@ -14,6 +14,9 @@ // RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-indirect-gotos -emit-llvm %s -o - | FileCheck %s --check-prefixes=ALL,GOTOS // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-indirect-gotos -emit-llvm %s -o - | FileCheck %s --check-prefixes=ALL,GOTOS +// RUN: %clang_cc1 -triple arm64e-apple-ios -faarch64-jump-table-hardening -emit-llvm %s -o - | FileCheck %s --check-prefixes=ALL,JMPTBL +// RUN: %clang_cc1 -triple aarch64-linux-gnu -faarch64-jump-table-hardening -emit-llvm %s -o - | FileCheck %s --check-prefixes=ALL,JMPTBL + // ALL: define {{(dso_local )?}}void @test() #0 void test() { } @@ -26,4 +29,6 @@ void test() { // GOTOS: attributes #0 = {{{.*}} "ptrauth-indirect-gotos" {{.*}}} +// JMPTBL: attributes #0 = {{{.*}} "aarch64-jump-table-hardening" {{.*}}} + // OFF-NOT: attributes {{.*}} "ptrauth- diff --git a/clang/test/CodeGen/tbaa-pointers.c b/clang/test/CodeGen/tbaa-pointers.c index 068459f4dce11..6aee2ff3717ac 100644 --- a/clang/test/CodeGen/tbaa-pointers.c +++ b/clang/test/CodeGen/tbaa-pointers.c @@ -1,18 +1,18 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-passes -no-pointer-tbaa %s -emit-llvm -o - | FileCheck --check-prefixes=COMMON,DISABLE %s // RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-passes %s -emit-llvm -o - | FileCheck --check-prefixes=COMMON,DEFAULT %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-passes -pointer-tbaa %s -emit-llvm -o - | FileCheck --check-prefixes=COMMON,ENABLED %s +// RUN: %clang --target=x86_64-apple-darwin -O1 -fno-pointer-tbaa %s -emit-llvm -S -mllvm -disable-llvm-optzns -o - | FileCheck --check-prefixes=COMMON,DISABLE %s // RUN: %clang --target=x86_64-apple-darwin -O1 %s -emit-llvm -S -mllvm -disable-llvm-optzns -o - | FileCheck --check-prefixes=COMMON,DEFAULT %s -// RUN: %clang --target=x86_64-apple-darwin -O1 -fpointer-tbaa %s -emit-llvm -S -mllvm -disable-llvm-optzns -o - | FileCheck --check-prefixes=COMMON,ENABLED %s void p2unsigned(unsigned **ptr) { // COMMON-LABEL: define void @p2unsigned( // COMMON-SAME: ptr noundef [[PTR:%.+]]) // COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 - // ENABLED-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P2INT_0:!.+]] - // ENABLED-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P2INT_0]] - // ENABLED-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[P1INT_0:!.+]] - // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR:!.+]] - // DEFAULT-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[ANYPTR]] + // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P2INT_0:!.+]] + // DEFAULT-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P2INT_0]] + // DEFAULT-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[P1INT_0:!.+]] + // DISABLE-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR:!.+]] + // DISABLE-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[ANYPTR]] // COMMON-NEXT: ret void // *ptr = 0; @@ -22,12 +22,12 @@ void p2unsigned_volatile(unsigned *volatile *ptr) { // COMMON-LABEL: define void @p2unsigned_volatile( // COMMON-SAME: ptr noundef [[PTR:%.+]]) // COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 - // ENABLED-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P2INT_0]] - // ENABLED-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P2INT_0]] - // ENABLED-NEXT: store volatile ptr null, ptr [[BASE]], align 8, !tbaa [[P1INT_0]] - // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: store volatile ptr null, ptr [[BASE]], align 8, !tbaa [[ANYPTR]] + // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P2INT_0]] + // DEFAULT-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P2INT_0]] + // DEFAULT-NEXT: store volatile ptr null, ptr [[BASE]], align 8, !tbaa [[P1INT_0]] + // DISABLE-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: store volatile ptr null, ptr [[BASE]], align 8, !tbaa [[ANYPTR]] // COMMON-NEXT: ret void // *ptr = 0; @@ -37,14 +37,14 @@ void p3int(int ***ptr) { // COMMON-LABEL: define void @p3int( // COMMON-SAME: ptr noundef [[PTR:%.+]]) // COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 - // ENABLED-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P3INT_0:!.+]] - // ENABLED-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P3INT_0]] - // ENABLED-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P2INT_0]] - // ENABLED-NEXT: store ptr null, ptr [[BASE_1]], align 8, !tbaa [[P1INT_0]] - // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: store ptr null, ptr [[BASE_1]], align 8, !tbaa [[ANYPTR]] + // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P3INT_0:!.+]] + // DEFAULT-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P3INT_0]] + // DEFAULT-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P2INT_0]] + // DEFAULT-NEXT: store ptr null, ptr [[BASE_1]], align 8, !tbaa [[P1INT_0]] + // DISABLE-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: store ptr null, ptr [[BASE_1]], align 8, !tbaa [[ANYPTR]] // COMMON-NEXT: ret void // **ptr = 0; @@ -54,16 +54,16 @@ void p4char(char ****ptr) { // COMMON-LABEL: define void @p4char( // COMMON-SAME: ptr noundef [[PTR:%.+]]) // COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 - // ENABLED-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P4CHAR_0:!.+]] - // ENABLED-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P4CHAR_0]] - // ENABLED-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0:!.+]] - // ENABLED-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0:!.+]] - // ENABLED-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0:!.+]] - // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANYPTR]] + // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P4CHAR_0:!.+]] + // DEFAULT-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P4CHAR_0]] + // DEFAULT-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0:!.+]] + // DEFAULT-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0:!.+]] + // DEFAULT-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0:!.+]] + // DISABLE-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANYPTR]] // COMMON-NEXT: ret void // ***ptr = 0; @@ -73,16 +73,16 @@ void p4char_const1(const char ****ptr) { // COMMON-LABEL: define void @p4char_const1( // COMMON-SAME: ptr noundef [[PTR:%.+]]) // COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 - // ENABLED-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P4CHAR_0]] - // ENABLED-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P4CHAR_0]] - // ENABLED-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0]] - // ENABLED-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0]] - // ENABLED-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0]] - // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANYPTR]] + // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P4CHAR_0]] + // DEFAULT-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P4CHAR_0]] + // DEFAULT-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0]] + // DEFAULT-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0]] + // DEFAULT-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0]] + // DISABLE-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANYPTR]] // COMMON-NEXT: ret void // ***ptr = 0; @@ -92,16 +92,16 @@ void p4char_const2(const char **const **ptr) { // COMMON-LABEL: define void @p4char_const2( // COMMON-SAME: ptr noundef [[PTR:%.+]]) // COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 - // ENABLED-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P4CHAR_0]] - // ENABLED-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P4CHAR_0]] - // ENABLED-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0]] - // ENABLED-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0]] - // ENABLED-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0]] - // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANYPTR]] + // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P4CHAR_0]] + // DEFAULT-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P4CHAR_0]] + // DEFAULT-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0]] + // DEFAULT-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0]] + // DEFAULT-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0]] + // DISABLE-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: [[BASE_0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANYPTR]] // COMMON-NEXT: ret void // ***ptr = 0; @@ -116,12 +116,12 @@ void p2struct(struct S1 **ptr) { // COMMON-LABEL: define void @p2struct( // COMMON-SAME: ptr noundef [[PTR:%.+]]) // COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 - // ENABLED-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P2S1_TAG:!.+]] - // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // ENABLED-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P2S1_TAG]] - // DEFAULT-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // ENABLED-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[P1S1_TAG:!.+]] - // DEFAULT-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[ANYPTR]] + // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P2S1_TAG:!.+]] + // DISABLE-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DEFAULT-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P2S1_TAG]] + // DISABLE-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DEFAULT-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[P1S1_TAG:!.+]] + // DISABLE-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[ANYPTR]] // COMMON-NEXT: ret void // *ptr = 0; @@ -133,8 +133,8 @@ void p2struct_const(struct S1 const **ptr) { // COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 // COMMON-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR:!.+]] // COMMON-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // ENABLED-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[P1S1_TAG]] - // DEFAULT-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[ANYPTR]] + // DEFAULT-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[P1S1_TAG]] + // DISABLE-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[ANYPTR]] // COMMON-NEXT: ret void // *ptr = 0; @@ -148,14 +148,14 @@ void p2struct2(struct S2 *ptr) { // COMMON-LABEL: define void @p2struct2( // COMMON-SAME: ptr noundef [[PTR:%.+]]) // COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 - // ENABLED-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P1S2_TAG:!.+]] - // ENABLED-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P1S2_TAG]] - // ENABLED-NEXT: [[S:%.+]] = getelementptr inbounds nuw %struct.S2, ptr [[BASE]], i32 0, i32 0 - // ENABLED-NEXT: store ptr null, ptr [[S]], align 8, !tbaa [[S2_S_TAG:!.+]] - // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // DEFAULT-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P1S2_TAG:!.+]] + // DEFAULT-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P1S2_TAG]] // DEFAULT-NEXT: [[S:%.+]] = getelementptr inbounds nuw %struct.S2, ptr [[BASE]], i32 0, i32 0 // DEFAULT-NEXT: store ptr null, ptr [[S]], align 8, !tbaa [[S2_S_TAG:!.+]] + // DISABLE-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DISABLE-NEXT: [[S:%.+]] = getelementptr inbounds nuw %struct.S2, ptr [[BASE]], i32 0, i32 0 + // DISABLE-NEXT: store ptr null, ptr [[S]], align 8, !tbaa [[S2_S_TAG:!.+]] // COMMON-NEXT: ret void ptr->s = 0; } @@ -168,20 +168,20 @@ void vla1(int n, int ptr[][n], int idx) { // COMMON-NEXT: [[PTR_ADDR:%.+]] = alloca ptr, align 8 // COMMON-NEXT: [[IDX_ADDR:%.+]] = alloca i32, align 4 // COMMON-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4, !tbaa [[INT_TY:!.+]] -// ENABLED-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P1INT0:!.+]] -// DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] +// DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P1INT0:!.+]] +// DISABLE-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] // COMMON-NEXT: store i32 [[IDX]], ptr [[IDX_ADDR]], align 4, !tbaa [[INT_TY]] // COMMON-NEXT: [[L:%.+]] = load i32, ptr [[N_ADDR]], align 4, !tbaa [[INT_TY]] // COMMON-NEXT: [[L_EXT:%.+]] = zext i32 [[L]] to i64 -// ENABLED-NEXT: [[L_PTR:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P1INT0]] -// DEFAULT-NEXT: [[L_PTR:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] +// DEFAULT-NEXT: [[L_PTR:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P1INT0]] +// DISABLE-NEXT: [[L_PTR:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] // COMMON-NEXT: [[L_IDX:%.+]] = load i32, ptr [[IDX_ADDR]], align 4, !tbaa [[INT_TY]] // COMMON-NEXT: [[IDX_EXT:%.+]] = sext i32 [[L_IDX]] to i64 // COMMON-NEXT: [[MUL:%.+]] = mul nsw i64 [[IDX_EXT]], [[L_EXT]] // COMMON-NEXT: [[GEP1:%.+]] = getelementptr inbounds i32, ptr [[L_PTR]], i64 [[MUL]] // COMMON-NEXT: [[GEP2:%.+]] = getelementptr inbounds i32, ptr [[GEP1]], i64 0 // COMMON-NEXT: store i32 0, ptr [[GEP2]], align 4, !tbaa [[INT_TAG:!.+]] -// ENABLED-NEXT: ret void +// DEFAULT-NEXT: ret void ptr[idx][0] = 0; } @@ -194,10 +194,10 @@ void unamed_struct_typedef(TypedefS *ptr) { // COMMON-LABEL: define void @unamed_struct_typedef( // COMMON-SAME: ptr noundef [[PTRA:%.+]]) // COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 -// DEFAULT-NEXT: store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] -// DEFAULT-NEXT: [[L0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] -// ENABLED-NEXT: store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[P1TYPEDEF:!.+]] -// ENABLED-NEXT: [[L0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P1TYPEDEF]] +// DISABLE-NEXT: store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] +// DISABLE-NEXT: [[L0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] +// DEFAULT-NEXT: store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[P1TYPEDEF:!.+]] +// DEFAULT-NEXT: [[L0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P1TYPEDEF]] // COMMON-NEXT: [[GEP:%.+]] = getelementptr inbounds nuw %struct.TypedefS, ptr [[L0]], i32 0, i32 0 // COMMON-NEXT: store i32 0, ptr [[GEP]], align 4 // COMMON-NEXT: ret void @@ -205,35 +205,35 @@ void unamed_struct_typedef(TypedefS *ptr) { ptr->i1 = 0; } -// ENABLED: [[P2INT_0]] = !{[[P2INT:!.+]], [[P2INT]], i64 0} -// ENABLED: [[P2INT]] = !{!"p2 int", [[ANY_POINTER:!.+]], i64 0} -// DEFAULT: [[ANYPTR]] = !{[[ANY_POINTER:!.+]], [[ANY_POINTER]], i64 0} +// DEFAULT: [[P2INT_0]] = !{[[P2INT:!.+]], [[P2INT]], i64 0} +// DEFAULT: [[P2INT]] = !{!"p2 int", [[ANY_POINTER:!.+]], i64 0} +// DISABLE: [[ANYPTR]] = !{[[ANY_POINTER:!.+]], [[ANY_POINTER]], i64 0} // COMMON: [[ANY_POINTER]] = !{!"any pointer", [[CHAR:!.+]], i64 0} // COMMON: [[CHAR]] = !{!"omnipotent char", [[TBAA_ROOT:!.+]], i64 0} // COMMON: [[TBAA_ROOT]] = !{!"Simple C/C++ TBAA"} -// ENABLED: [[P1INT_0]] = !{[[P1INT:!.+]], [[P1INT]], i64 0} -// ENABLED: [[P1INT]] = !{!"p1 int", [[ANY_POINTER]], i64 0} -// ENABLED: [[P3INT_0]] = !{[[P3INT:!.+]], [[P3INT]], i64 0} -// ENABLED: [[P3INT]] = !{!"p3 int", [[ANY_POINTER]], i64 0} -// ENABLED: [[P4CHAR_0]] = !{[[P4CHAR:!.+]], [[P4CHAR]], i64 0} -// ENABLED: [[P4CHAR]] = !{!"p4 omnipotent char", [[ANY_POINTER]], i64 0} -// ENABLED: [[P3CHAR_0]] = !{[[P3CHAR:!.+]], [[P3CHAR]], i64 0} -// ENABLED: [[P3CHAR]] = !{!"p3 omnipotent char", [[ANY_POINTER]], i64 0} -// ENABLED: [[P2CHAR_0]] = !{[[P2CHAR:!.+]], [[P2CHAR]], i64 0} -// ENABLED: [[P2CHAR]] = !{!"p2 omnipotent char", [[ANY_POINTER]], i64 0} -// ENABLED: [[P1CHAR_0]] = !{[[P1CHAR:!.+]], [[P1CHAR]], i64 0} -// ENABLED: [[P1CHAR]] = !{!"p1 omnipotent char", [[ANY_POINTER]], i64 0} -// ENABLED: [[P2S1_TAG]] = !{[[P2S1:!.+]], [[P2S1]], i64 0} -// ENABLED: [[P2S1]] = !{!"p2 _ZTS2S1", [[ANY_POINTER]], i64 0} -// ENABLED: [[P1S1_TAG:!.+]] = !{[[P1S1:!.+]], [[P1S1]], i64 0} -// ENABLED: [[P1S1]] = !{!"p1 _ZTS2S1", [[ANY_POINTER]], i64 0} -// ENABLED: [[P1S2_TAG]] = !{[[P1S2:!.+]], [[P1S2]], i64 0} -// ENABLED: [[P1S2]] = !{!"p1 _ZTS2S2", [[ANY_POINTER]], i64 0} - -// ENABLED: [[S2_S_TAG]] = !{[[S2_TY:!.+]], [[P1S1]], i64 0} -// ENABLED: [[S2_TY]] = !{!"S2", [[P1S1]], i64 0} -// DEFAULT: [[S2_S_TAG]] = !{[[S2_TY:!.+]], [[ANY_POINTER]], i64 0} -// DEFAULT: [[S2_TY]] = !{!"S2", [[ANY_POINTER]], i64 0} +// DEFAULT: [[P1INT_0]] = !{[[P1INT:!.+]], [[P1INT]], i64 0} +// DEFAULT: [[P1INT]] = !{!"p1 int", [[ANY_POINTER]], i64 0} +// DEFAULT: [[P3INT_0]] = !{[[P3INT:!.+]], [[P3INT]], i64 0} +// DEFAULT: [[P3INT]] = !{!"p3 int", [[ANY_POINTER]], i64 0} +// DEFAULT: [[P4CHAR_0]] = !{[[P4CHAR:!.+]], [[P4CHAR]], i64 0} +// DEFAULT: [[P4CHAR]] = !{!"p4 omnipotent char", [[ANY_POINTER]], i64 0} +// DEFAULT: [[P3CHAR_0]] = !{[[P3CHAR:!.+]], [[P3CHAR]], i64 0} +// DEFAULT: [[P3CHAR]] = !{!"p3 omnipotent char", [[ANY_POINTER]], i64 0} +// DEFAULT: [[P2CHAR_0]] = !{[[P2CHAR:!.+]], [[P2CHAR]], i64 0} +// DEFAULT: [[P2CHAR]] = !{!"p2 omnipotent char", [[ANY_POINTER]], i64 0} +// DEFAULT: [[P1CHAR_0]] = !{[[P1CHAR:!.+]], [[P1CHAR]], i64 0} +// DEFAULT: [[P1CHAR]] = !{!"p1 omnipotent char", [[ANY_POINTER]], i64 0} +// DEFAULT: [[P2S1_TAG]] = !{[[P2S1:!.+]], [[P2S1]], i64 0} +// DEFAULT: [[P2S1]] = !{!"p2 _ZTS2S1", [[ANY_POINTER]], i64 0} +// DEFAULT: [[P1S1_TAG:!.+]] = !{[[P1S1:!.+]], [[P1S1]], i64 0} +// DEFAULT: [[P1S1]] = !{!"p1 _ZTS2S1", [[ANY_POINTER]], i64 0} +// DEFAULT: [[P1S2_TAG]] = !{[[P1S2:!.+]], [[P1S2]], i64 0} +// DEFAULT: [[P1S2]] = !{!"p1 _ZTS2S2", [[ANY_POINTER]], i64 0} + +// DEFAULT: [[S2_S_TAG]] = !{[[S2_TY:!.+]], [[P1S1]], i64 0} +// DEFAULT: [[S2_TY]] = !{!"S2", [[P1S1]], i64 0} +// DISABLE: [[S2_S_TAG]] = !{[[S2_TY:!.+]], [[ANY_POINTER]], i64 0} +// DISABLE: [[S2_TY]] = !{!"S2", [[ANY_POINTER]], i64 0} // COMMON: [[INT_TAG]] = !{[[INT_TY:!.+]], [[INT_TY]], i64 0} // COMMON: [[INT_TY]] = !{!"int", [[CHAR]], i64 0} -// ENABLED: [[P1TYPEDEF]] = !{[[ANY_POINTER]], [[ANY_POINTER]], i64 0} +// DEFAULT: [[P1TYPEDEF]] = !{[[ANY_POINTER]], [[ANY_POINTER]], i64 0} diff --git a/clang/test/CodeGen/tbaa-reference.cpp b/clang/test/CodeGen/tbaa-reference.cpp index 8395badf35ded..1f62849bb6f42 100644 --- a/clang/test/CodeGen/tbaa-reference.cpp +++ b/clang/test/CodeGen/tbaa-reference.cpp @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,OLD-PATH -// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes -pointer-tbaa %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,OLD-PATH-POINTER -// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s -emit-llvm -new-struct-path-tbaa -o - | FileCheck %s -check-prefixes=CHECK,NEW-PATH -// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s -pointer-tbaa -emit-llvm -new-struct-path-tbaa -o - | FileCheck %s -check-prefixes=CHECK,NEW-PATH-POINTER +// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes -no-pointer-tbaa %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,OLD-PATH +// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,OLD-PATH-POINTER +// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s -no-pointer-tbaa -emit-llvm -new-struct-path-tbaa -o - | FileCheck %s -check-prefixes=CHECK,NEW-PATH +// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s -emit-llvm -new-struct-path-tbaa -o - | FileCheck %s -check-prefixes=CHECK,NEW-PATH-POINTER // // Check that we generate correct TBAA information for reference accesses. diff --git a/clang/test/CodeGen/union-tbaa1.c b/clang/test/CodeGen/union-tbaa1.c index 5263b1714c8c6..0f7a67cb7eccd 100644 --- a/clang/test/CodeGen/union-tbaa1.c +++ b/clang/test/CodeGen/union-tbaa1.c @@ -27,10 +27,10 @@ void bar(vect32 p[][2]); // CHECK-NEXT: store i32 [[TMP3]], ptr [[VEC]], align 4, !tbaa [[TBAA2]] // CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[INDEX]], align 4, !tbaa [[TBAA2]] // CHECK-NEXT: [[ARRAYIDX14:%.*]] = getelementptr inbounds [4 x [2 x %union.vect32]], ptr [[TMP]], i32 0, i32 [[TMP4]], i32 1 -// CHECK-NEXT: [[ARRAYIDX15:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX14]], i32 2 +// CHECK-NEXT: [[ARRAYIDX15:%.*]] = getelementptr inbounds nuw i8, ptr [[ARRAYIDX14]], i32 2 // CHECK-NEXT: [[TMP5:%.*]] = load i16, ptr [[ARRAYIDX15]], align 2, !tbaa [[TBAA6]] // CHECK-NEXT: [[CONV16:%.*]] = zext i16 [[TMP5]] to i32 -// CHECK-NEXT: [[ARRAYIDX17:%.*]] = getelementptr inbounds i8, ptr [[VEC]], i32 4 +// CHECK-NEXT: [[ARRAYIDX17:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i32 4 // CHECK-NEXT: store i32 [[CONV16]], ptr [[ARRAYIDX17]], align 4, !tbaa [[TBAA2]] // CHECK-NEXT: call void @bar(ptr noundef nonnull [[TMP]]) #[[ATTR3]] // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[TMP]]) #[[ATTR3]] diff --git a/clang/test/CodeGenCUDA/amdgpu-atomic-ops.cu b/clang/test/CodeGenCUDA/amdgpu-atomic-ops.cu index efe75be8488b3..0e5fe8fa35cf1 100644 --- a/clang/test/CodeGenCUDA/amdgpu-atomic-ops.cu +++ b/clang/test/CodeGenCUDA/amdgpu-atomic-ops.cu @@ -157,7 +157,7 @@ __global__ void ffp3(long double *p) { __device__ double ffp4(double *p, float f) { // CHECK-LABEL: @_Z4ffp4Pdf - // CHECK: fpext float {{.*}} to double + // CHECK: fpext contract float {{.*}} to double // SAFEIR: atomicrmw fsub ptr {{.*}} monotonic, align 8{{$}} // UNSAFEIR: atomicrmw fsub ptr {{.*}} monotonic, align 8, !amdgpu.no.fine.grained.memory !{{[0-9]+$}} diff --git a/clang/test/CodeGenCUDA/amdgpu-kernel-arg-pointer-type.cu b/clang/test/CodeGenCUDA/amdgpu-kernel-arg-pointer-type.cu index 838bdda825728..334b33c872bbc 100644 --- a/clang/test/CodeGenCUDA/amdgpu-kernel-arg-pointer-type.cu +++ b/clang/test/CodeGenCUDA/amdgpu-kernel-arg-pointer-type.cu @@ -331,7 +331,7 @@ struct S { // OPT-NEXT: [[ENTRY:.*:]] // OPT-NEXT: [[COERCE_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr addrspace(4) [[TMP0]], align 8, !amdgpu.noclobber [[META4:![0-9]+]] // OPT-NEXT: [[TMP1:%.*]] = addrspacecast ptr [[COERCE_SROA_0_0_COPYLOAD]] to ptr addrspace(1) -// OPT-NEXT: [[COERCE_SROA_2_0__SROA_IDX:%.*]] = getelementptr inbounds i8, ptr addrspace(4) [[TMP0]], i64 8 +// OPT-NEXT: [[COERCE_SROA_2_0__SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[TMP0]], i64 8 // OPT-NEXT: [[COERCE_SROA_2_0_COPYLOAD:%.*]] = load ptr, ptr addrspace(4) [[COERCE_SROA_2_0__SROA_IDX]], align 8, !amdgpu.noclobber [[META4]] // OPT-NEXT: [[TMP2:%.*]] = addrspacecast ptr [[COERCE_SROA_2_0_COPYLOAD]] to ptr addrspace(1) // OPT-NEXT: [[TMP3:%.*]] = load i32, ptr addrspace(1) [[TMP1]], align 4, !amdgpu.noclobber [[META4]] @@ -438,7 +438,7 @@ __global__ void kernel4(struct S s) { // OPT-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4 // OPT-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1 // OPT-NEXT: store i32 [[INC]], ptr [[TMP0]], align 4 -// OPT-NEXT: [[Y:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[S_COERCE]], i64 8 +// OPT-NEXT: [[Y:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[S_COERCE]], i64 8 // OPT-NEXT: [[TMP2:%.*]] = load ptr, ptr addrspace(1) [[Y]], align 8 // OPT-NEXT: [[TMP3:%.*]] = load float, ptr [[TMP2]], align 4 // OPT-NEXT: [[ADD:%.*]] = fadd contract float [[TMP3]], 1.000000e+00 @@ -539,7 +539,7 @@ struct T { // OPT-NEXT: [[ENTRY:.*:]] // OPT-NEXT: [[COERCE_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr addrspace(4) [[TMP0]], align 8, !amdgpu.noclobber [[META4]] // OPT-NEXT: [[TMP1:%.*]] = addrspacecast ptr [[COERCE_SROA_0_0_COPYLOAD]] to ptr addrspace(1) -// OPT-NEXT: [[COERCE_SROA_2_0__SROA_IDX:%.*]] = getelementptr inbounds i8, ptr addrspace(4) [[TMP0]], i64 8 +// OPT-NEXT: [[COERCE_SROA_2_0__SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[TMP0]], i64 8 // OPT-NEXT: [[COERCE_SROA_2_0_COPYLOAD:%.*]] = load ptr, ptr addrspace(4) [[COERCE_SROA_2_0__SROA_IDX]], align 8, !amdgpu.noclobber [[META4]] // OPT-NEXT: [[TMP2:%.*]] = addrspacecast ptr [[COERCE_SROA_2_0_COPYLOAD]] to ptr addrspace(1) // OPT-NEXT: [[TMP3:%.*]] = load float, ptr addrspace(1) [[TMP1]], align 4, !amdgpu.noclobber [[META4]] diff --git a/clang/test/CodeGenCXX/aarch64-sve-vector-init.cpp b/clang/test/CodeGenCXX/aarch64-sve-vector-init.cpp index f9068364d0dcb..bb71eb5636652 100644 --- a/clang/test/CodeGenCXX/aarch64-sve-vector-init.cpp +++ b/clang/test/CodeGenCXX/aarch64-sve-vector-init.cpp @@ -1212,3 +1212,20 @@ void test_copy_mf8x3(__clang_svmfloat8x3_t a) { void test_copy_mf8x4(__clang_svmfloat8x4_t a) { __clang_svmfloat8x4_t b{a}; } + +/// Reduced from: https://github.com/llvm/llvm-project/issues/107609 +using vec_t = __SVInt8_t; + +// CHECK-LABEL: define dso_local void @_Z20test_copy_s8_typedefu10__SVInt8_t +// CHECK-SAME: ( [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca , align 16 +// CHECK-NEXT: [[VEC:%.*]] = alloca , align 16 +// CHECK-NEXT: store [[A]], ptr [[A_ADDR]], align 16 +// CHECK-NEXT: [[TMP0:%.*]] = load , ptr [[A_ADDR]], align 16 +// CHECK-NEXT: store [[TMP0]], ptr [[VEC]], align 16 +// CHECK-NEXT: ret void +// +void test_copy_s8_typedef(__SVInt8_t a) { + vec_t vec{a}; +} diff --git a/clang/test/CodeGenCXX/auto-var-init.cpp b/clang/test/CodeGenCXX/auto-var-init.cpp index 7c323c2d368c0..94386e44573b5 100644 --- a/clang/test/CodeGenCXX/auto-var-init.cpp +++ b/clang/test/CodeGenCXX/auto-var-init.cpp @@ -1296,7 +1296,7 @@ TEST_CUSTOM(semivolatile, semivolatile, { 0x44444444, 0x44444444 }); // CHECK-NOT: !annotation // CHECK-O0: call void @{{.*}}used{{.*}}%custom) // PATTERN-O1: store i32 1145324612, ptr %custom, align 4 -// PATTERN-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds i8, ptr %custom, i64 4 +// PATTERN-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds nuw i8, ptr %custom, i64 4 // PATTERN-O1-NEXT: store i32 1145324612, ptr %[[I]], align 4 // ZERO-O1: store i64 4919131752989213764, ptr %custom, align 8 // CHECK-NOT: !annotation @@ -1338,7 +1338,7 @@ TEST_UNINIT(base, base); // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_base_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_base_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store ptr getelementptr inbounds inrange(-16, 16) (i8, ptr @_ZTV4base, i64 16), {{.*}}, align 8 +// ZERO-O1: store ptr getelementptr inbounds nuw inrange(-16, 16) (i8, ptr @_ZTV4base, i64 16), {{.*}}, align 8 // ZERO-O1-NOT: !annotation TEST_BRACES(base, base); @@ -1359,7 +1359,7 @@ TEST_UNINIT(derived, derived); // ZERO-LABEL: @test_derived_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.+}}), !annotation [[AUTO_INIT]] // ZERO-O1: store i64 0, {{.*}} align 8, !annotation [[AUTO_INIT]] -// ZERO-O1: store ptr getelementptr inbounds inrange(-16, 16) (i8, ptr @_ZTV7derived, i64 16), {{.*}} align 8 +// ZERO-O1: store ptr getelementptr inbounds nuw inrange(-16, 16) (i8, ptr @_ZTV7derived, i64 16), {{.*}} align 8 TEST_BRACES(derived, derived); // CHECK-LABEL: @test_derived_braces() @@ -1494,11 +1494,11 @@ TEST_CUSTOM(unmatchedreverse, unmatchedreverse, { .c = 42 }); // CHECK-NOT: !annotation // CHECK-O0: call void @{{.*}}used{{.*}}%custom) // PATTERN-O1: store i8 42, ptr {{.*}}, align 4 -// PATTERN-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds i8, ptr %custom, i64 1 +// PATTERN-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds nuw i8, ptr %custom, i64 1 // PATTERN-O1-NEXT: store i8 -86, ptr %[[I]], align {{.*}} -// PATTERN-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds i8, ptr %custom, i64 2 +// PATTERN-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds nuw i8, ptr %custom, i64 2 // PATTERN-O1-NEXT: store i8 -86, ptr %[[I]], align {{.*}} -// PATTERN-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds i8, ptr %custom, i64 3 +// PATTERN-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds nuw i8, ptr %custom, i64 3 // PATTERN-O1-NEXT: store i8 -86, ptr %[[I]], align {{.*}} // ZERO-O1: store i32 42, ptr {{.*}}, align 4 diff --git a/clang/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp b/clang/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp index 4b046acf0d878..a5d0d5ad6e91f 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp @@ -18,7 +18,7 @@ T* test1(V* x) { return &dynamic_cast(*x); } T* test2(A* x) { return &dynamic_cast(*x); } // CHECK-LABEL: define dso_local noundef ptr @"?test2@@YAPAUT@@PAUA@@@Z"(ptr noundef %x) // CHECK: [[VBTBL:%.*]] = load ptr, ptr %x, align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8, ptr [[VBTBL]], i32 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds nuw i8, ptr [[VBTBL]], i32 4 // CHECK-NEXT: [[VBOFFS:%.*]] = load i32, ptr [[VBOFFP]], align 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, ptr %x, i32 [[VBOFFS]] // CHECK-NEXT: [[CALL:%.*]] = tail call ptr @__RTDynamicCast(ptr nonnull [[ADJ]], i32 [[VBOFFS]], ptr nonnull @"??_R0?AUA@@@8", ptr nonnull @"??_R0?AUT@@@8", i32 1) @@ -26,9 +26,9 @@ T* test2(A* x) { return &dynamic_cast(*x); } T* test3(B* x) { return &dynamic_cast(*x); } // CHECK-LABEL: define dso_local noundef ptr @"?test3@@YAPAUT@@PAUB@@@Z"(ptr noundef %x) -// CHECK: [[VBPTR:%.*]] = getelementptr inbounds i8, ptr %x, i32 4 +// CHECK: [[VBPTR:%.*]] = getelementptr inbounds nuw i8, ptr %x, i32 4 // CHECK-NEXT: [[VBTBL:%.*]] = load ptr, ptr [[VBPTR:%.*]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8, ptr [[VBTBL]], i32 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds nuw i8, ptr [[VBTBL]], i32 4 // CHECK-NEXT: [[VBOFFS:%.*]] = load i32, ptr [[VBOFFP]], align 4 // CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, ptr %x, i32 [[DELTA]] @@ -45,7 +45,7 @@ T* test5(A* x) { return dynamic_cast(x); } // CHECK: [[CHECK:%.*]] = icmp eq ptr %x, null // CHECK-NEXT: br i1 [[CHECK]] // CHECK: [[VBTBL:%.*]] = load ptr, ptr %x, align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8, ptr [[VBTBL]], i32 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds nuw i8, ptr [[VBTBL]], i32 4 // CHECK-NEXT: [[VBOFFS:%.*]] = load i32, ptr [[VBOFFP]], align 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, ptr %x, i32 [[VBOFFS]] // CHECK-NEXT: [[CALL:%.*]] = tail call ptr @__RTDynamicCast(ptr nonnull [[ADJ]], i32 [[VBOFFS]], ptr {{.*}}@"??_R0?AUA@@@8", ptr {{.*}}@"??_R0?AUT@@@8", i32 0) @@ -57,9 +57,9 @@ T* test6(B* x) { return dynamic_cast(x); } // CHECK-LABEL: define dso_local noundef ptr @"?test6@@YAPAUT@@PAUB@@@Z"(ptr noundef %x) // CHECK: [[CHECK:%.*]] = icmp eq ptr %x, null // CHECK-NEXT: br i1 [[CHECK]] -// CHECK: [[VBPTR:%.*]] = getelementptr inbounds i8, ptr %x, i32 4 +// CHECK: [[VBPTR:%.*]] = getelementptr inbounds nuw i8, ptr %x, i32 4 // CHECK-NEXT: [[VBTBL:%.*]] = load ptr, ptr [[VBPTR]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8, ptr [[VBTBL]], i32 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds nuw i8, ptr [[VBTBL]], i32 4 // CHECK-NEXT: [[VBOFFS:%.*]] = load i32, ptr [[VBOFFP]], align 4 // CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, ptr %x, i32 [[DELTA]] @@ -78,7 +78,7 @@ void* test8(A* x) { return dynamic_cast(x); } // CHECK: [[CHECK:%.*]] = icmp eq ptr %x, null // CHECK-NEXT: br i1 [[CHECK]] // CHECK: [[VBTBL:%.*]] = load ptr, ptr %x, align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8, ptr [[VBTBL]], i32 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds nuw i8, ptr [[VBTBL]], i32 4 // CHECK-NEXT: [[VBOFFS:%.*]] = load i32, ptr [[VBOFFP]], align 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, ptr %x, i32 [[VBOFFS]] // CHECK-NEXT: [[RES:%.*]] = tail call ptr @__RTCastToVoid(ptr nonnull [[ADJ]]) @@ -90,9 +90,9 @@ void* test9(B* x) { return dynamic_cast(x); } // CHECK-LABEL: define dso_local noundef ptr @"?test9@@YAPAXPAUB@@@Z"(ptr noundef %x) // CHECK: [[CHECK:%.*]] = icmp eq ptr %x, null // CHECK-NEXT: br i1 [[CHECK]] -// CHECK: [[VBPTR:%.*]] = getelementptr inbounds i8, ptr %x, i32 4 +// CHECK: [[VBPTR:%.*]] = getelementptr inbounds nuw i8, ptr %x, i32 4 // CHECK-NEXT: [[VBTBL:%.*]] = load ptr, ptr [[VBPTR]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8, ptr [[VBTBL]], i32 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds nuw i8, ptr [[VBTBL]], i32 4 // CHECK-NEXT: [[VBOFFS:%.*]] = load i32, ptr [[VBOFFP]], align 4 // CHECK-NEXT: [[BASE:%.*]] = getelementptr i8, ptr %x, i32 [[VBOFFS]] // CHECK-NEXT: [[ADJ:%.*]] = getelementptr i8, ptr [[BASE]], i32 4 diff --git a/clang/test/CodeGenCXX/microsoft-abi-typeid.cpp b/clang/test/CodeGenCXX/microsoft-abi-typeid.cpp index 31d7d23fd6fc5..24a19cd856602 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-typeid.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-typeid.cpp @@ -31,7 +31,7 @@ const std::type_info* test3_typeid() { return &typeid(*fn()); } // CHECK: call ptr @__RTtypeid(ptr null) // CHECK-NEXT: unreachable // CHECK: [[VBTBL:%.*]] = load ptr, ptr [[CALL]], align 4 -// CHECK-NEXT: [[VBSLOT:%.*]] = getelementptr inbounds i8, ptr [[VBTBL]], i32 4 +// CHECK-NEXT: [[VBSLOT:%.*]] = getelementptr inbounds nuw i8, ptr [[VBTBL]], i32 4 // CHECK-NEXT: [[VBASE_OFFS:%.*]] = load i32, ptr [[VBSLOT]], align 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i32 [[VBASE_OFFS]] // CHECK-NEXT: [[RT:%.*]] = tail call ptr @__RTtypeid(ptr nonnull [[ADJ]]) diff --git a/clang/test/CodeGenCXX/template-instantiation.cpp b/clang/test/CodeGenCXX/template-instantiation.cpp index 15d409447c117..8453bcefc7ebb 100644 --- a/clang/test/CodeGenCXX/template-instantiation.cpp +++ b/clang/test/CodeGenCXX/template-instantiation.cpp @@ -17,6 +17,7 @@ // CHECK2-NOT: _ZTVN5test31SIiEE // CHECK2-NOT: _ZTSN5test31SIiEE +// CHECK2: !{!"p1 _ZTSN5test31SIiEE", // CHECK-LABEL: define linkonce_odr void @_ZN5test21CIiEC1Ev(ptr {{[^,]*}} %this) unnamed_addr // CHECK-LABEL: define linkonce_odr void @_ZN5test21CIiE6foobarIdEEvT_( diff --git a/clang/test/CodeGenHIP/printf_nonhostcall.cpp b/clang/test/CodeGenHIP/printf_nonhostcall.cpp index 2c6d0ecac1e8a..1982eb864e2a4 100644 --- a/clang/test/CodeGenHIP/printf_nonhostcall.cpp +++ b/clang/test/CodeGenHIP/printf_nonhostcall.cpp @@ -263,7 +263,7 @@ __device__ _BitInt(128) Int128 = 45637; // CHECK-NEXT: [[CONV:%.*]] = zext i16 [[TMP1]] to i32 // CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr addrspacecast (ptr addrspace(1) @n to ptr), align 8 // CHECK-NEXT: [[TMP3:%.*]] = load float, ptr addrspacecast (ptr addrspace(1) @f1 to ptr), align 4 -// CHECK-NEXT: [[CONV1:%.*]] = fpext float [[TMP3]] to double +// CHECK-NEXT: [[CONV1:%.*]] = fpext contract float [[TMP3]] to double // CHECK-NEXT: [[TMP4:%.*]] = load double, ptr addrspacecast (ptr addrspace(1) @f2 to ptr), align 8 // CHECK-NEXT: [[TMP5:%.*]] = load half, ptr addrspacecast (ptr addrspace(1) @f3 to ptr), align 2 // CHECK-NEXT: [[TMP6:%.*]] = load bfloat, ptr addrspacecast (ptr addrspace(1) @f4 to ptr), align 2 @@ -324,7 +324,7 @@ __device__ _BitInt(128) Int128 = 45637; // CHECK_CONSTRAINED-NEXT: [[CONV:%.*]] = zext i16 [[TMP1]] to i32 // CHECK_CONSTRAINED-NEXT: [[TMP2:%.*]] = load i64, ptr addrspacecast (ptr addrspace(1) @n to ptr), align 8 // CHECK_CONSTRAINED-NEXT: [[TMP3:%.*]] = load float, ptr addrspacecast (ptr addrspace(1) @f1 to ptr), align 4 -// CHECK_CONSTRAINED-NEXT: [[CONV1:%.*]] = fpext float [[TMP3]] to double +// CHECK_CONSTRAINED-NEXT: [[CONV1:%.*]] = fpext contract float [[TMP3]] to double // CHECK_CONSTRAINED-NEXT: [[TMP4:%.*]] = load double, ptr addrspacecast (ptr addrspace(1) @f2 to ptr), align 8 // CHECK_CONSTRAINED-NEXT: [[TMP5:%.*]] = load half, ptr addrspacecast (ptr addrspace(1) @f3 to ptr), align 2 // CHECK_CONSTRAINED-NEXT: [[TMP6:%.*]] = load bfloat, ptr addrspacecast (ptr addrspace(1) @f4 to ptr), align 2 diff --git a/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl new file mode 100644 index 0000000000000..45e135427ba9c --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL +// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV + +// NOTE: SPIRV codegen for resource types is not yet implemented + +ByteAddressBuffer Buffer0: register(t0); +RWByteAddressBuffer Buffer1: register(u1, space2); +RasterizerOrderedByteAddressBuffer Buffer2: register(u3, space4); + +// CHECK: "class.hlsl::ByteAddressBuffer" = type { target("dx.RawBuffer", i8, 0, 0) } +// CHECK: "class.hlsl::RWByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 0) } +// CHECK: "class.hlsl::RasterizerOrderedByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 1) } + +// CHECK: @Buffer0 = global %"class.hlsl::ByteAddressBuffer" zeroinitializer, align 4 +// CHECK: @Buffer1 = global %"class.hlsl::RWByteAddressBuffer" zeroinitializer, align 4 +// CHECK: @Buffer2 = global %"class.hlsl::RasterizerOrderedByteAddressBuffer" zeroinitializer, align 4 + +// CHECK: define internal void @_GLOBAL__sub_I_ByteAddressBuffers_constructors.hlsl() +// CHECK: entry: +// CHECK: call void @_init_resource_bindings() + +// CHECK: define internal void @_init_resource_bindings() { +// CHECK-NEXT: entry: +// CHECK-DXIL-NEXT: %Buffer0_h = call target("dx.RawBuffer", i8, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 0, 0) %Buffer0_h, ptr @Buffer0, align 4 +// CHECK-DXIL-NEXT: %Buffer1_h = call target("dx.RawBuffer", i8, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_1_0t(i32 2, i32 1, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 1, 0) %Buffer1_h, ptr @Buffer1, align 4 +// CHECK-DXIL-NEXT: %Buffer2_h = call target("dx.RawBuffer", i8, 1, 1) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_1_1t(i32 4, i32 3, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 1, 1) %Buffer2_h, ptr @Buffer2, align 4 diff --git a/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl b/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl index 62b5661da9dbd..5599f4dd50f04 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl @@ -427,7 +427,7 @@ kernel void test_target_features_kernel(global int *i) { // // GFX900: Function Attrs: convergent norecurse nounwind // GFX900-LABEL: define {{[^@]+}}@test -// GFX900-SAME: (ptr addrspace(1) noundef align 1 [[A:%.*]], i8 noundef [[B:%.*]], ptr addrspace(1) noundef align 8 [[C:%.*]], i64 noundef [[D:%.*]]) #[[ATTR2:[0-9]+]] !kernel_arg_addr_space [[META9:![0-9]+]] !kernel_arg_access_qual [[META10:![0-9]+]] !kernel_arg_type [[META11:![0-9]+]] !kernel_arg_base_type [[META11]] !kernel_arg_type_qual [[META12:![0-9]+]] { +// GFX900-SAME: (ptr addrspace(1) noundef align 1 [[A:%.*]], i8 noundef [[B:%.*]], ptr addrspace(1) noundef align 8 [[C:%.*]], i64 noundef [[D:%.*]]) #[[ATTR2:[0-9]+]] !kernel_arg_addr_space [[META10:![0-9]+]] !kernel_arg_access_qual [[META11:![0-9]+]] !kernel_arg_type [[META12:![0-9]+]] !kernel_arg_base_type [[META12]] !kernel_arg_type_qual [[META13:![0-9]+]] { // GFX900-NEXT: entry: // GFX900-NEXT: [[A_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) // GFX900-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1, addrspace(5) @@ -463,17 +463,17 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[BLOCK20_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK20]] to ptr // GFX900-NEXT: [[BLOCK21_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK21]] to ptr // GFX900-NEXT: [[TMP27_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[VARTMP27]] to ptr -// GFX900-NEXT: store ptr addrspace(1) [[A]], ptr [[A_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: store i8 [[B]], ptr [[B_ADDR_ASCAST]], align 1, !tbaa [[TBAA13:![0-9]+]] +// GFX900-NEXT: store ptr addrspace(1) [[A]], ptr [[A_ADDR_ASCAST]], align 8, !tbaa [[TBAA14:![0-9]+]] +// GFX900-NEXT: store i8 [[B]], ptr [[B_ADDR_ASCAST]], align 1, !tbaa [[TBAA16:![0-9]+]] // GFX900-NEXT: store ptr addrspace(1) [[C]], ptr [[C_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] // GFX900-NEXT: store i64 [[D]], ptr [[D_ADDR_ASCAST]], align 8, !tbaa [[TBAA3]] // GFX900-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[DEFAULT_QUEUE]]) #[[ATTR8:[0-9]+]] // GFX900-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[FLAGS]]) #[[ATTR8]] -// GFX900-NEXT: store i32 0, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14:![0-9]+]] +// GFX900-NEXT: store i32 0, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA17:![0-9]+]] // GFX900-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[NDRANGE]]) #[[ATTR8]] -// GFX900-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA16:![0-9]+]] -// GFX900-NEXT: [[TMP1:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] -// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18:![0-9]+]] +// GFX900-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA19:![0-9]+]] +// GFX900-NEXT: [[TMP1:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA17]] +// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT21:![0-9]+]] // GFX900-NEXT: [[BLOCK_SIZE:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 0 // GFX900-NEXT: store i32 25, ptr [[BLOCK_SIZE]], align 8 // GFX900-NEXT: [[BLOCK_ALIGN:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 1 @@ -481,15 +481,15 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[BLOCK_INVOKE:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 2 // GFX900-NEXT: store ptr @__test_block_invoke, ptr [[BLOCK_INVOKE]], align 8 // GFX900-NEXT: [[BLOCK_CAPTURED:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 3 -// GFX900-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr [[A_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: store ptr addrspace(1) [[TMP2]], ptr [[BLOCK_CAPTURED]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr [[A_ADDR_ASCAST]], align 8, !tbaa [[TBAA14]] +// GFX900-NEXT: store ptr addrspace(1) [[TMP2]], ptr [[BLOCK_CAPTURED]], align 8, !tbaa [[TBAA14]] // GFX900-NEXT: [[BLOCK_CAPTURED1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 4 -// GFX900-NEXT: [[TMP3:%.*]] = load i8, ptr [[B_ADDR_ASCAST]], align 1, !tbaa [[TBAA13]] -// GFX900-NEXT: store i8 [[TMP3]], ptr [[BLOCK_CAPTURED1]], align 8, !tbaa [[TBAA13]] +// GFX900-NEXT: [[TMP3:%.*]] = load i8, ptr [[B_ADDR_ASCAST]], align 1, !tbaa [[TBAA16]] +// GFX900-NEXT: store i8 [[TMP3]], ptr [[BLOCK_CAPTURED1]], align 8, !tbaa [[TBAA16]] // GFX900-NEXT: [[TMP4:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP0]], i32 [[TMP1]], ptr [[TMP_ASCAST]], ptr @__test_block_invoke_kernel, ptr [[BLOCK_ASCAST]]) -// GFX900-NEXT: [[TMP5:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA16]] -// GFX900-NEXT: [[TMP6:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] -// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP2_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] +// GFX900-NEXT: [[TMP5:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA19]] +// GFX900-NEXT: [[TMP6:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA17]] +// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP2_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT21]] // GFX900-NEXT: [[BLOCK_SIZE4:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 0 // GFX900-NEXT: store i32 41, ptr [[BLOCK_SIZE4]], align 8 // GFX900-NEXT: [[BLOCK_ALIGN5:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 1 @@ -497,11 +497,11 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[BLOCK_INVOKE6:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 2 // GFX900-NEXT: store ptr @__test_block_invoke_2, ptr [[BLOCK_INVOKE6]], align 8 // GFX900-NEXT: [[BLOCK_CAPTURED7:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 3 -// GFX900-NEXT: [[TMP7:%.*]] = load ptr addrspace(1), ptr [[A_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: store ptr addrspace(1) [[TMP7]], ptr [[BLOCK_CAPTURED7]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: [[TMP7:%.*]] = load ptr addrspace(1), ptr [[A_ADDR_ASCAST]], align 8, !tbaa [[TBAA14]] +// GFX900-NEXT: store ptr addrspace(1) [[TMP7]], ptr [[BLOCK_CAPTURED7]], align 8, !tbaa [[TBAA14]] // GFX900-NEXT: [[BLOCK_CAPTURED8:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 6 -// GFX900-NEXT: [[TMP8:%.*]] = load i8, ptr [[B_ADDR_ASCAST]], align 1, !tbaa [[TBAA13]] -// GFX900-NEXT: store i8 [[TMP8]], ptr [[BLOCK_CAPTURED8]], align 8, !tbaa [[TBAA13]] +// GFX900-NEXT: [[TMP8:%.*]] = load i8, ptr [[B_ADDR_ASCAST]], align 1, !tbaa [[TBAA16]] +// GFX900-NEXT: store i8 [[TMP8]], ptr [[BLOCK_CAPTURED8]], align 8, !tbaa [[TBAA16]] // GFX900-NEXT: [[BLOCK_CAPTURED9:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 4 // GFX900-NEXT: [[TMP9:%.*]] = load ptr addrspace(1), ptr [[C_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] // GFX900-NEXT: store ptr addrspace(1) [[TMP9]], ptr [[BLOCK_CAPTURED9]], align 8, !tbaa [[TBAA7]] @@ -509,9 +509,9 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[TMP10:%.*]] = load i64, ptr [[D_ADDR_ASCAST]], align 8, !tbaa [[TBAA3]] // GFX900-NEXT: store i64 [[TMP10]], ptr [[BLOCK_CAPTURED10]], align 8, !tbaa [[TBAA3]] // GFX900-NEXT: [[TMP11:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP5]], i32 [[TMP6]], ptr [[TMP2_ASCAST]], ptr @__test_block_invoke_2_kernel, ptr [[BLOCK3_ASCAST]]) -// GFX900-NEXT: [[TMP12:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA16]] -// GFX900-NEXT: [[TMP13:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] -// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP11_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] +// GFX900-NEXT: [[TMP12:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA19]] +// GFX900-NEXT: [[TMP13:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA17]] +// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP11_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT21]] // GFX900-NEXT: [[BLOCK_SIZE13:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 0 // GFX900-NEXT: store i32 41, ptr [[BLOCK_SIZE13]], align 8 // GFX900-NEXT: [[BLOCK_ALIGN14:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 1 @@ -519,11 +519,11 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[BLOCK_INVOKE15:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 2 // GFX900-NEXT: store ptr @__test_block_invoke_3, ptr [[BLOCK_INVOKE15]], align 8 // GFX900-NEXT: [[BLOCK_CAPTURED16:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 3 -// GFX900-NEXT: [[TMP14:%.*]] = load ptr addrspace(1), ptr [[A_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: store ptr addrspace(1) [[TMP14]], ptr [[BLOCK_CAPTURED16]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: [[TMP14:%.*]] = load ptr addrspace(1), ptr [[A_ADDR_ASCAST]], align 8, !tbaa [[TBAA14]] +// GFX900-NEXT: store ptr addrspace(1) [[TMP14]], ptr [[BLOCK_CAPTURED16]], align 8, !tbaa [[TBAA14]] // GFX900-NEXT: [[BLOCK_CAPTURED17:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 6 -// GFX900-NEXT: [[TMP15:%.*]] = load i8, ptr [[B_ADDR_ASCAST]], align 1, !tbaa [[TBAA13]] -// GFX900-NEXT: store i8 [[TMP15]], ptr [[BLOCK_CAPTURED17]], align 8, !tbaa [[TBAA13]] +// GFX900-NEXT: [[TMP15:%.*]] = load i8, ptr [[B_ADDR_ASCAST]], align 1, !tbaa [[TBAA16]] +// GFX900-NEXT: store i8 [[TMP15]], ptr [[BLOCK_CAPTURED17]], align 8, !tbaa [[TBAA16]] // GFX900-NEXT: [[BLOCK_CAPTURED18:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 4 // GFX900-NEXT: [[TMP16:%.*]] = load ptr addrspace(1), ptr [[C_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] // GFX900-NEXT: store ptr addrspace(1) [[TMP16]], ptr [[BLOCK_CAPTURED18]], align 8, !tbaa [[TBAA7]] @@ -548,11 +548,11 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[BLOCK_CAPTURED26:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[BLOCK21_ASCAST]], i32 0, i32 4 // GFX900-NEXT: [[TMP21:%.*]] = load ptr addrspace(1), ptr [[C_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] // GFX900-NEXT: store ptr addrspace(1) [[TMP21]], ptr [[BLOCK_CAPTURED26]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: store ptr [[BLOCK21_ASCAST]], ptr [[BLOCK20_ASCAST]], align 8, !tbaa [[TBAA13]] -// GFX900-NEXT: [[TMP22:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA16]] -// GFX900-NEXT: [[TMP23:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] -// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP27_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] -// GFX900-NEXT: [[TMP24:%.*]] = load ptr, ptr [[BLOCK20_ASCAST]], align 8, !tbaa [[TBAA13]] +// GFX900-NEXT: store ptr [[BLOCK21_ASCAST]], ptr [[BLOCK20_ASCAST]], align 8, !tbaa [[TBAA16]] +// GFX900-NEXT: [[TMP22:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA19]] +// GFX900-NEXT: [[TMP23:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA17]] +// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP27_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT21]] +// GFX900-NEXT: [[TMP24:%.*]] = load ptr, ptr [[BLOCK20_ASCAST]], align 8, !tbaa [[TBAA16]] // GFX900-NEXT: [[TMP25:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP22]], i32 [[TMP23]], ptr [[TMP27_ASCAST]], ptr @__test_block_invoke_4_kernel, ptr [[BLOCK21_ASCAST]]) // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[BLOCK20]]) #[[ATTR8]] // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[NDRANGE]]) #[[ATTR8]] @@ -569,17 +569,17 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]] to ptr // GFX900-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST]], align 8 // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 4 -// GFX900-NEXT: [[TMP0:%.*]] = load i8, ptr [[BLOCK_CAPTURE_ADDR]], align 8, !tbaa [[TBAA13]] +// GFX900-NEXT: [[TMP0:%.*]] = load i8, ptr [[BLOCK_CAPTURE_ADDR]], align 8, !tbaa [[TBAA16]] // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 3 -// GFX900-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[BLOCK_CAPTURE_ADDR1]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[BLOCK_CAPTURE_ADDR1]], align 8, !tbaa [[TBAA14]] // GFX900-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[TMP1]], i64 0 -// GFX900-NEXT: store i8 [[TMP0]], ptr addrspace(1) [[ARRAYIDX]], align 1, !tbaa [[TBAA13]] +// GFX900-NEXT: store i8 [[TMP0]], ptr addrspace(1) [[ARRAYIDX]], align 1, !tbaa [[TBAA16]] // GFX900-NEXT: ret void // // // GFX900: Function Attrs: convergent nounwind // GFX900-LABEL: define {{[^@]+}}@__test_block_invoke_kernel -// GFX900-SAME: (<{ i32, i32, ptr, ptr addrspace(1), i8 }> [[TMP0:%.*]]) #[[ATTR6:[0-9]+]] !kernel_arg_addr_space [[META19:![0-9]+]] !kernel_arg_access_qual [[META20:![0-9]+]] !kernel_arg_type [[META21:![0-9]+]] !kernel_arg_base_type [[META21]] !kernel_arg_type_qual [[META22:![0-9]+]] { +// GFX900-SAME: (<{ i32, i32, ptr, ptr addrspace(1), i8 }> [[TMP0:%.*]]) #[[ATTR6:[0-9]+]] !kernel_arg_addr_space [[META22:![0-9]+]] !kernel_arg_access_qual [[META23:![0-9]+]] !kernel_arg_type [[META24:![0-9]+]] !kernel_arg_base_type [[META24]] !kernel_arg_type_qual [[META25:![0-9]+]] { // GFX900-NEXT: entry: // GFX900-NEXT: [[TMP1:%.*]] = alloca <{ i32, i32, ptr, ptr addrspace(1), i8 }>, align 8, addrspace(5) // GFX900-NEXT: store <{ i32, i32, ptr, ptr addrspace(1), i8 }> [[TMP0]], ptr addrspace(5) [[TMP1]], align 8 @@ -596,11 +596,11 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]] to ptr // GFX900-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST]], align 8 // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 6 -// GFX900-NEXT: [[TMP0:%.*]] = load i8, ptr [[BLOCK_CAPTURE_ADDR]], align 8, !tbaa [[TBAA13]] +// GFX900-NEXT: [[TMP0:%.*]] = load i8, ptr [[BLOCK_CAPTURE_ADDR]], align 8, !tbaa [[TBAA16]] // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 3 -// GFX900-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[BLOCK_CAPTURE_ADDR1]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[BLOCK_CAPTURE_ADDR1]], align 8, !tbaa [[TBAA14]] // GFX900-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[TMP1]], i64 0 -// GFX900-NEXT: store i8 [[TMP0]], ptr addrspace(1) [[ARRAYIDX]], align 1, !tbaa [[TBAA13]] +// GFX900-NEXT: store i8 [[TMP0]], ptr addrspace(1) [[ARRAYIDX]], align 1, !tbaa [[TBAA16]] // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR2:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 5 // GFX900-NEXT: [[TMP2:%.*]] = load i64, ptr [[BLOCK_CAPTURE_ADDR2]], align 8, !tbaa [[TBAA3]] // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR3:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 4 @@ -612,7 +612,7 @@ kernel void test_target_features_kernel(global int *i) { // // GFX900: Function Attrs: convergent nounwind // GFX900-LABEL: define {{[^@]+}}@__test_block_invoke_2_kernel -// GFX900-SAME: (<{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }> [[TMP0:%.*]]) #[[ATTR6]] !kernel_arg_addr_space [[META19]] !kernel_arg_access_qual [[META20]] !kernel_arg_type [[META21]] !kernel_arg_base_type [[META21]] !kernel_arg_type_qual [[META22]] { +// GFX900-SAME: (<{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }> [[TMP0:%.*]]) #[[ATTR6]] !kernel_arg_addr_space [[META22]] !kernel_arg_access_qual [[META23]] !kernel_arg_type [[META24]] !kernel_arg_base_type [[META24]] !kernel_arg_type_qual [[META25]] { // GFX900-NEXT: entry: // GFX900-NEXT: [[TMP1:%.*]] = alloca <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, align 8, addrspace(5) // GFX900-NEXT: store <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }> [[TMP0]], ptr addrspace(5) [[TMP1]], align 8 @@ -630,28 +630,28 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]] to ptr // GFX900-NEXT: [[LP_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[LP_ADDR]] to ptr // GFX900-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST]], align 8 -// GFX900-NEXT: store ptr addrspace(3) [[LP]], ptr [[LP_ADDR_ASCAST]], align 4, !tbaa [[TBAA7]] +// GFX900-NEXT: store ptr addrspace(3) [[LP]], ptr [[LP_ADDR_ASCAST]], align 4, !tbaa [[TBAA26:![0-9]+]] // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 6 -// GFX900-NEXT: [[TMP0:%.*]] = load i8, ptr [[BLOCK_CAPTURE_ADDR]], align 8, !tbaa [[TBAA13]] +// GFX900-NEXT: [[TMP0:%.*]] = load i8, ptr [[BLOCK_CAPTURE_ADDR]], align 8, !tbaa [[TBAA16]] // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 3 -// GFX900-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[BLOCK_CAPTURE_ADDR1]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[BLOCK_CAPTURE_ADDR1]], align 8, !tbaa [[TBAA14]] // GFX900-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[TMP1]], i64 0 -// GFX900-NEXT: store i8 [[TMP0]], ptr addrspace(1) [[ARRAYIDX]], align 1, !tbaa [[TBAA13]] +// GFX900-NEXT: store i8 [[TMP0]], ptr addrspace(1) [[ARRAYIDX]], align 1, !tbaa [[TBAA16]] // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR2:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 5 // GFX900-NEXT: [[TMP2:%.*]] = load i64, ptr [[BLOCK_CAPTURE_ADDR2]], align 8, !tbaa [[TBAA3]] // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR3:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 4 // GFX900-NEXT: [[TMP3:%.*]] = load ptr addrspace(1), ptr [[BLOCK_CAPTURE_ADDR3]], align 8, !tbaa [[TBAA7]] // GFX900-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds i64, ptr addrspace(1) [[TMP3]], i64 0 // GFX900-NEXT: store i64 [[TMP2]], ptr addrspace(1) [[ARRAYIDX4]], align 8, !tbaa [[TBAA3]] -// GFX900-NEXT: [[TMP4:%.*]] = load ptr addrspace(3), ptr [[LP_ADDR_ASCAST]], align 4, !tbaa [[TBAA7]] +// GFX900-NEXT: [[TMP4:%.*]] = load ptr addrspace(3), ptr [[LP_ADDR_ASCAST]], align 4, !tbaa [[TBAA26]] // GFX900-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, ptr addrspace(3) [[TMP4]], i64 0 -// GFX900-NEXT: store i32 1, ptr addrspace(3) [[ARRAYIDX5]], align 4, !tbaa [[TBAA14]] +// GFX900-NEXT: store i32 1, ptr addrspace(3) [[ARRAYIDX5]], align 4, !tbaa [[TBAA17]] // GFX900-NEXT: ret void // // // GFX900: Function Attrs: convergent nounwind // GFX900-LABEL: define {{[^@]+}}@__test_block_invoke_3_kernel -// GFX900-SAME: (<{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }> [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) #[[ATTR6]] !kernel_arg_addr_space [[META23:![0-9]+]] !kernel_arg_access_qual [[META24:![0-9]+]] !kernel_arg_type [[META25:![0-9]+]] !kernel_arg_base_type [[META25]] !kernel_arg_type_qual [[META26:![0-9]+]] { +// GFX900-SAME: (<{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }> [[TMP0:%.*]], ptr addrspace(3) [[TMP1:%.*]]) #[[ATTR6]] !kernel_arg_addr_space [[META28:![0-9]+]] !kernel_arg_access_qual [[META29:![0-9]+]] !kernel_arg_type [[META30:![0-9]+]] !kernel_arg_base_type [[META30]] !kernel_arg_type_qual [[META31:![0-9]+]] { // GFX900-NEXT: entry: // GFX900-NEXT: [[TMP2:%.*]] = alloca <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, align 8, addrspace(5) // GFX900-NEXT: store <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }> [[TMP0]], ptr addrspace(5) [[TMP2]], align 8 @@ -677,7 +677,7 @@ kernel void test_target_features_kernel(global int *i) { // // GFX900: Function Attrs: convergent nounwind // GFX900-LABEL: define {{[^@]+}}@__test_block_invoke_4_kernel -// GFX900-SAME: (<{ i32, i32, ptr, i64, ptr addrspace(1) }> [[TMP0:%.*]]) #[[ATTR6]] !kernel_arg_addr_space [[META19]] !kernel_arg_access_qual [[META20]] !kernel_arg_type [[META21]] !kernel_arg_base_type [[META21]] !kernel_arg_type_qual [[META22]] { +// GFX900-SAME: (<{ i32, i32, ptr, i64, ptr addrspace(1) }> [[TMP0:%.*]]) #[[ATTR6]] !kernel_arg_addr_space [[META22]] !kernel_arg_access_qual [[META23]] !kernel_arg_type [[META24]] !kernel_arg_base_type [[META24]] !kernel_arg_type_qual [[META25]] { // GFX900-NEXT: entry: // GFX900-NEXT: [[TMP1:%.*]] = alloca <{ i32, i32, ptr, i64, ptr addrspace(1) }>, align 8, addrspace(5) // GFX900-NEXT: store <{ i32, i32, ptr, i64, ptr addrspace(1) }> [[TMP0]], ptr addrspace(5) [[TMP1]], align 8 @@ -688,7 +688,7 @@ kernel void test_target_features_kernel(global int *i) { // // GFX900: Function Attrs: convergent norecurse nounwind // GFX900-LABEL: define {{[^@]+}}@test_target_features_kernel -// GFX900-SAME: (ptr addrspace(1) noundef align 4 [[I:%.*]]) #[[ATTR2]] !kernel_arg_addr_space [[META27:![0-9]+]] !kernel_arg_access_qual [[META20]] !kernel_arg_type [[META28:![0-9]+]] !kernel_arg_base_type [[META28]] !kernel_arg_type_qual [[META22]] { +// GFX900-SAME: (ptr addrspace(1) noundef align 4 [[I:%.*]]) #[[ATTR2]] !kernel_arg_addr_space [[META32:![0-9]+]] !kernel_arg_access_qual [[META23]] !kernel_arg_type [[META33:![0-9]+]] !kernel_arg_base_type [[META33]] !kernel_arg_type_qual [[META25]] { // GFX900-NEXT: entry: // GFX900-NEXT: [[I_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) // GFX900-NEXT: [[DEFAULT_QUEUE:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) @@ -700,15 +700,15 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[FLAGS_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FLAGS]] to ptr // GFX900-NEXT: [[NDRANGE_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[NDRANGE]] to ptr // GFX900-NEXT: [[TMP_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[TMP]] to ptr -// GFX900-NEXT: store ptr addrspace(1) [[I]], ptr [[I_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: store ptr addrspace(1) [[I]], ptr [[I_ADDR_ASCAST]], align 8, !tbaa [[TBAA34:![0-9]+]] // GFX900-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[DEFAULT_QUEUE]]) #[[ATTR8]] // GFX900-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[FLAGS]]) #[[ATTR8]] -// GFX900-NEXT: store i32 0, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] +// GFX900-NEXT: store i32 0, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA17]] // GFX900-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[NDRANGE]]) #[[ATTR8]] // GFX900-NEXT: [[TMP0:%.*]] = call i64 @llvm.amdgcn.s.memtime() -// GFX900-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA16]] -// GFX900-NEXT: [[TMP2:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] -// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] +// GFX900-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA19]] +// GFX900-NEXT: [[TMP2:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA17]] +// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT21]] // GFX900-NEXT: [[TMP3:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP1]], i32 [[TMP2]], ptr [[TMP_ASCAST]], ptr @__test_target_features_kernel_block_invoke_kernel, ptr addrspacecast (ptr addrspace(1) @__block_literal_global to ptr)) // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[NDRANGE]]) #[[ATTR8]] // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[FLAGS]]) #[[ATTR8]] @@ -729,7 +729,7 @@ kernel void test_target_features_kernel(global int *i) { // // GFX900: Function Attrs: convergent nounwind // GFX900-LABEL: define {{[^@]+}}@__test_target_features_kernel_block_invoke_kernel -// GFX900-SAME: ({ i32, i32, ptr } [[TMP0:%.*]]) #[[ATTR6]] !kernel_arg_addr_space [[META19]] !kernel_arg_access_qual [[META20]] !kernel_arg_type [[META21]] !kernel_arg_base_type [[META21]] !kernel_arg_type_qual [[META22]] { +// GFX900-SAME: ({ i32, i32, ptr } [[TMP0:%.*]]) #[[ATTR6]] !kernel_arg_addr_space [[META22]] !kernel_arg_access_qual [[META23]] !kernel_arg_type [[META24]] !kernel_arg_base_type [[META24]] !kernel_arg_type_qual [[META25]] { // GFX900-NEXT: entry: // GFX900-NEXT: [[TMP1:%.*]] = alloca { i32, i32, ptr }, align 8, addrspace(5) // GFX900-NEXT: store { i32, i32, ptr } [[TMP0]], ptr addrspace(5) [[TMP1]], align 8 @@ -785,27 +785,34 @@ kernel void test_target_features_kernel(global int *i) { // GFX900: [[META5]] = !{!"omnipotent char", [[META6:![0-9]+]], i64 0} // GFX900: [[META6]] = !{!"Simple C/C++ TBAA"} // GFX900: [[TBAA7]] = !{[[META8:![0-9]+]], [[META8]], i64 0} -// GFX900: [[META8]] = !{!"any pointer", [[META5]], i64 0} -// GFX900: [[META9]] = !{i32 1, i32 0, i32 1, i32 0} -// GFX900: [[META10]] = !{!"none", !"none", !"none", !"none"} -// GFX900: [[META11]] = !{!"char*", !"char", !"long*", !"long"} -// GFX900: [[META12]] = !{!"", !"", !"", !""} -// GFX900: [[TBAA13]] = !{[[META5]], [[META5]], i64 0} +// GFX900: [[META8]] = !{!"p1 long", [[META9:![0-9]+]], i64 0} +// GFX900: [[META9]] = !{!"any pointer", [[META5]], i64 0} +// GFX900: [[META10]] = !{i32 1, i32 0, i32 1, i32 0} +// GFX900: [[META11]] = !{!"none", !"none", !"none", !"none"} +// GFX900: [[META12]] = !{!"char*", !"char", !"long*", !"long"} +// GFX900: [[META13]] = !{!"", !"", !"", !""} // GFX900: [[TBAA14]] = !{[[META15:![0-9]+]], [[META15]], i64 0} -// GFX900: [[META15]] = !{!"int", [[META5]], i64 0} -// GFX900: [[TBAA16]] = !{[[META17:![0-9]+]], [[META17]], i64 0} -// GFX900: [[META17]] = !{!"queue_t", [[META5]], i64 0} -// GFX900: [[TBAA_STRUCT18]] = !{i64 0, i64 4, [[TBAA14]]} -// GFX900: [[META19]] = !{i32 0} -// GFX900: [[META20]] = !{!"none"} -// GFX900: [[META21]] = !{!"__block_literal"} -// GFX900: [[META22]] = !{!""} -// GFX900: [[META23]] = !{i32 0, i32 3} -// GFX900: [[META24]] = !{!"none", !"none"} -// GFX900: [[META25]] = !{!"__block_literal", !"void*"} -// GFX900: [[META26]] = !{!"", !""} -// GFX900: [[META27]] = !{i32 1} -// GFX900: [[META28]] = !{!"int*"} +// GFX900: [[META15]] = !{!"p1 omnipotent char", [[META9]], i64 0} +// GFX900: [[TBAA16]] = !{[[META5]], [[META5]], i64 0} +// GFX900: [[TBAA17]] = !{[[META18:![0-9]+]], [[META18]], i64 0} +// GFX900: [[META18]] = !{!"int", [[META5]], i64 0} +// GFX900: [[TBAA19]] = !{[[META20:![0-9]+]], [[META20]], i64 0} +// GFX900: [[META20]] = !{!"queue_t", [[META5]], i64 0} +// GFX900: [[TBAA_STRUCT21]] = !{i64 0, i64 4, [[TBAA17]]} +// GFX900: [[META22]] = !{i32 0} +// GFX900: [[META23]] = !{!"none"} +// GFX900: [[META24]] = !{!"__block_literal"} +// GFX900: [[META25]] = !{!""} +// GFX900: [[TBAA26]] = !{[[META27:![0-9]+]], [[META27]], i64 0} +// GFX900: [[META27]] = !{!"p1 void", [[META9]], i64 0} +// GFX900: [[META28]] = !{i32 0, i32 3} +// GFX900: [[META29]] = !{!"none", !"none"} +// GFX900: [[META30]] = !{!"__block_literal", !"void*"} +// GFX900: [[META31]] = !{!"", !""} +// GFX900: [[META32]] = !{i32 1} +// GFX900: [[META33]] = !{!"int*"} +// GFX900: [[TBAA34]] = !{[[META35:![0-9]+]], [[META35]], i64 0} +// GFX900: [[META35]] = !{!"p1 int", [[META9]], i64 0} //. //// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: // CHECK: {{.*}} diff --git a/clang/test/CodeGenOpenCL/amdgpu-nullptr.cl b/clang/test/CodeGenOpenCL/amdgpu-nullptr.cl index 53cca49e87ef4..a0c106bca83c9 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-nullptr.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-nullptr.cl @@ -513,9 +513,9 @@ typedef struct { // CHECK-LABEL: test_memset_private // CHECK: call void @llvm.memset.p5.i64(ptr addrspace(5) noundef align 8 {{.*}}, i8 0, i64 32, i1 false) -// CHECK: [[GEP:%.*]] = getelementptr inbounds i8, ptr addrspace(5) %ptr, i32 32 +// CHECK: [[GEP:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(5) %ptr, i32 32 // CHECK: store ptr addrspace(5) addrspacecast (ptr null to ptr addrspace(5)), ptr addrspace(5) [[GEP]] -// CHECK: [[GEP1:%.*]] = getelementptr inbounds i8, ptr addrspace(5) {{.*}}, i32 36 +// CHECK: [[GEP1:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(5) {{.*}}, i32 36 // CHECK: store i32 0, ptr addrspace(5) [[GEP1]], align 4 void test_memset_private(private StructTy3 *ptr) { StructTy3 S3 = {0, 0, 0, 0, 0}; diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx950.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx950.cl index f1259ef678f1e..8251d6c213e3d 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx950.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx950.cl @@ -1673,7 +1673,7 @@ void test_cvt_scalef32_sr_fp8_f32(global unsigned *out, float src, uint seed, fl // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[A_ADDR]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(5) [[B_ADDR]], align 4 // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(5) [[C_ADDR]], align 4 -// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.amdgcn.bitop3.i32(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i8 1) +// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.amdgcn.bitop3.i32(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 1) // CHECK-NEXT: [[TMP4:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[OUT_ADDR]], align 8 // CHECK-NEXT: store i32 [[TMP3]], ptr addrspace(1) [[TMP4]], align 4 // CHECK-NEXT: ret void @@ -1696,7 +1696,7 @@ void test_bitop3_b32(global uint* out, uint a, uint b, uint c) // CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr addrspace(5) [[A_ADDR]], align 2 // CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr addrspace(5) [[B_ADDR]], align 2 // CHECK-NEXT: [[TMP2:%.*]] = load i16, ptr addrspace(5) [[C_ADDR]], align 2 -// CHECK-NEXT: [[TMP3:%.*]] = call i16 @llvm.amdgcn.bitop3.i16(i16 [[TMP0]], i16 [[TMP1]], i16 [[TMP2]], i8 1) +// CHECK-NEXT: [[TMP3:%.*]] = call i16 @llvm.amdgcn.bitop3.i16(i16 [[TMP0]], i16 [[TMP1]], i16 [[TMP2]], i32 1) // CHECK-NEXT: [[TMP4:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[OUT_ADDR]], align 8 // CHECK-NEXT: store i16 [[TMP3]], ptr addrspace(1) [[TMP4]], align 2 // CHECK-NEXT: ret void diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl index c22a43146a8c8..ded5f6b5ac4fd 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl @@ -620,11 +620,11 @@ void test_get_local_id(int d, global int *out) // CHECK-LABEL: @test_get_workgroup_size( // CHECK: {{.*}}call align 8 dereferenceable(256){{.*}} ptr addrspace(4) @llvm.amdgcn.implicitarg.ptr() -// CHECK: getelementptr inbounds i8, ptr addrspace(4) %{{.*}}, i64 12 +// CHECK: getelementptr inbounds nuw i8, ptr addrspace(4) %{{.*}}, i64 12 // CHECK: load i16, ptr addrspace(4) %{{.*}}, align 4, !range [[$WS_RANGE:![0-9]*]], !invariant.load{{.*}}, !noundef -// CHECK: getelementptr inbounds i8, ptr addrspace(4) %{{.*}}, i64 14 +// CHECK: getelementptr inbounds nuw i8, ptr addrspace(4) %{{.*}}, i64 14 // CHECK: load i16, ptr addrspace(4) %{{.*}}, align 2, !range [[$WS_RANGE:![0-9]*]], !invariant.load{{.*}}, !noundef -// CHECK: getelementptr inbounds i8, ptr addrspace(4) %{{.*}}, i64 16 +// CHECK: getelementptr inbounds nuw i8, ptr addrspace(4) %{{.*}}, i64 16 // CHECK: load i16, ptr addrspace(4) %{{.*}}, align 8, !range [[$WS_RANGE:![0-9]*]], !invariant.load{{.*}}, !noundef void test_get_workgroup_size(int d, global int *out) { @@ -638,7 +638,7 @@ void test_get_workgroup_size(int d, global int *out) // CHECK-LABEL: @test_get_grid_size( // CHECK: {{.*}}call align 4 dereferenceable(64){{.*}} ptr addrspace(4) @llvm.amdgcn.dispatch.ptr() -// CHECK: getelementptr inbounds i8, ptr addrspace(4) %{{.*}}, i64 %{{.+}} +// CHECK: getelementptr inbounds nuw i8, ptr addrspace(4) %{{.*}}, i64 %{{.+}} // CHECK: load i32, ptr addrspace(4) %{{.*}}, align 4, !range [[$GRID_RANGE:![0-9]+]], !invariant.load void test_get_grid_size(int d, global int *out) { diff --git a/clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp b/clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp index 86f21ee556ce8..697e50e199a04 100644 --- a/clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp +++ b/clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp @@ -2,11 +2,11 @@ //RUN: %clang_cc1 %s -triple spir -emit-llvm -O1 -o - | FileCheck %s // CHECK-LABEL: define dso_local spir_kernel void @test( -// CHECK-SAME: ptr addrspace(1) nocapture noundef readonly align 8 [[IN:%.*]], ptr addrspace(1) nocapture noundef writeonly align 8 initializes((0, 8)) [[OUT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] !kernel_arg_addr_space [[META3:![0-9]+]] !kernel_arg_access_qual [[META4:![0-9]+]] !kernel_arg_type [[META5:![0-9]+]] !kernel_arg_base_type [[META5]] !kernel_arg_type_qual [[META6:![0-9]+]] { +// CHECK-SAME: ptr addrspace(1) nocapture noundef readonly align 8 [[IN:%.*]], ptr addrspace(1) nocapture noundef writeonly align 8 initializes((0, 8)) [[OUT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] !kernel_arg_addr_space [[META4:![0-9]+]] !kernel_arg_access_qual [[META5:![0-9]+]] !kernel_arg_type [[META6:![0-9]+]] !kernel_arg_base_type [[META6]] !kernel_arg_type_qual [[META7:![0-9]+]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[IN]], i32 8 -// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr addrspace(1) [[ARRAYIDX1]], align 8, !tbaa [[TBAA7:![0-9]+]] -// CHECK-NEXT: store i64 [[TMP0]], ptr addrspace(1) [[OUT]], align 8, !tbaa [[TBAA7]] +// CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[IN]], i32 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr addrspace(1) [[ARRAYIDX1]], align 8, !tbaa [[TBAA8:![0-9]+]] +// CHECK-NEXT: store i64 [[TMP0]], ptr addrspace(1) [[OUT]], align 8, !tbaa [[TBAA8]] // CHECK-NEXT: ret void // __kernel void test(__global long *In, __global long *Out) { @@ -14,12 +14,12 @@ __kernel void test(__global long *In, __global long *Out) { *Out = m[1]; } //. -// CHECK: [[META3]] = !{i32 1, i32 1} -// CHECK: [[META4]] = !{!"none", !"none"} -// CHECK: [[META5]] = !{!"long*", !"long*"} -// CHECK: [[META6]] = !{!"", !""} -// CHECK: [[TBAA7]] = !{[[META8:![0-9]+]], [[META8]], i64 0} -// CHECK: [[META8]] = !{!"long", [[META9:![0-9]+]], i64 0} -// CHECK: [[META9]] = !{!"omnipotent char", [[META10:![0-9]+]], i64 0} -// CHECK: [[META10]] = !{!"Simple C++ TBAA"} +// CHECK: [[META4]] = !{i32 1, i32 1} +// CHECK: [[META5]] = !{!"none", !"none"} +// CHECK: [[META6]] = !{!"long*", !"long*"} +// CHECK: [[META7]] = !{!"", !""} +// CHECK: [[TBAA8]] = !{[[META9:![0-9]+]], [[META9]], i64 0} +// CHECK: [[META9]] = !{!"long", [[META10:![0-9]+]], i64 0} +// CHECK: [[META10]] = !{!"omnipotent char", [[META11:![0-9]+]], i64 0} +// CHECK: [[META11]] = !{!"Simple C++ TBAA"} //. diff --git a/clang/test/Driver/Inputs/config-l.cfg b/clang/test/Driver/Inputs/config-l.cfg new file mode 100644 index 0000000000000..e76efafd3039a --- /dev/null +++ b/clang/test/Driver/Inputs/config-l.cfg @@ -0,0 +1,3 @@ +-Wall $-lm +-Wl,--as-needed $-Wl,-Bstatic +$-lhappy $-Wl,-Bdynamic diff --git a/clang/test/Driver/aarch64-fixed-register-global.c b/clang/test/Driver/aarch64-fixed-register-global.c deleted file mode 100644 index 7b1fb118fcdf7..0000000000000 --- a/clang/test/Driver/aarch64-fixed-register-global.c +++ /dev/null @@ -1,12 +0,0 @@ -// Check that -ffixed register handled for globals. -// Regression test for #76426 -// RUN: %clang --target=aarch64-none-gnu -ffixed-x15 -### %s 2>&1 | FileCheck %s -// CHECK-NOT: fatal error: error in backend: Invalid register name "x15". -register int i1 __asm__("x15"); - -int foo() { - return i1; -} -int main() { - return foo(); -} diff --git a/clang/test/Driver/aarch64-fujitsu-monaka.c b/clang/test/Driver/aarch64-fujitsu-monaka.c new file mode 100644 index 0000000000000..df96b36bace68 --- /dev/null +++ b/clang/test/Driver/aarch64-fujitsu-monaka.c @@ -0,0 +1,13 @@ +// RUN: %clang --target=aarch64 -mcpu=fujitsu-monaka -### -c %s 2>&1 | FileCheck -check-prefix=fujitsu-monaka %s +// RUN: %clang --target=aarch64 -mlittle-endian -mcpu=fujitsu-monaka -### -c %s 2>&1 | FileCheck -check-prefix=fujitsu-monaka %s +// RUN: %clang --target=aarch64 -mtune=fujitsu-monaka -### -c %s 2>&1 | FileCheck -check-prefix=fujitsu-monaka-TUNE %s +// RUN: %clang --target=aarch64 -mlittle-endian -mtune=fujitsu-monaka -### -c %s 2>&1 | FileCheck -check-prefix=fujitsu-monaka-TUNE %s +// fujitsu-monaka: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "fujitsu-monaka" +// fujitsu-monaka-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" + +// RUN: %clang --target=arm64 -mcpu=fujitsu-monaka -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-fujitsu-monaka %s +// RUN: %clang --target=arm64 -mlittle-endian -mcpu=fujitsu-monaka -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-fujitsu-monaka %s +// RUN: %clang --target=arm64 -mtune=fujitsu-monaka -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-fujitsu-monaka-TUNE %s +// RUN: %clang --target=arm64 -mlittle-endian -mtune=fujitsu-monaka -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-fujitsu-monaka-TUNE %s +// ARM64-fujitsu-monaka: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "fujitsu-monaka" +// ARM64-fujitsu-monaka-TUNE: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "generic" diff --git a/clang/test/Driver/aarch64-ptrauth.c b/clang/test/Driver/aarch64-ptrauth.c index 19eaa73b14d9e..d036189e61498 100644 --- a/clang/test/Driver/aarch64-ptrauth.c +++ b/clang/test/Driver/aarch64-ptrauth.c @@ -15,8 +15,9 @@ // RUN: -fno-ptrauth-indirect-gotos -fptrauth-indirect-gotos \ // RUN: -fno-ptrauth-init-fini -fptrauth-init-fini \ // RUN: -fno-ptrauth-init-fini-address-discrimination -fptrauth-init-fini-address-discrimination \ +// RUN: -fno-aarch64-jump-table-hardening -faarch64-jump-table-hardening \ // RUN: %s 2>&1 | FileCheck %s --check-prefix=ALL -// ALL: "-cc1"{{.*}} "-fptrauth-intrinsics" "-fptrauth-calls" "-fptrauth-returns" "-fptrauth-auth-traps" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-type-info-vtable-pointer-discrimination" "-fptrauth-indirect-gotos" "-fptrauth-init-fini" "-fptrauth-init-fini-address-discrimination" +// ALL: "-cc1"{{.*}} "-fptrauth-intrinsics" "-fptrauth-calls" "-fptrauth-returns" "-fptrauth-auth-traps" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-type-info-vtable-pointer-discrimination" "-fptrauth-indirect-gotos" "-fptrauth-init-fini" "-fptrauth-init-fini-address-discrimination" "-faarch64-jump-table-hardening" // RUN: %clang -### -c --target=aarch64-linux -mabi=pauthtest %s 2>&1 | FileCheck %s --check-prefix=PAUTHABI1 // RUN: %clang -### -c --target=aarch64-linux-pauthtest %s 2>&1 | FileCheck %s --check-prefix=PAUTHABI1 @@ -38,7 +39,7 @@ // RUN: not %clang -### -c --target=x86_64 -fptrauth-intrinsics -fptrauth-calls -fptrauth-returns -fptrauth-auth-traps \ // RUN: -fptrauth-vtable-pointer-address-discrimination -fptrauth-vtable-pointer-type-discrimination \ // RUN: -fptrauth-type-info-vtable-pointer-discrimination -fptrauth-indirect-gotos -fptrauth-init-fini \ -// RUN: -fptrauth-init-fini-address-discrimination %s 2>&1 | FileCheck %s --check-prefix=ERR1 +// RUN: -fptrauth-init-fini-address-discrimination -faarch64-jump-table-hardening %s 2>&1 | FileCheck %s --check-prefix=ERR1 // ERR1: error: unsupported option '-fptrauth-intrinsics' for target '{{.*}}' // ERR1-NEXT: error: unsupported option '-fptrauth-calls' for target '{{.*}}' // ERR1-NEXT: error: unsupported option '-fptrauth-returns' for target '{{.*}}' @@ -49,6 +50,7 @@ // ERR1-NEXT: error: unsupported option '-fptrauth-indirect-gotos' for target '{{.*}}' // ERR1-NEXT: error: unsupported option '-fptrauth-init-fini' for target '{{.*}}' // ERR1-NEXT: error: unsupported option '-fptrauth-init-fini-address-discrimination' for target '{{.*}}' +// ERR1-NEXT: error: unsupported option '-faarch64-jump-table-hardening' for target '{{.*}}' //// Only support PAuth ABI for Linux as for now. // RUN: not %clang -o /dev/null -c --target=aarch64-unknown -mabi=pauthtest %s 2>&1 | FileCheck %s --check-prefix=ERR2 diff --git a/clang/test/Driver/arm-cortex-cpus-2.c b/clang/test/Driver/arm-cortex-cpus-2.c index 2f17a08140436..0ee8e05f378ef 100644 --- a/clang/test/Driver/arm-cortex-cpus-2.c +++ b/clang/test/Driver/arm-cortex-cpus-2.c @@ -544,6 +544,17 @@ // CHECK-CORTEX-A78AE-MFPU: "-target-feature" "+sha2" // CHECK-CORTEX-A78AE-MFPU: "-target-feature" "+aes" +// RUN: %clang -target armv8a-arm-none-eabi -mcpu=cortex-a510 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CORTEX-A510 %s +// RUN: %clang -target armv8a-arm-none-eabi -mcpu=cortex-a510 -mfpu=crypto-neon-fp-armv8 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CORTEX-A510-MFPU %s +// CHECK-CORTEX-A510: "-cc1"{{.*}} "-triple" "armv9a-{{.*}} "-target-cpu" "cortex-a510" +// CHECK-CORTEX-A510-NOT: "-target-feature" "{{[+-]}}sm4" +// CHECK-CORTEX-A510-NOT: "-target-feature" "{{[+-]}}sha3" +// CHECK-CORTEX-A510: "-target-feature" "-aes" +// CHECK-CORTEX-A510-SAME: {{$}} +// CHECK-CORTEX-A510-MFPU: "-cc1"{{.*}} "-target-feature" "+fp-armv8" +// CHECK-CORTEX-A510-MFPU: "-target-feature" "+sha2" +// CHECK-CORTEX-A510-MFPU: "-target-feature" "+aes" + // RUN: %clang -target armv8a-arm-none-eabi -mcpu=cortex-a710 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CORTEX-A710 %s // RUN: %clang -target armv8a-arm-none-eabi -mcpu=cortex-a710 -mfpu=crypto-neon-fp-armv8 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CORTEX-A710-MFPU %s // CHECK-CORTEX-A710: "-cc1"{{.*}} "-triple" "armv9a-{{.*}} "-target-cpu" "cortex-a710" diff --git a/clang/test/Driver/baremetal-multilib.yaml b/clang/test/Driver/baremetal-multilib.yaml index b6bfd0ed3a94c..853a4e9e36e43 100644 --- a/clang/test/Driver/baremetal-multilib.yaml +++ b/clang/test/Driver/baremetal-multilib.yaml @@ -10,7 +10,8 @@ # CHECK-SAME: "-x" "c++" "{{.*}}baremetal-multilib.yaml" # CHECK-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" # CHECK-SAME: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib" -# CHECK-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" +# CHECK-SAME: "{{[^"]*}}libclang_rt.builtins.a" +# CHECK-SAME: "-lc" # CHECK-SAME: "-o" "{{.*}}.tmp.out" # RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c++ %s -### -o %t.out 2>&1 \ diff --git a/clang/test/Driver/baremetal-sysroot.cpp b/clang/test/Driver/baremetal-sysroot.cpp index 18654be33b87c..5cbb7ac69a7ac 100644 --- a/clang/test/Driver/baremetal-sysroot.cpp +++ b/clang/test/Driver/baremetal-sysroot.cpp @@ -18,5 +18,6 @@ // CHECK-V6M-C-SAME: "-x" "c++" "{{.*}}baremetal-sysroot.cpp" // CHECK-V6M-C-NEXT: "{{[^"]*}}ld{{(\.(lld|bfd|gold))?}}{{(\.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-V6M-C-SAME: "-L{{.*}}/baremetal_default_sysroot{{[/\\]+}}bin{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}armv6m-none-eabi{{[/\\]+}}lib" -// CHECK-V6M-C-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-V6M-C-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-V6M-C-SAME: "-lc" // CHECK-V6M-C-SAME: "-o" "{{.*}}.o" diff --git a/clang/test/Driver/baremetal.cpp b/clang/test/Driver/baremetal.cpp index f09d7361e6c13..6d6255ef5970f 100644 --- a/clang/test/Driver/baremetal.cpp +++ b/clang/test/Driver/baremetal.cpp @@ -19,7 +19,9 @@ // CHECK-V6M-C-SAME: "[[SYSROOT:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}crt0.o" // CHECK-V6M-C-SAME: "-T" "semihosted.lds" "-Lsome{{[/\\]+}}directory{{[/\\]+}}user{{[/\\]+}}asked{{[/\\]+}}for" // CHECK-V6M-C-SAME: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}lib" -// CHECK-V6M-C-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "--target2=rel" "-o" "{{.*}}.tmp.out" +// CHECK-V6M-C-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-V6M-C-SAME: "-lc" +// CHECK-V6M-C-SAME: "--target2=rel" "-o" "{{.*}}.tmp.out" // RUN: %clang %s -### --target=armv6m-none-eabi -nostdlibinc -nobuiltininc 2>&1 \ // RUN: --sysroot=%S/Inputs/baremetal_arm | FileCheck --check-prefix=CHECK-V6M-LIBINC %s @@ -40,7 +42,9 @@ // CHECK-V6M-TREE-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL" // CHECK-V6M-TREE-SAME: "[[INSTALLED_DIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}armv6m-unknown-none-eabi{{[/\\]+}}crt0.o" // CHECK-V6M-TREE-SAME: "-L[[INSTALLED_DIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}armv6m-unknown-none-eabi" -// CHECK-V6M-TREE-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "--target2=rel" "-o" "{{.*}}.tmp.out" +// CHECK-V6M-TREE-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-V6M-TREE-SAME: "-lc" +// CHECK-V6M-TREE-SAME: "--target2=rel" "-o" "{{.*}}.tmp.out" // RUN: %clang %s -### --target=armv7m-vendor-none-eabi -rtlib=compiler-rt 2>&1 \ // RUN: --sysroot=%S/Inputs/baremetal_arm \ @@ -53,7 +57,8 @@ // CHECK-ARMV7M-PER_TARGET: "[[SYSROOT:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}crt0.o" // CHECK-ARMV7M-PER-TARGET: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}lib" // CHECK-ARMV7M-PER-TARGET: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}armv7m-vendor-none-eabi -// CHECK-ARMV7M-PER-TARGET: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-ARMV7M-PER-TARGET: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-ARMV7M-PER-TARGET: "-lc" // RUN: %clangxx %s -### --target=armv6m-none-eabi 2>&1 \ // RUN: --sysroot=%S/Inputs/baremetal_arm | FileCheck --check-prefix=CHECK-V6M-DEFAULTCXX %s @@ -61,8 +66,11 @@ // CHECK-V6M-DEFAULTCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL" // CHECK-V6M-DEFAULTCXX-SAME: "[[SYSROOT:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}crt0.o" // CHECK-V6M-DEFAULTCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib" -// CHECK-V6M-DEFAULTCXX-SAME: "-lc++" "-lc++abi" "-lunwind" -// CHECK-V6M-DEFAULTCXX-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "--target2=rel" "-o" "a.out" +// CHECK-V6M-DEFAULTCXX-SAME: "-lc++" +// CHECK-V6M-DEFAULTCXX-SAME: "-lm" +// CHECK-V6M-DEFAULTCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-V6M-DEFAULTCXX-SAME: "-lc" +// CHECK-V6M-DEFAULTCXX-SAME: "--target2=rel" "-o" "a.out" // RUN: %clangxx %s -### --target=armv6m-none-eabi -stdlib=libc++ 2>&1 \ // RUN: --sysroot=%S/Inputs/baremetal_arm | FileCheck --check-prefix=CHECK-V6M-LIBCXX %s @@ -71,8 +79,11 @@ // CHECK-V6M-LIBCXX-SAME: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" // CHECK-V6M-LIBCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL" // CHECK-V6M-LIBCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib" -// CHECK-V6M-LIBCXX-SAME: "-lc++" "-lc++abi" "-lunwind" -// CHECK-V6M-LIBCXX-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "--target2=rel" "-o" "a.out" +// CHECK-V6M-LIBCXX-SAME: "-lc++" +// CHECK-V6M-LIBCXX-SAME: "-lm" +// CHECK-V6M-LIBCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-V6M-LIBCXX-SAME: "-lc" +// CHECK-V6M-LIBCXX-SAME: "--target2=rel" "-o" "a.out" // RUN: %clangxx %s -### --target=armv6m-none-eabi 2>&1 \ // RUN: --sysroot=%S/Inputs/baremetal_arm \ @@ -83,8 +94,10 @@ // CHECK-V6M-LIBSTDCXX-SAME: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}6.0.0" // CHECK-V6M-LIBSTDCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL" // CHECK-V6M-LIBSTDCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib" -// CHECK-V6M-LIBSTDCXX-SAME: "-lstdc++" "-lsupc++" "-lunwind" -// CHECK-V6M-LIBSTDCXX-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "--target2=rel" "-o" "a.out" +// CHECK-V6M-LIBSTDCXX-SAME: "-lstdc++" "-lm" +// CHECK-V6M-LIBSTDCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-V6M-LIBSTDCXX-SAME: "-lc" +// CHECK-V6M-LIBSTDCXX-SAME: "--target2=rel" "-o" "a.out" // RUN: %clangxx %s -### --target=armv6m-none-eabi 2>&1 \ // RUN: --sysroot=%S/Inputs/baremetal_arm \ @@ -106,8 +119,9 @@ // CHECK-V6M-LIBCXX-USR-SAME: "-internal-isystem" "{{[^"]+}}baremetal_cxx_sysroot{{[/\\]+}}usr{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" // CHECK-V6M-LIBCXX-USR: "{{[^"]*}}-Bstatic" // CHECK-V6M-LIBCXX-USR-SAME: "-L{{[^"]*}}{{[/\\]+}}baremetal_cxx_sysroot{{[/\\]+}}lib" -// CHECK-V6M-LIBCXX-USR-SAME: "-lc++" "-lc++abi" "-lunwind" -// CHECK-V6M-LIBCXX-USR-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-V6M-LIBCXX-USR-SAME: "-lc++" "-lm" +// CHECK-V6M-LIBCXX-USR-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-V6M-LIBCXX-USR-SAME: "-lc" // RUN: %clangxx --target=arm-none-eabi -v 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-THREAD-MODEL @@ -125,7 +139,7 @@ // RUN: | FileCheck %s --check-prefix=CHECK-NOSTARTFILES // CHECK-NOSTARTFILES-NOT: "crt0.o" -// RUN: %clang -### --target=arm-none-eabi -rtlib=libgcc -v %s 2>&1 \ +// RUN: %clang -### --target=arm-none-eabi -rtlib=libgcc --unwindlib=libgcc -v %s 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-RTLIB-GCC // CHECK-RTLIB-GCC: -lgcc @@ -194,7 +208,9 @@ // CHECK-RV64-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-RV64-SAME: "-Lsome{{[/\\]+}}directory{{[/\\]+}}user{{[/\\]+}}asked{{[/\\]+}}for" // CHECK-RV64-SAME: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}lib" -// CHECK-RV64-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "-X" "-o" "{{.*}}.tmp.out" +// CHECK-RV64-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-RV64-SAME: "-lc" +// CHECK-RV64-SAME: "-X" "-o" "{{.*}}.tmp.out" // RUN: %clangxx %s -### --target=riscv64-unknown-elf 2>&1 \ // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf \ @@ -202,8 +218,10 @@ // CHECK-RV64-DEFAULTCXX: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-RV64-DEFAULTCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-RV64-DEFAULTCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}basic_riscv64_tree{{[/\\]+}}riscv64-unknown-elf{{[/\\]+}}lib" -// CHECK-RV64-DEFAULTCXX-SAME: "-lc++" "-lc++abi" "-lunwind" -// CHECK-RV64-DEFAULTCXX-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "-X" "-o" "a.out" +// CHECK-RV64-DEFAULTCXX-SAME: "-lc++" "-lm" +// CHECK-RV64-DEFAULTCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-RV64-DEFAULTCXX-SAME: "-lc" +// CHECK-RV64-DEFAULTCXX-SAME: "-X" "-o" "a.out" // RUN: %clangxx %s -### --target=riscv64-unknown-elf 2>&1 \ // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf \ @@ -214,8 +232,10 @@ // CHECK-RV64-LIBCXX-SAME: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" // CHECK-RV64-LIBCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-RV64-LIBCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}basic_riscv64_tree{{[/\\]+}}riscv64-unknown-elf{{[/\\]+}}lib" -// CHECK-RV64-LIBCXX-SAME: "-lc++" "-lc++abi" "-lunwind" -// CHECK-RV64-LIBCXX-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "-X" "-o" "a.out" +// CHECK-RV64-LIBCXX-SAME: "-lc++" "-lm" +// CHECK-RV64-LIBCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-RV64-LIBCXX-SAME: "-lc" +// CHECK-RV64-LIBCXX-SAME: "-X" "-o" "a.out" // RUN: %clangxx %s -### 2>&1 --target=riscv64-unknown-elf \ // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf \ @@ -226,8 +246,10 @@ // CHECK-RV64-LIBSTDCXX-SAME: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}8.0.1" // CHECK-RV64-LIBSTDCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-RV64-LIBSTDCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}basic_riscv64_tree{{[/\\]+}}riscv64-unknown-elf{{[/\\]+}}lib" -// CHECK-RV64-LIBSTDCXX-SAME: "-lstdc++" "-lsupc++" "-lunwind" -// CHECK-RV64-LIBSTDCXX-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "-X" "-o" "a.out" +// CHECK-RV64-LIBSTDCXX-SAME: "-lstdc++" "-lm" +// CHECK-RV64-LIBSTDCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-RV64-LIBSTDCXX-SAME: "-lc" +// CHECK-RV64-LIBSTDCXX-SAME: "-X" "-o" "a.out" // RUN: %clang %s -### 2>&1 --target=riscv32-unknown-elf \ // RUN: -L some/directory/user/asked/for \ @@ -242,7 +264,9 @@ // CHECK-RV32-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-RV32-SAME: "-Lsome{{[/\\]+}}directory{{[/\\]+}}user{{[/\\]+}}asked{{[/\\]+}}for" // CHECK-RV32-SAME: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}lib" -// CHECK-RV32-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "-X" "-o" "a.out" +// CHECK-RV32-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-RV32-SAME: "-lc" +// CHECK-RV32-SAME: "-X" "-o" "a.out" // RUN: %clangxx %s -### 2>&1 --target=riscv32-unknown-elf \ // RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ @@ -250,8 +274,10 @@ // CHECK-RV32-DEFAULTCXX: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-RV32-DEFAULTCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-RV32-DEFAULTCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}basic_riscv32_tree{{[/\\]+}}riscv32-unknown-elf{{[/\\]+}}lib" -// CHECK-RV32-DEFAULTCXX-SAME: "-lc++" "-lc++abi" "-lunwind" -// CHECK-RV32-DEFAULTCXX-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "-X" "-o" "a.out" +// CHECK-RV32-DEFAULTCXX-SAME: "-lc++" "-lm" +// CHECK-RV32-DEFAULTCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-RV32-DEFAULTCXX-SAME: "-lc" +// CHECK-RV32-DEFAULTCXX-SAME: "-X" "-o" "a.out" // RUN: %clangxx %s -### 2>&1 --target=riscv32-unknown-elf \ // RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ @@ -262,8 +288,9 @@ // CHECK-RV32-LIBCXX-SAME: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" // CHECK-RV32-LIBCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-RV32-LIBCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}basic_riscv32_tree{{[/\\]+}}riscv32-unknown-elf{{[/\\]+}}lib" -// CHECK-RV32-LIBCXX-SAME: "-lc++" "-lc++abi" "-lunwind" -// CHECK-RV32-LIBCXX-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "-X" "-o" "a.out" +// CHECK-RV32-LIBCXX-SAME: "-lc++" "-lm" +// CHECK-RV32-LIBCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-RV32-LIBCXX-SAME: "-X" "-o" "a.out" // RUN: %clangxx %s -### 2>&1 --target=riscv32-unknown-elf \ // RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ @@ -274,8 +301,9 @@ // CHECK-RV32-LIBSTDCXX-SAME: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}8.0.1" // CHECK-RV32-LIBSTDCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-RV32-LIBSTDCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}basic_riscv32_tree{{[/\\]+}}riscv32-unknown-elf{{[/\\]+}}lib" -// CHECK-RV32-LIBSTDCXX-SAME: "-lstdc++" "-lsupc++" "-lunwind" -// CHECK-RV32-LIBSTDCXX-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "-X" "-o" "a.out" +// CHECK-RV32-LIBSTDCXX-SAME: "-lstdc++" "-lm" +// CHECK-RV32-LIBSTDCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-RV32-LIBSTDCXX-SAME: "-lc" "-X" "-o" "a.out" // RUN: %clang %s -### 2>&1 --target=riscv64-unknown-elf \ // RUN: -nostdlibinc -nobuiltininc \ @@ -397,7 +425,9 @@ // CHECK-PPCEABI-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include" // CHECK-PPCEABI-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-PPCEABI-SAME: "-L[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}lib" -// CHECK-PPCEABI-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "-o" "a.out" +// CHECK-PPCEABI-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-PPCEABI-SAME: "-lc" +// CHECK-PPCEABI-SAME: "-o" "a.out" // RUN: %clang -no-canonical-prefixes %s -### --target=powerpc64-unknown-eabi 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-PPC64EABI %s @@ -409,7 +439,9 @@ // CHECK-PPC64EABI-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include" // CHECK-PPC64EABI-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-PPC64EABI-SAME: "-L[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}lib" -// CHECK-PPC64EABI-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "-o" "a.out" +// CHECK-PPC64EABI-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-PPC64EABI-SAME: "-lc" +// CHECK-PPC64EABI-SAME: "-o" "a.out" // RUN: %clang -no-canonical-prefixes %s -### --target=powerpcle-unknown-eabi 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-PPCLEEABI %s @@ -421,7 +453,9 @@ // CHECK-PPCLEEABI-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include" // CHECK-PPCLEEABI-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-PPCLEEABI-SAME: "-L[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}lib" -// CHECK-PPCLEEABI-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "-o" "a.out" +// CHECK-PPCLEEABI-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-PPCLEEABI-SAME: "-lc" +// CHECK-PPCLEEABI-SAME: "-o" "a.out" // RUN: %clang -no-canonical-prefixes %s -### --target=powerpc64le-unknown-eabi 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-PPC64LEEABI %s @@ -433,7 +467,9 @@ // CHECK-PPC64LEEABI-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include" // CHECK-PPC64LEEABI-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" // CHECK-PPC64LEEABI-SAME: "-L[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}lib" -// CHECK-PPC64LEEABI-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "-o" "a.out" +// CHECK-PPC64LEEABI-SAME: "{{[^"]*}}libclang_rt.builtins.a" +// CHECK-PPC64LEEABI-SAME: "-lc" +// CHECK-PPC64LEEABI-SAME: "-o" "a.out" // Check that compiler-rt library without the arch filename suffix will // be used if present. diff --git a/clang/test/Driver/config-file.c b/clang/test/Driver/config-file.c index 9df830ca4c753..e9a8555bcc8e4 100644 --- a/clang/test/Driver/config-file.c +++ b/clang/test/Driver/config-file.c @@ -82,3 +82,29 @@ // CHECK-TWO-CONFIGS: -isysroot // CHECK-TWO-CONFIGS-SAME: /opt/data // CHECK-TWO-CONFIGS-SAME: -Wall + +//--- The linker input flags should be moved to the end of input list and appear only when linking. +// RUN: %clang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg %s -lmylib -Wl,foo.a -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING +// RUN: %clang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -fopenmp %s -lmylib -Wl,foo.a -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING-LIBOMP-GOES-AFTER +// RUN: %clang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING +// RUN: %clang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -fopenmp -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING-OPENMP +// RUN: %clang --target=x86_64-pc-windows-msvc --config %S/Inputs/config-l.cfg %s -lmylib -Wl,foo.lib -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING-MSVC +// RUN: %clang --target=x86_64-pc-windows-msvc --config %S/Inputs/config-l.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING-MSVC +// CHECK-LINKING: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +// CHECK-LINKING: "-Wall" +// CHECK-LINKING: "--as-needed" "{{.*}}-{{.*}}.o" "-lmylib" "foo.a" "-lm" "-Bstatic" "-lhappy" "-Bdynamic" +// CHECK-LINKING-LIBOMP-GOES-AFTER: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +// CHECK-LINKING-LIBOMP-GOES-AFTER: "-Wall" {{.*}}"-fopenmp" +// CHECK-LINKING-LIBOMP-GOES-AFTER: "--as-needed" "{{.*}}-{{.*}}.o" "-lmylib" "foo.a" "-lm" "-Bstatic" "-lhappy" "-Bdynamic" {{.*}}"-lomp" +// CHECK-NOLINKING: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +// CHECK-NOLINKING: "-Wall" +// CHECK-NOLINKING-NO: "-lm" "-Bstatic" "-lhappy" "-Bdynamic" +// CHECK-NOLINKING-OPENMP: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +// CHECK-NOLINKING-OPENMP: "-Wall" {{.*}}"-fopenmp" +// CHECK-NOLINKING-OPENMP-NO: "-lm" "-Bstatic" "-lhappy" "-Bdynamic" {{.*}}"-lomp" +// CHECK-LINKING-MSVC: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +// CHECK-LINKING-MSVC: "-Wall" +// CHECK-LINKING-MSVC: "--as-needed" "{{.*}}-{{.*}}.o" "mylib.lib" "foo.lib" "m.lib" "-Bstatic" "happy.lib" "-Bdynamic" +// CHECK-NOLINKING-MSVC: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +// CHECK-NOLINKING-MSVC: "-Wall" +// CHECK-NOLINKING-MSVC-NO: "m.lib" "-Bstatic" "happy.lib" "-Bdynamic" diff --git a/clang/test/Driver/frame-pointer-elim.c b/clang/test/Driver/frame-pointer-elim.c index cdedcc7ae4c89..f64ff6efc7261 100644 --- a/clang/test/Driver/frame-pointer-elim.c +++ b/clang/test/Driver/frame-pointer-elim.c @@ -162,5 +162,58 @@ // RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s // RUN: not %clang -### --target=riscv64-linux-android -mbig-endian -O1 -S %s 2>&1 | \ // RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s + +// On ARM backend bare metal targets, frame pointer is omitted +// RUN: %clang -### --target=arm-arm-none-eabi -S %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NONE %s +// RUN: %clang -### --target=arm-arm-none-eabihf -S %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NONE %s +// RUN: %clang -### --target=arm-arm-none-eabi -S -fno-omit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: %clang -### --target=arm-arm-none-eabihf -S -fno-omit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: %clang -### --target=arm-arm-none-eabi -S -O1 %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NONE %s +// RUN: %clang -### --target=arm-arm-none-eabihf -S -O1 %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NONE %s +// RUN: %clang -### --target=arm-arm-none-eabi -S -O1 -fno-omit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: %clang -### --target=arm-arm-none-eabihf -S -O1 -fno-omit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: %clang -### --target=armeb-arm-none-eabi -S %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NONE %s +// RUN: %clang -### --target=thumb-arm-none-eabi -S %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NONE %s +// RUN: %clang -### --target=thumbeb-arm-none-eabi -S %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NONE %s + +// Check that for Apple bare metal targets, we're keeping frame pointers by default +// RUN: %clang -### --target=thumbv6m-apple-none-macho -S %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: %clang -### --target=thumbv6m-apple-none-macho -S -fno-omit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: %clang -### --target=arm-apple-none-macho -S %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: %clang -### --target=arm-apple-none-macho -S -fno-omit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: %clang -### --target=thumbv6m-apple-none-macho -S -O1 %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: %clang -### --target=thumbv6m-apple-none-macho -S -O1 -fno-omit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: %clang -### --target=arm-apple-none-macho -S -O1 %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: %clang -### --target=arm-apple-none-macho -S -O1 -fno-omit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-ALL %s + +// AArch64 bare metal targets behave like hosted targets +// RUN: %clang -### --target=aarch64-none-elf -S %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s +// RUN: %clang -### --target=aarch64-none-elf -S -O1 %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s +// RUN: %clang -### --target=aarch64-none-elf -S -fno-omit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s +// RUN: %clang -### --target=aarch64-none-elf -S -O1 -fno-omit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s + void f0() {} void f1() { f0(); } diff --git a/clang/test/Driver/fuchsia.c b/clang/test/Driver/fuchsia.c index 83dee16981690..cf92f85040901 100644 --- a/clang/test/Driver/fuchsia.c +++ b/clang/test/Driver/fuchsia.c @@ -297,3 +297,9 @@ // RUN: %clang --target=riscv64-unknown-fuchsia -mno-relax -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=RISCV64-FLAGS %s // RISCV64-FLAGS: "-X" "--no-relax" + +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia 2>&1 \ +// RUN: -nostdlib -nolibc \ +// RUN: | FileCheck %s -check-prefix=CHECK-NOSTDLIB-NOLIBC +// CHECK-NOSTDLIB-NOLIBC-NOT: "warning:" +// CHECK-NOSTDLIB-NOLIBC-NOT: "error:" diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c index 28fb075a80dbb..4d641c8f1b46e 100644 --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -940,6 +940,36 @@ // CHECK-ANDROID-HASH-STYLE-M: "{{.*}}ld{{(.exe)?}}" // CHECK-ANDROID-HASH-STYLE-M: "--hash-style=gnu" +// Check that we pass --no-rosegment for pre-29 Android versions and do not for +// 29+. +// RUN: %clang %s -### -o %t.o 2>&1 \ +// RUN: --target=armv7-linux-android28 \ +// RUN: | FileCheck --check-prefix=CHECK-ANDROID-ROSEGMENT-28 %s +// CHECK-ANDROID-ROSEGMENT-28: "{{.*}}ld{{(.exe)?}}" +// CHECK-ANDROID-ROSEGMENT-28: "--no-rosegment" +// +// RUN: %clang %s -### -o %t.o 2>&1 \ +// RUN: --target=armv7-linux-android29 \ +// RUN: | FileCheck --check-prefix=CHECK-ANDROID-ROSEGMENT-29 %s +// CHECK-ANDROID-ROSEGMENT-29: "{{.*}}ld{{(.exe)?}}" +// CHECK-ANDROID-ROSEGMENT-29-NOT: "--no-rosegment" + +// Check that we pass --pack-dyn-relocs=relr for API 28+ and not before. +// RUN: %clang %s -### -o %t.o 2>&1 \ +// RUN: --target=armv7-linux-android27 \ +// RUN: | FileCheck --check-prefix=CHECK-ANDROID-RELR-27 %s +// CHECK-ANDROID-RELR-27: "{{.*}}ld{{(.exe)?}}" +// CHECK-ANDROID-RELR-27-NOT: "--pack-dyn-relocs=relr" +// CHECK-ANDROID-RELR-27-NOT: "--pack-dyn-relocs=android+relr" +// +// RUN: %clang %s -### -o %t.o 2>&1 \ +// RUN: --target=armv7-linux-android28 \ +// RUN: | FileCheck --check-prefix=CHECK-ANDROID-RELR-28 %s +// CHECK-ANDROID-RELR-28: "{{.*}}ld{{(.exe)?}}" +// CHECK-ANDROID-RELR-28: "--use-android-relr-tags" +// CHECK-ANDROID-RELR-28: "--pack-dyn-relocs=relr" +// CHECK-ANDROID-RELR-28-NOT: "--pack-dyn-relocs=android+relr" + // RUN: %clang -### %s -no-pie 2>&1 --target=mips64-linux-gnuabin32 \ // RUN: | FileCheck --check-prefix=CHECK-MIPS64EL-GNUABIN32 %s // CHECK-MIPS64EL-GNUABIN32: "{{.*}}ld{{(.exe)?}}" diff --git a/clang/test/Driver/openmp-offload.c b/clang/test/Driver/openmp-offload.c index eaed0d66df75c..caedc223a5c76 100644 --- a/clang/test/Driver/openmp-offload.c +++ b/clang/test/Driver/openmp-offload.c @@ -84,9 +84,15 @@ /// Check -Xopenmp-target triggers error when an option requiring arguments is passed to it. // RUN: not %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target -Xopenmp-target -mcpu=pwr8 %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHK-FOPENMP-TARGET-NESTED-ERROR %s +// RUN: | FileCheck -check-prefix=CHK-FOPENMP-TARGET-NESTED-ERROR_0 %s -// CHK-FOPENMP-TARGET-NESTED-ERROR: clang{{.*}} error: invalid -Xopenmp-target argument: '-Xopenmp-target -Xopenmp-target', options requiring arguments are unsupported +// CHK-FOPENMP-TARGET-NESTED-ERROR_0: error: invalid -Xopenmp-target argument: '-Xopenmp-target -Xopenmp-target', options requiring arguments are unsupported + +/// Check -Xopenmp-target= triggers error when an option requiring arguments is passed to it. +// RUN: not %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target=powerpc64le-ibm-linux-gnu -Xopenmp-target -mcpu=pwr8 %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-FOPENMP-TARGET-NESTED-ERROR_1 %s + +// CHK-FOPENMP-TARGET-NESTED-ERROR_1: error: invalid -Xopenmp-target argument: '-Xopenmp-target=powerpc64le-ibm-linux-gnu -Xopenmp-target', options requiring arguments are unsupported /// ########################################################################### diff --git a/clang/test/Driver/print-enabled-extensions/aarch64-fujitsu-monaka.c b/clang/test/Driver/print-enabled-extensions/aarch64-fujitsu-monaka.c new file mode 100644 index 0000000000000..3c74e3620df03 --- /dev/null +++ b/clang/test/Driver/print-enabled-extensions/aarch64-fujitsu-monaka.c @@ -0,0 +1,82 @@ +// REQUIRES: aarch64-registered-target +// RUN: %clang --target=aarch64 --print-enabled-extensions -mcpu=fujitsu-monaka | FileCheck --strict-whitespace --implicit-check-not=FEAT_ %s + +// CHECK: Extensions enabled for the given AArch64 target +// CHECK-EMPTY: +// CHECK-NEXT: Architecture Feature(s) Description +// CHECK-NEXT: FEAT_AES, FEAT_PMULL Enable AES support +// CHECK-NEXT: FEAT_AMUv1 Enable Armv8.4-A Activity Monitors extension +// CHECK-NEXT: FEAT_AMUv1p1 Enable Armv8.6-A Activity Monitors Virtualization support +// CHECK-NEXT: FEAT_AdvSIMD Enable Advanced SIMD instructions +// CHECK-NEXT: FEAT_BF16 Enable BFloat16 Extension +// CHECK-NEXT: FEAT_BTI Enable Branch Target Identification +// CHECK-NEXT: FEAT_CCIDX Enable Armv8.3-A Extend of the CCSIDR number of sets +// CHECK-NEXT: FEAT_CLRBHB Enable Clear BHB instruction +// CHECK-NEXT: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions +// CHECK-NEXT: FEAT_CSV2_2 Enable architectural speculation restriction +// CHECK-NEXT: FEAT_DIT Enable Armv8.4-A Data Independent Timing instructions +// CHECK-NEXT: FEAT_DPB Enable Armv8.2-A data Cache Clean to Point of Persistence +// CHECK-NEXT: FEAT_DPB2 Enable Armv8.5-A Cache Clean to Point of Deep Persistence +// CHECK-NEXT: FEAT_DotProd Enable dot product support +// CHECK-NEXT: FEAT_ECV Enable enhanced counter virtualization extension +// CHECK-NEXT: FEAT_ETE Enable Embedded Trace Extension +// CHECK-NEXT: FEAT_FAMINMAX Enable FAMIN and FAMAX instructions +// CHECK-NEXT: FEAT_FCMA Enable Armv8.3-A Floating-point complex number support +// CHECK-NEXT: FEAT_FGT Enable fine grained virtualization traps extension +// CHECK-NEXT: FEAT_FHM Enable FP16 FML instructions +// CHECK-NEXT: FEAT_FP Enable Armv8.0-A Floating Point Extensions +// CHECK-NEXT: FEAT_FP16 Enable half-precision floating-point data processing +// CHECK-NEXT: FEAT_FP8 Enable FP8 instructions +// CHECK-NEXT: FEAT_FP8DOT2 Enable FP8 2-way dot instructions +// CHECK-NEXT: FEAT_FP8DOT4 Enable FP8 4-way dot instructions +// CHECK-NEXT: FEAT_FP8FMA Enable Armv9.5-A FP8 multiply-add instructions +// CHECK-NEXT: FEAT_FPAC Enable Armv8.3-A Pointer Authentication Faulting enhancement +// CHECK-NEXT: FEAT_FRINTTS Enable FRInt[32|64][Z|X] instructions that round a floating-point number to an integer (in FP format) forcing it to fit into a 32- or 64-bit int +// CHECK-NEXT: FEAT_FlagM Enable Armv8.4-A Flag Manipulation instructions +// CHECK-NEXT: FEAT_FlagM2 Enable alternative NZCV format for floating point comparisons +// CHECK-NEXT: FEAT_HBC Enable Armv8.8-A Hinted Conditional Branches Extension +// CHECK-NEXT: FEAT_HCX Enable Armv8.7-A HCRX_EL2 system register +// CHECK-NEXT: FEAT_I8MM Enable Matrix Multiply Int8 Extension +// CHECK-NEXT: FEAT_JSCVT Enable Armv8.3-A JavaScript FP conversion instructions +// CHECK-NEXT: FEAT_LOR Enable Armv8.1-A Limited Ordering Regions extension +// CHECK-NEXT: FEAT_LRCPC Enable support for RCPC extension +// CHECK-NEXT: FEAT_LRCPC2 Enable Armv8.4-A RCPC instructions with Immediate Offsets +// CHECK-NEXT: FEAT_LS64, FEAT_LS64_V, FEAT_LS64_ACCDATA Enable Armv8.7-A LD64B/ST64B Accelerator Extension +// CHECK-NEXT: FEAT_LSE Enable Armv8.1-A Large System Extension (LSE) atomic instructions +// CHECK-NEXT: FEAT_LSE2 Enable Armv8.4-A Large System Extension 2 (LSE2) atomicity rules +// CHECK-NEXT: FEAT_LUT Enable Lookup Table instructions +// CHECK-NEXT: FEAT_MEC Enable Memory Encryption Contexts Extension +// CHECK-NEXT: FEAT_MOPS Enable Armv8.8-A memcpy and memset acceleration instructions +// CHECK-NEXT: FEAT_MPAM Enable Armv8.4-A Memory system Partitioning and Monitoring extension +// CHECK-NEXT: FEAT_NMI, FEAT_GICv3_NMI Enable Armv8.8-A Non-maskable Interrupts +// CHECK-NEXT: FEAT_NV, FEAT_NV2 Enable Armv8.4-A Nested Virtualization Enchancement +// CHECK-NEXT: FEAT_PAN Enable Armv8.1-A Privileged Access-Never extension +// CHECK-NEXT: FEAT_PAN2 Enable Armv8.2-A PAN s1e1R and s1e1W Variants +// CHECK-NEXT: FEAT_PAuth Enable Armv8.3-A Pointer Authentication extension +// CHECK-NEXT: FEAT_PMUv3 Enable Armv8.0-A PMUv3 Performance Monitors extension +// CHECK-NEXT: FEAT_RAS, FEAT_RASv1p1 Enable Armv8.0-A Reliability, Availability and Serviceability Extensions +// CHECK-NEXT: FEAT_RDM Enable Armv8.1-A Rounding Double Multiply Add/Subtract instructions +// CHECK-NEXT: FEAT_RME Enable Realm Management Extension +// CHECK-NEXT: FEAT_RNG Enable Random Number generation instructions +// CHECK-NEXT: FEAT_SB Enable Armv8.5-A Speculation Barrier +// CHECK-NEXT: FEAT_SEL2 Enable Armv8.4-A Secure Exception Level 2 extension +// CHECK-NEXT: FEAT_SHA1, FEAT_SHA256 Enable SHA1 and SHA256 support +// CHECK-NEXT: FEAT_SHA3, FEAT_SHA512 Enable SHA512 and SHA3 support +// CHECK-NEXT: FEAT_SM4, FEAT_SM3 Enable SM3 and SM4 support +// CHECK-NEXT: FEAT_SPECRES Enable Armv8.5-A execution and data prediction invalidation instructions +// CHECK-NEXT: FEAT_SPECRES2 Enable Speculation Restriction Instruction +// CHECK-NEXT: FEAT_SPEv1p2 Enable extra register in the Statistical Profiling Extension +// CHECK-NEXT: FEAT_SSBS, FEAT_SSBS2 Enable Speculative Store Bypass Safe bit +// CHECK-NEXT: FEAT_SVE Enable Scalable Vector Extension (SVE) instructions +// CHECK-NEXT: FEAT_SVE2 Enable Scalable Vector Extension 2 (SVE2) instructions +// CHECK-NEXT: FEAT_SVE_AES, FEAT_SVE_PMULL128 Enable SVE AES and quadword SVE polynomial multiply instructions +// CHECK-NEXT: FEAT_SVE_BitPerm Enable bit permutation SVE2 instructions +// CHECK-NEXT: FEAT_SVE_SHA3 Enable SHA3 SVE2 instructions +// CHECK-NEXT: FEAT_SVE_SM4 Enable SM4 SVE2 instructions +// CHECK-NEXT: FEAT_TLBIOS, FEAT_TLBIRANGE Enable Armv8.4-A TLB Range and Maintenance instructions +// CHECK-NEXT: FEAT_TRBE Enable Trace Buffer Extension +// CHECK-NEXT: FEAT_TRF Enable Armv8.4-A Trace extension +// CHECK-NEXT: FEAT_UAO Enable Armv8.2-A UAO PState +// CHECK-NEXT: FEAT_VHE Enable Armv8.1-A Virtual Host extension +// CHECK-NEXT: FEAT_WFxT Enable Armv8.7-A WFET and WFIT instruction +// CHECK-NEXT: FEAT_XS Enable Armv8.7-A limited-TLB-maintenance instruction \ No newline at end of file diff --git a/clang/test/Driver/print-supported-cpus-aarch64.c b/clang/test/Driver/print-supported-cpus-aarch64.c new file mode 100644 index 0000000000000..3c1dcebf7c6c8 --- /dev/null +++ b/clang/test/Driver/print-supported-cpus-aarch64.c @@ -0,0 +1,27 @@ +// Test that --print-supported-cpus lists supported CPU models, including aliases. + +// REQUIRES: aarch64-registered-target + +// RUN: %clang --target=arm64-apple-macosx --print-supported-cpus 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK --implicit-check-not=apple-latest + +// CHECK: Target: arm64-apple-macosx + +// CHECK: apple-a11 +// CHECK: apple-a12 +// CHECK: apple-a13 +// CHECK: apple-a14 +// CHECK: apple-a15 +// CHECK: apple-a16 +// CHECK: apple-a17 +// CHECK: apple-a7 +// CHECK: apple-a8 +// CHECK: apple-a9 +// CHECK: apple-m1 +// CHECK: apple-m2 +// CHECK: apple-m3 +// CHECK: apple-m4 +// CHECK: apple-s4 +// CHECK: apple-s5 + +// CHECK: Use -mcpu or -mtune to specify the target's processor. diff --git a/clang/test/Driver/sanitizer-ld.c b/clang/test/Driver/sanitizer-ld.c index c83066a334001..877a01c3de304 100644 --- a/clang/test/Driver/sanitizer-ld.c +++ b/clang/test/Driver/sanitizer-ld.c @@ -15,7 +15,7 @@ // CHECK-ASAN-LINUX: "-lpthread" // CHECK-ASAN-LINUX: "-lrt" // CHECK-ASAN-LINUX: "-ldl" -// CHECK-ASAN-LINUX: "-lresolv" +// CHECK-ASAN-LINUX-NOT: "-lresolv" // RUN: %clang -fsanitize=address -fno-sanitize-link-runtime -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -143,7 +143,7 @@ // CHECK-ASAN-LINUX-CXX: "-lpthread" // CHECK-ASAN-LINUX-CXX: "-lrt" // CHECK-ASAN-LINUX-CXX: "-ldl" -// CHECK-ASAN-LINUX-CXX: "-lresolv" +// CHECK-ASAN-LINUX-CXX-NOT: "-lresolv" // RUN: %clang -### %s -o /dev/null -fsanitize=address \ // RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform \ @@ -292,7 +292,7 @@ // CHECK-TSAN-LINUX-CXX: "-lpthread" // CHECK-TSAN-LINUX-CXX: "-lrt" // CHECK-TSAN-LINUX-CXX: "-ldl" -// CHECK-TSAN-LINUX-CXX: "-lresolv" +// CHECK-TSAN-LINUX-CXX-NOT: "-lresolv" // RUN: %clang -fsanitize=thread -fno-sanitize-link-runtime -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -365,7 +365,7 @@ // CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_standalone_cxx // CHECK-UBSAN-LINUX-NOT: "-lstdc++" // CHECK-UBSAN-LINUX: "-lpthread" -// CHECK-UBSAN-LINUX: "-lresolv" +// CHECK-UBSAN-LINUX-NOT: "-lresolv" // RUN: %clang -fsanitize=undefined -fno-sanitize-link-runtime -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -438,7 +438,7 @@ // CHECK-UBSAN-LINUX-CXX: "-lstdc++" // CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan // CHECK-UBSAN-LINUX-CXX: "-lpthread" -// CHECK-UBSAN-LINUX-CXX: "-lresolv" +// CHECK-UBSAN-LINUX-CXX-NOT: "-lresolv" // RUN: %clang -fsanitize=undefined -fsanitize-minimal-runtime -### %s 2>&1 \ // RUN: --target=i386-unknown-linux -fuse-ld=ld \ @@ -448,7 +448,7 @@ // CHECK-UBSAN-MINIMAL-LINUX: "{{.*}}ld{{(.exe)?}}" // CHECK-UBSAN-MINIMAL-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_minimal.a" "--no-whole-archive" // CHECK-UBSAN-MINIMAL-LINUX: "-lpthread" -// CHECK-UBSAN-MINIMAL-LINUX: "-lresolv" +// CHECK-UBSAN-MINIMAL-LINUX-NOT: "-lresolv" // RUN: %clang -fsanitize=undefined -fsanitize-minimal-runtime -### %s 2>&1 \ // RUN: --target=x86_64-apple-darwin -fuse-ld=ld \ @@ -485,7 +485,7 @@ // CHECK-ASAN-UBSAN-LINUX-NOT: libclang_rt.ubsan // CHECK-ASAN-UBSAN-LINUX-NOT: "-lstdc++" // CHECK-ASAN-UBSAN-LINUX: "-lpthread" -// CHECK-ASAN-UBSAN-LINUX: "-lresolv" +// CHECK-ASAN-UBSAN-LINUX-NOT: "-lresolv" // RUN: %clangxx -fsanitize=address,undefined -### %s 2>&1 \ // RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform \ @@ -498,7 +498,7 @@ // CHECK-ASAN-UBSAN-LINUX-CXX-NOT: libclang_rt.ubsan // CHECK-ASAN-UBSAN-LINUX-CXX: "-lstdc++" // CHECK-ASAN-UBSAN-LINUX-CXX: "-lpthread" -// CHECK-ASAN-UBSAN-LINUX-CXX: "-lresolv" +// CHECK-ASAN-UBSAN-LINUX-CXX-NOT: "-lresolv" // RUN: %clangxx -fsanitize=memory,undefined -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -541,7 +541,7 @@ // CHECK-LSAN-LINUX: libclang_rt.lsan.a" // CHECK-LSAN-LINUX: "-lpthread" // CHECK-LSAN-LINUX: "-ldl" -// CHECK-LSAN-LINUX: "-lresolv" +// CHECK-LSAN-LINUX-NOT: "-lresolv" // RUN: %clang -fsanitize=leak -fno-sanitize-link-runtime -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -564,7 +564,7 @@ // CHECK-LSAN-COV-LINUX-NOT: libclang_rt.ubsan // CHECK-LSAN-COV-LINUX: "-lpthread" // CHECK-LSAN-COV-LINUX: "-ldl" -// CHECK-LSAN-COV-LINUX: "-lresolv" +// CHECK-LSAN-COV-LINUX-NOT: "-lresolv" // RUN: %clang -fsanitize=leak,address -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -586,7 +586,7 @@ // CHECK-ASAN-COV-LINUX-NOT: libclang_rt.ubsan // CHECK-ASAN-COV-LINUX-NOT: "-lstdc++" // CHECK-ASAN-COV-LINUX: "-lpthread" -// CHECK-ASAN-COV-LINUX: "-lresolv" +// CHECK-ASAN-COV-LINUX-NOT: "-lresolv" // RUN: %clang -fsanitize=memory -fsanitize-coverage=func -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -610,7 +610,7 @@ // CHECK-DFSAN-COV-LINUX-NOT: libclang_rt.ubsan // CHECK-DFSAN-COV-LINUX-NOT: "-lstdc++" // CHECK-DFSAN-COV-LINUX: "-lpthread" -// CHECK-DFSAN-COV-LINUX: "-lresolv" +// CHECK-DFSAN-COV-LINUX-NOT: "-lresolv" // RUN: %clang -fsanitize=undefined -fsanitize-coverage=func -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -621,7 +621,7 @@ // CHECK-UBSAN-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone.a" "--no-whole-archive" // CHECK-UBSAN-COV-LINUX-NOT: "-lstdc++" // CHECK-UBSAN-COV-LINUX: "-lpthread" -// CHECK-UBSAN-COV-LINUX: "-lresolv" +// CHECK-UBSAN-COV-LINUX-NOT: "-lresolv" // RUN: %clang -fsanitize-coverage=func -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -632,7 +632,7 @@ // CHECK-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone.a" "--no-whole-archive" // CHECK-COV-LINUX-NOT: "-lstdc++" // CHECK-COV-LINUX: "-lpthread" -// CHECK-COV-LINUX: "-lresolv" +// CHECK-COV-LINUX-NOT: "-lresolv" // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld -fsanitize=numerical \ @@ -644,7 +644,8 @@ // CHECK-NSAN-LINUX-NOT: "-lc" // CHECK-NSAN-LINUX-NOT: libclang_rt.ubsan // CHECK-NSAN-LINUX: libclang_rt.nsan.a" -// CHECK-NSAN-LINUX: "-lpthread" "-lrt" "-lm" "-ldl" "-lresolv" +// CHECK-NSAN-LINUX: "-lpthread" "-lrt" "-lm" "-ldl" +// CHECK-NSAN-LINUX-NOT: "-lresolv" // RUN: %clang -### %s 2>&1 --target=x86_64-unknown-linux -fuse-ld=ld -fsanitize=numerical -shared-libsan \ // RUN: -resource-dir=%S/Inputs/resource_dir \ @@ -757,7 +758,7 @@ // CHECK-SAFESTACK-LINUX: libclang_rt.safestack.a" // CHECK-SAFESTACK-LINUX: "-lpthread" // CHECK-SAFESTACK-LINUX: "-ldl" -// CHECK-SAFESTACK-LINUX: "-lresolv" +// CHECK-SAFESTACK-LINUX-NOT: "-lresolv" // RUN: %clang -fsanitize=shadow-call-stack -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ @@ -957,7 +958,7 @@ // CHECK-SCUDO-LINUX-NOT: "-lstdc++" // CHECK-SCUDO-LINUX: "-lpthread" // CHECK-SCUDO-LINUX: "-ldl" -// CHECK-SCUDO-LINUX: "-lresolv" +// CHECK-SCUDO-LINUX-NOT: "-lresolv" // RUN: %clang -### %s -o %t.so -shared 2>&1 \ // RUN: --target=i386-unknown-linux -fuse-ld=ld -fsanitize=scudo -shared-libsan \ @@ -1018,7 +1019,7 @@ // CHECK-HWASAN-X86-64-LINUX: "-lpthread" // CHECK-HWASAN-X86-64-LINUX: "-lrt" // CHECK-HWASAN-X86-64-LINUX: "-ldl" -// CHECK-HWASAN-X86-64-LINUX: "-lresolv" +// CHECK-HWASAN-X86-64-LINUX-NOT: "-lresolv" // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \ @@ -1067,7 +1068,7 @@ // CHECK-HWASAN-AARCH64-LINUX: "-lpthread" // CHECK-HWASAN-AARCH64-LINUX: "-lrt" // CHECK-HWASAN-AARCH64-LINUX: "-ldl" -// CHECK-HWASAN-AARCH64-LINUX: "-lresolv" +// CHECK-HWASAN-AARCH64-LINUX-NOT: "-lresolv" // RUN: %clang -### %s 2>&1 \ // RUN: --target=aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \ diff --git a/clang/test/Format/docs_updated.test b/clang/test/Format/docs_updated.test new file mode 100644 index 0000000000000..17066650a1267 --- /dev/null +++ b/clang/test/Format/docs_updated.test @@ -0,0 +1,5 @@ +// RUN: %python %S/../../docs/tools/dump_format_style.py -o %t.style +// RUN: diff %t.style %S/../../docs/ClangFormatStyleOptions.rst + +// RUN: %python %S/../../docs/tools/dump_format_help.py -o %t.help +// RUN: diff %t.help %S/../../docs/ClangFormat.rst diff --git a/clang/test/Format/lit.local.cfg b/clang/test/Format/lit.local.cfg index 3eb0f54ceaa6f..8acf02725d701 100644 --- a/clang/test/Format/lit.local.cfg +++ b/clang/test/Format/lit.local.cfg @@ -17,4 +17,5 @@ config.suffixes = [ ".textpb", ".asciipb", ".td", + ".test" ] diff --git a/clang/test/Headers/__clang_hip_math_ocml_rounded_ops.hip b/clang/test/Headers/__clang_hip_math_ocml_rounded_ops.hip index 9e30c2c9c2ccb..9bccb0f571643 100644 --- a/clang/test/Headers/__clang_hip_math_ocml_rounded_ops.hip +++ b/clang/test/Headers/__clang_hip_math_ocml_rounded_ops.hip @@ -297,9 +297,9 @@ extern "C" __device__ double test___dmul_rz(double x, double y) { // CHECK-LABEL: @test___drcp_rd( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double +// CHECK-NEXT: [[CONV:%.*]] = fpext contract float [[X:%.*]] to double // CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_div_rtn_f64(double noundef 1.000000e+00, double noundef [[CONV]]) #[[ATTR3]] -// CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float +// CHECK-NEXT: [[CONV1:%.*]] = fptrunc contract double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // extern "C" __device__ float test___drcp_rd(float x) { @@ -308,9 +308,9 @@ extern "C" __device__ float test___drcp_rd(float x) { // CHECK-LABEL: @test___drcp_rn( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double +// CHECK-NEXT: [[CONV:%.*]] = fpext contract float [[X:%.*]] to double // CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_div_rte_f64(double noundef 1.000000e+00, double noundef [[CONV]]) #[[ATTR3]] -// CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float +// CHECK-NEXT: [[CONV1:%.*]] = fptrunc contract double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // extern "C" __device__ float test___drcp_rn(float x) { @@ -319,9 +319,9 @@ extern "C" __device__ float test___drcp_rn(float x) { // CHECK-LABEL: @test___drcp_ru( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double +// CHECK-NEXT: [[CONV:%.*]] = fpext contract float [[X:%.*]] to double // CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_div_rtp_f64(double noundef 1.000000e+00, double noundef [[CONV]]) #[[ATTR3]] -// CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float +// CHECK-NEXT: [[CONV1:%.*]] = fptrunc contract double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // extern "C" __device__ float test___drcp_ru(float x) { @@ -330,9 +330,9 @@ extern "C" __device__ float test___drcp_ru(float x) { // CHECK-LABEL: @test___drcp_rz( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double +// CHECK-NEXT: [[CONV:%.*]] = fpext contract float [[X:%.*]] to double // CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_div_rtz_f64(double noundef 1.000000e+00, double noundef [[CONV]]) #[[ATTR3]] -// CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float +// CHECK-NEXT: [[CONV1:%.*]] = fptrunc contract double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // extern "C" __device__ float test___drcp_rz(float x) { @@ -341,9 +341,9 @@ extern "C" __device__ float test___drcp_rz(float x) { // CHECK-LABEL: @test___dsqrt_rd( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double +// CHECK-NEXT: [[CONV:%.*]] = fpext contract float [[X:%.*]] to double // CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sqrt_rtn_f64(double noundef [[CONV]]) #[[ATTR3]] -// CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float +// CHECK-NEXT: [[CONV1:%.*]] = fptrunc contract double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // extern "C" __device__ float test___dsqrt_rd(float x) { @@ -352,9 +352,9 @@ extern "C" __device__ float test___dsqrt_rd(float x) { // CHECK-LABEL: @test___dsqrt_rn( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double +// CHECK-NEXT: [[CONV:%.*]] = fpext contract float [[X:%.*]] to double // CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sqrt_rte_f64(double noundef [[CONV]]) #[[ATTR3]] -// CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float +// CHECK-NEXT: [[CONV1:%.*]] = fptrunc contract double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // extern "C" __device__ float test___dsqrt_rn(float x) { @@ -363,9 +363,9 @@ extern "C" __device__ float test___dsqrt_rn(float x) { // CHECK-LABEL: @test___dsqrt_ru( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double +// CHECK-NEXT: [[CONV:%.*]] = fpext contract float [[X:%.*]] to double // CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sqrt_rtp_f64(double noundef [[CONV]]) #[[ATTR3]] -// CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float +// CHECK-NEXT: [[CONV1:%.*]] = fptrunc contract double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // extern "C" __device__ float test___dsqrt_ru(float x) { @@ -374,9 +374,9 @@ extern "C" __device__ float test___dsqrt_ru(float x) { // CHECK-LABEL: @test___dsqrt_rz( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double +// CHECK-NEXT: [[CONV:%.*]] = fpext contract float [[X:%.*]] to double // CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sqrt_rtz_f64(double noundef [[CONV]]) #[[ATTR3]] -// CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float +// CHECK-NEXT: [[CONV1:%.*]] = fptrunc contract double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // extern "C" __device__ float test___dsqrt_rz(float x) { diff --git a/clang/test/Index/print-type.cpp b/clang/test/Index/print-type.cpp index b64469e921a8d..35bf511303332 100644 --- a/clang/test/Index/print-type.cpp +++ b/clang/test/Index/print-type.cpp @@ -163,7 +163,7 @@ inline namespace InlineNS {} // CHECK: DeclRefExpr=i:44:14 [type=int] [typekind=Int] [isPOD=1] // CHECK: StructDecl=Blob:46:8 (Definition) [type=Blob] [typekind=Record] [isPOD=1] [nbFields=2] // CHECK: FieldDecl=i:47:7 (Definition) [type=int] [typekind=Int] [isPOD=1] -// CHECK: VarDecl=member_pointer:50:12 (Definition) [type=int Blob::*] [typekind=MemberPointer] [isPOD=1] +// CHECK: VarDecl=member_pointer:50:12 (Definition) [type=int Blob::*] [typekind=MemberPointer] [canonicaltype=int Blob::*] [canonicaltypekind=MemberPointer] [isPOD=1] // CHECK: FunctionDecl=elaboratedNamespaceType:52:42 [type=NS::Type (const NS::Type)] [typekind=FunctionProto] [canonicaltype=NS::Type (NS::Type)] [canonicaltypekind=FunctionProto] [resulttype=NS::Type] [resulttypekind=Elaborated] [args= [const NS::Type] [Elaborated]] [isPOD=0] // CHECK: NamespaceRef=NS:52:11 [type=] [typekind=Invalid] [isPOD=0] // CHECK: TypeRef=struct NS::Type:52:23 [type=NS::Type] [typekind=Record] [isPOD=1] diff --git a/clang/test/Layout/ms-x86-member-pointers.cpp b/clang/test/Layout/ms-x86-member-pointers.cpp index a45359f23a9c4..3952226e7d787 100644 --- a/clang/test/Layout/ms-x86-member-pointers.cpp +++ b/clang/test/Layout/ms-x86-member-pointers.cpp @@ -17,56 +17,56 @@ struct UF { char a; int (U::*mp)(); }; // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct SD // CHECK-NEXT: 0 | char a -// CHECK-NEXT: 4 | int struct S::* mp +// CHECK-NEXT: 4 | int S::* mp // CHECK-NEXT: | [sizeof=8, align=4 // CHECK-NEXT: | nvsize=8, nvalign=4] // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct MD // CHECK-NEXT: 0 | char a -// CHECK-NEXT: 4 | int struct M::* mp +// CHECK-NEXT: 4 | int M::* mp // CHECK-NEXT: | [sizeof=8, align=4 // CHECK-NEXT: | nvsize=8, nvalign=4] // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct VD // CHECK-NEXT: 0 | char a -// CHECK-NEXT: 8 | int struct V::* mp +// CHECK-NEXT: 8 | int V::* mp // CHECK-NEXT: | [sizeof=16, align=8 // CHECK-NEXT: | nvsize=16, nvalign=8] // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct UD // CHECK-NEXT: 0 | char a -// CHECK-NEXT: 8 | int struct U::* mp +// CHECK-NEXT: 8 | int U::* mp // CHECK-NEXT: | [sizeof=24, align=8 // CHECK-NEXT: | nvsize=24, nvalign=8] // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct SF // CHECK-NEXT: 0 | char a -// CHECK-NEXT: 4 | int (struct S::*)(void) __attribute__((thiscall)) mp +// CHECK-NEXT: 4 | int (S::*)(void) __attribute__((thiscall)) mp // CHECK-NEXT: | [sizeof=8, align=4 // CHECK-NEXT: | nvsize=8, nvalign=4] // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct MF // CHECK-NEXT: 0 | char a -// CHECK-NEXT: 8 | int (struct M::*)(void) __attribute__((thiscall)) mp +// CHECK-NEXT: 8 | int (M::*)(void) __attribute__((thiscall)) mp // CHECK-NEXT: | [sizeof=16, align=8 // CHECK-NEXT: | nvsize=16, nvalign=8] // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct VF // CHECK-NEXT: 0 | char a -// CHECK-NEXT: 8 | int (struct V::*)(void) __attribute__((thiscall)) mp +// CHECK-NEXT: 8 | int (V::*)(void) __attribute__((thiscall)) mp // CHECK-NEXT: | [sizeof=24, align=8 // CHECK-NEXT: | nvsize=24, nvalign=8] // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct UF // CHECK-NEXT: 0 | char a -// CHECK-NEXT: 8 | int (struct U::*)(void) __attribute__((thiscall)) mp +// CHECK-NEXT: 8 | int (U::*)(void) __attribute__((thiscall)) mp // CHECK-NEXT: | [sizeof=24, align=8 // CHECK-NEXT: | nvsize=24, nvalign=8] diff --git a/clang/test/Misc/target-invalid-cpu-note/aarch64.c b/clang/test/Misc/target-invalid-cpu-note/aarch64.c index ab83f299ac599..e6ff09557fe07 100644 --- a/clang/test/Misc/target-invalid-cpu-note/aarch64.c +++ b/clang/test/Misc/target-invalid-cpu-note/aarch64.c @@ -67,6 +67,7 @@ // CHECK-SAME: {{^}}, exynos-m4 // CHECK-SAME: {{^}}, exynos-m5 // CHECK-SAME: {{^}}, falkor +// CHECK-SAME: {{^}}, fujitsu-monaka // CHECK-SAME: {{^}}, generic // CHECK-SAME: {{^}}, grace // CHECK-SAME: {{^}}, kryo diff --git a/clang/test/Misc/target-invalid-cpu-note/arm.c b/clang/test/Misc/target-invalid-cpu-note/arm.c index 17280a9edd221..12acdabbb7756 100644 --- a/clang/test/Misc/target-invalid-cpu-note/arm.c +++ b/clang/test/Misc/target-invalid-cpu-note/arm.c @@ -84,6 +84,7 @@ // CHECK-SAME: {{^}}, cortex-a78 // CHECK-SAME: {{^}}, cortex-a78ae // CHECK-SAME: {{^}}, cortex-a78c +// CHECK-SAME: {{^}}, cortex-a510 // CHECK-SAME: {{^}}, cortex-a710 // CHECK-SAME: {{^}}, cortex-x1 // CHECK-SAME: {{^}}, cortex-x1c diff --git a/clang/test/Modules/prune-non-affecting-module-map-repeated-textual.cpp b/clang/test/Modules/prune-non-affecting-module-map-repeated-textual.cpp new file mode 100644 index 0000000000000..30914056c55fa --- /dev/null +++ b/clang/test/Modules/prune-non-affecting-module-map-repeated-textual.cpp @@ -0,0 +1,104 @@ +// Same as prune-non-affecting-module-map-repeated.cpp, but check that textual-only +// inclusions do not cause duplication of the module map files they are defined in. + +// RUN: rm -rf %t && mkdir %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -xc++ -fmodules -fno-implicit-modules \ +// RUN: -fmodule-map-file=%t/base.map -fmodule-map-file=%t/mixed.map\ +// RUN: -fmodule-map-file=%t/mod1.map \ +// RUN: -fmodule-name=mod1 -emit-module %t/mod1.map -o %t/mod1.pcm +// RUN: %clang_cc1 -xc++ -fmodules -fno-implicit-modules \ +// RUN: -fmodule-map-file=%t/mixed.map\ +// RUN: -fmodule-name=mixed -emit-module %t/mixed.map -o %t/mixed.pcm +// RUN: %clang_cc1 -xc++ -fmodules -fno-implicit-modules \ +// RUN: -fmodule-map-file=%t/base.map -fmodule-map-file=%t/mod1.map -fmodule-map-file=%t/mod2.map \ +// RUN: -fmodule-file=%t/mod1.pcm -fmodule-file=%t/mixed.pcm \ +// RUN: -fmodule-name=mod2 -emit-module %t/mod2.map -o %t/mod2.pcm +// RUN: %clang_cc1 -xc++ -fmodules -fno-implicit-modules \ +// RUN: -fmodule-map-file=%t/base.map -fmodule-map-file=%t/mod2.map -fmodule-map-file=%t/mod3.map \ +// RUN: -fmodule-file=%t/mod2.pcm -fmodule-file=%t/mixed.pcm \ +// RUN: -fmodule-name=mod3 -emit-module %t/mod3.map -o %t/mod3.pcm +// RUN: %clang_cc1 -xc++ -fmodules -fno-implicit-modules \ +// RUN: -fmodule-map-file=%t/base.map -fmodule-map-file=%t/mod3.map -fmodule-map-file=%t/mod4.map \ +// RUN: -fmodule-file=%t/mod3.pcm \ +// RUN: -fmodule-name=mod4 -emit-module %t/mod4.map -o %t/mod4.pcm +// RUN: %clang_cc1 -xc++ -fmodules -fno-implicit-modules -fmodule-map-file=%t/base.map -fmodule-map-file=%t/mod4.map -fmodule-file=%t/mod4.pcm -fsyntax-only -verify %t/check_slocs.cc + +//--- base.map +module base { textual header "vector.h" } +//--- mixed.map +module mixed { textual header "mixed_text.h" header "mixed_mod.h"} +//--- mod1.map +module mod1 { header "mod1.h" } +//--- mod2.map +module mod2 { header "mod2.h" } +//--- mod3.map +module mod3 { header "mod3.h" } +//--- mod4.map +module mod4 { header "mod4.h" } +//--- check_slocs.cc +#include "mod4.h" +#include "vector.h" +#pragma clang __debug sloc_usage // expected-remark {{source manager location address space usage}} +// expected-note@* {{% of available space}} + +// base.map must only be present once, despite being used in each module. +// Because its location in every module compile should be non-affecting. + +// expected-note@base.map:1 {{file entered 1 time}} + +// different modules use either only textual header from mixed.map or both textual and modular +// headers. Either combination must lead to only 1 use at the end, because the module is ultimately +// in the import chain and any textual uses should not change that. + +// expected-note@mixed.map:1 {{file entered 1 time}} + +// expected-note@* + {{file entered}} + + +//--- vector.h +#ifndef VECTOR_H +#define VECTOR_H +#endif + +//--- mixed_text.h +#ifndef MIXED_TEXT_H +#define MIXED_TEXT_H +#endif +//--- mixed_mod.h +#ifndef MIXED_MOD_H +#define MIXED_MOD_H +#endif + +//--- mod1.h +#ifndef MOD1 +#define MOD1 +#include "vector.h" +#include "mixed_text.h" +int mod1(); +#endif +//--- mod2.h +#ifndef MOD2 +#define MOD2 +#include "vector.h" +#include "mod1.h" +#include "mixed_mod.h" +int mod2(); +#endif +//--- mod3.h +#ifndef MOD3 +#define MOD3 +#include "vector.h" +#include "mod2.h" +#include "mixed_text.h" +#include "mixed_mod.h" +int mod3(); +#endif +//--- mod4.h +#ifndef MOD4 +#define MOD4 +#include "vector.h" +#include "mod3.h" +int mod4(); +#endif diff --git a/clang/test/OpenMP/nvptx_target_parallel_reduction_codegen_tbaa_PR46146.cpp b/clang/test/OpenMP/nvptx_target_parallel_reduction_codegen_tbaa_PR46146.cpp index cec9700f2fccd..232cfdad043f0 100644 --- a/clang/test/OpenMP/nvptx_target_parallel_reduction_codegen_tbaa_PR46146.cpp +++ b/clang/test/OpenMP/nvptx_target_parallel_reduction_codegen_tbaa_PR46146.cpp @@ -43,7 +43,7 @@ void test() { // CHECK1: user_code.entry: // CHECK1-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) // CHECK1-NEXT: store i32 0, ptr [[DOTZERO_ADDR]], align 4 -// CHECK1-NEXT: store i32 [[TMP1]], ptr [[DOTTHREADID_TEMP_]], align 4, !tbaa [[TBAA14:![0-9]+]] +// CHECK1-NEXT: store i32 [[TMP1]], ptr [[DOTTHREADID_TEMP_]], align 4, !tbaa [[TBAA15:![0-9]+]] // CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z17complex_reductionIfEvv_l16_omp_outlined(ptr [[DOTTHREADID_TEMP_]], ptr [[DOTZERO_ADDR]]) #[[ATTR4:[0-9]+]] // CHECK1-NEXT: call void @__kmpc_target_deinit() // CHECK1-NEXT: ret void @@ -66,78 +66,78 @@ void test() { // CHECK1-NEXT: [[REF_TMP:%.*]] = alloca float, align 4 // CHECK1-NEXT: [[REF_TMP2:%.*]] = alloca float, align 4 // CHECK1-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [3 x ptr], align 8 -// CHECK1-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8, !tbaa [[TBAA17:![0-9]+]] +// CHECK1-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8, !tbaa [[TBAA17]] // CHECK1-NEXT: [[ISTART:%.*]] = call align 16 ptr @__kmpc_alloc_shared(i64 4) // CHECK1-NEXT: [[IEND:%.*]] = call align 16 ptr @__kmpc_alloc_shared(i64 4) // CHECK1-NEXT: [[PARTIAL_SUM:%.*]] = call align 16 ptr @__kmpc_alloc_shared(i64 8) // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_IV]]) #[[ATTR4]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_LB]]) #[[ATTR4]] -// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_UB]]) #[[ATTR4]] -// CHECK1-NEXT: store i32 99, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 99, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_STRIDE]]) #[[ATTR4]] -// CHECK1-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_IS_LAST]]) #[[ATTR4]] -// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[IB]]) #[[ATTR4]] // CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @__kmpc_distribute_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP1]], i32 92, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) -// CHECK1-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP2]], 99 // CHECK1-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] // CHECK1: cond.true: // CHECK1-NEXT: br label [[COND_END:%.*]] // CHECK1: cond.false: -// CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: br label [[COND_END]] // CHECK1: cond.end: // CHECK1-NEXT: [[COND:%.*]] = phi i32 [ 99, [[COND_TRUE]] ], [ [[TMP3]], [[COND_FALSE]] ] -// CHECK1-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: store i32 [[TMP4]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: store i32 [[TMP4]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] // CHECK1: omp.inner.for.cond: -// CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[CMP1:%.*]] = icmp sle i32 [[TMP5]], [[TMP6]] // CHECK1-NEXT: br i1 [[CMP1]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]] // CHECK1: omp.inner.for.cond.cleanup: // CHECK1-NEXT: br label [[OMP_INNER_FOR_END:%.*]] // CHECK1: omp.inner.for.body: -// CHECK1-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP7]], 1 // CHECK1-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] -// CHECK1-NEXT: store i32 [[ADD]], ptr [[IB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[ADD]], ptr [[IB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[REF_TMP]]) #[[ATTR4]] -// CHECK1-NEXT: store float 0.000000e+00, ptr [[REF_TMP]], align 4, !tbaa [[TBAA16:![0-9]+]] +// CHECK1-NEXT: store float 0.000000e+00, ptr [[REF_TMP]], align 4, !tbaa [[TBAA19:![0-9]+]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[REF_TMP2]]) #[[ATTR4]] -// CHECK1-NEXT: store float 0.000000e+00, ptr [[REF_TMP2]], align 4, !tbaa [[TBAA16]] +// CHECK1-NEXT: store float 0.000000e+00, ptr [[REF_TMP2]], align 4, !tbaa [[TBAA19]] // CHECK1-NEXT: call void @_ZNSt7complexIfEC1ERKfS2_(ptr nonnull align 4 dereferenceable(8) [[PARTIAL_SUM]], ptr nonnull align 4 dereferenceable(4) [[REF_TMP]], ptr nonnull align 4 dereferenceable(4) [[REF_TMP2]]) #[[ATTR11:[0-9]+]] // CHECK1-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[REF_TMP2]]) #[[ATTR4]] // CHECK1-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[REF_TMP]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[IB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[IB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[MUL3:%.*]] = mul nsw i32 [[TMP8]], 4 -// CHECK1-NEXT: store i32 [[MUL3]], ptr [[ISTART]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[IB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[MUL3]], ptr [[ISTART]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[IB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[ADD4:%.*]] = add nsw i32 [[TMP9]], 1 // CHECK1-NEXT: [[MUL5:%.*]] = mul nsw i32 [[ADD4]], 4 -// CHECK1-NEXT: store i32 [[MUL5]], ptr [[IEND]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[MUL5]], ptr [[IEND]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[CAPTURED_VARS_ADDRS]], i64 0, i64 0 -// CHECK1-NEXT: store ptr [[ISTART]], ptr [[TMP10]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[ISTART]], ptr [[TMP10]], align 8, !tbaa [[TBAA21:![0-9]+]] // CHECK1-NEXT: [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[CAPTURED_VARS_ADDRS]], i64 0, i64 1 -// CHECK1-NEXT: store ptr [[IEND]], ptr [[TMP11]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[IEND]], ptr [[TMP11]], align 8, !tbaa [[TBAA21]] // CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[CAPTURED_VARS_ADDRS]], i64 0, i64 2 -// CHECK1-NEXT: store ptr [[PARTIAL_SUM]], ptr [[TMP12]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[PARTIAL_SUM]], ptr [[TMP12]], align 8, !tbaa [[TBAA21]] // CHECK1-NEXT: call void @__kmpc_parallel_51(ptr @[[GLOB1]], i32 [[TMP1]], i32 1, i32 -1, i32 -1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z17complex_reductionIfEvv_l16_omp_outlined_omp_outlined, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z17complex_reductionIfEvv_l16_omp_outlined_omp_outlined_wrapper, ptr [[CAPTURED_VARS_ADDRS]], i64 3) // CHECK1-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] // CHECK1: omp.body.continue: // CHECK1-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] // CHECK1: omp.inner.for.inc: -// CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[ADD6:%.*]] = add nsw i32 [[TMP13]], 1 -// CHECK1-NEXT: store i32 [[ADD6]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[ADD6]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: br label [[OMP_INNER_FOR_COND]] // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] @@ -161,9 +161,9 @@ void test() { // CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[__RE_ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[__IM_ADDR:%.*]] = alloca ptr, align 8 -// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[__RE]], ptr [[__RE_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[__IM]], ptr [[__IM_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA23:![0-9]+]] +// CHECK1-NEXT: store ptr [[__RE]], ptr [[__RE_ADDR]], align 8, !tbaa [[TBAA25:![0-9]+]] +// CHECK1-NEXT: store ptr [[__IM]], ptr [[__IM_ADDR]], align 8, !tbaa [[TBAA25]] // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__RE_ADDR]], align 8 // CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__IM_ADDR]], align 8 @@ -197,79 +197,79 @@ void test() { // CHECK1-NEXT: [[REF_TMP15:%.*]] = alloca float, align 4 // CHECK1-NEXT: [[REF_TMP16:%.*]] = alloca float, align 4 // CHECK1-NEXT: [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8 -// CHECK1-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[ISTART]], ptr [[ISTART_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[IEND]], ptr [[IEND_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[PARTIAL_SUM]], ptr [[PARTIAL_SUM_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ISTART_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[IEND_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[PARTIAL_SUM_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8, !tbaa [[TBAA17]] +// CHECK1-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8, !tbaa [[TBAA17]] +// CHECK1-NEXT: store ptr [[ISTART]], ptr [[ISTART_ADDR]], align 8, !tbaa [[TBAA17]] +// CHECK1-NEXT: store ptr [[IEND]], ptr [[IEND_ADDR]], align 8, !tbaa [[TBAA17]] +// CHECK1-NEXT: store ptr [[PARTIAL_SUM]], ptr [[PARTIAL_SUM_ADDR]], align 8, !tbaa [[TBAA23]] +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ISTART_ADDR]], align 8, !tbaa [[TBAA17]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[IEND_ADDR]], align 8, !tbaa [[TBAA17]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[PARTIAL_SUM_ADDR]], align 8, !tbaa [[TBAA23]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_IV]]) #[[ATTR4]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTCAPTURE_EXPR_]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP0]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: store i32 [[TMP3]], ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP0]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: store i32 [[TMP3]], ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTCAPTURE_EXPR_1]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP1]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: store i32 [[TMP4]], ptr [[DOTCAPTURE_EXPR_1]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP1]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: store i32 [[TMP4]], ptr [[DOTCAPTURE_EXPR_1]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTCAPTURE_EXPR_2]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[SUB:%.*]] = sub i32 [[TMP5]], [[TMP6]] // CHECK1-NEXT: [[SUB3:%.*]] = sub i32 [[SUB]], 1 // CHECK1-NEXT: [[ADD:%.*]] = add i32 [[SUB3]], 1 // CHECK1-NEXT: [[DIV:%.*]] = udiv i32 [[ADD]], 1 // CHECK1-NEXT: [[SUB4:%.*]] = sub i32 [[DIV]], 1 -// CHECK1-NEXT: store i32 [[SUB4]], ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[SUB4]], ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[I]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: store i32 [[TMP7]], ptr [[I]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: store i32 [[TMP7]], ptr [[I]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[I]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP8]], [[TMP9]] // CHECK1-NEXT: br i1 [[CMP]], label [[OMP_PRECOND_THEN:%.*]], label [[OMP_PRECOND_END:%.*]] // CHECK1: omp.precond.then: // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_LB]]) #[[ATTR4]] -// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_UB]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: store i32 [[TMP10]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: store i32 [[TMP10]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_STRIDE]]) #[[ATTR4]] -// CHECK1-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_IS_LAST]]) #[[ATTR4]] -// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[PARTIAL_SUM5]]) #[[ATTR4]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[REF_TMP]]) #[[ATTR4]] -// CHECK1-NEXT: store float 0.000000e+00, ptr [[REF_TMP]], align 4, !tbaa [[TBAA16]] +// CHECK1-NEXT: store float 0.000000e+00, ptr [[REF_TMP]], align 4, !tbaa [[TBAA19]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[REF_TMP6]]) #[[ATTR4]] -// CHECK1-NEXT: store float 0.000000e+00, ptr [[REF_TMP6]], align 4, !tbaa [[TBAA16]] +// CHECK1-NEXT: store float 0.000000e+00, ptr [[REF_TMP6]], align 4, !tbaa [[TBAA19]] // CHECK1-NEXT: call void @_ZNSt7complexIfEC1ERKfS2_(ptr nonnull align 4 dereferenceable(8) [[PARTIAL_SUM5]], ptr nonnull align 4 dereferenceable(4) [[REF_TMP]], ptr nonnull align 4 dereferenceable(4) [[REF_TMP6]]) #[[ATTR11]] // CHECK1-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[REF_TMP6]]) #[[ATTR4]] // CHECK1-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[REF_TMP]]) #[[ATTR4]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[I7]]) #[[ATTR4]] // CHECK1-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 -// CHECK1-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @__kmpc_for_static_init_4u(ptr @[[GLOB3:[0-9]+]], i32 [[TMP12]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK1-NEXT: br label [[OMP_DISPATCH_COND:%.*]] // CHECK1: omp.dispatch.cond: -// CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[CMP8:%.*]] = icmp ugt i32 [[TMP13]], [[TMP14]] // CHECK1-NEXT: br i1 [[CMP8]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] // CHECK1: cond.true: -// CHECK1-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: br label [[COND_END:%.*]] // CHECK1: cond.false: -// CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: br label [[COND_END]] // CHECK1: cond.end: // CHECK1-NEXT: [[COND:%.*]] = phi i32 [ [[TMP15]], [[COND_TRUE]] ], [ [[TMP16]], [[COND_FALSE]] ] -// CHECK1-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: store i32 [[TMP17]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: store i32 [[TMP17]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[ADD9:%.*]] = add i32 [[TMP19]], 1 // CHECK1-NEXT: [[CMP10:%.*]] = icmp ult i32 [[TMP18]], [[ADD9]] // CHECK1-NEXT: br i1 [[CMP10]], label [[OMP_DISPATCH_BODY:%.*]], label [[OMP_DISPATCH_CLEANUP:%.*]] @@ -278,28 +278,28 @@ void test() { // CHECK1: omp.dispatch.body: // CHECK1-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] // CHECK1: omp.inner.for.cond: -// CHECK1-NEXT: [[TMP20:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP20:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[ADD11:%.*]] = add i32 [[TMP21]], 1 // CHECK1-NEXT: [[CMP12:%.*]] = icmp ult i32 [[TMP20]], [[ADD11]] // CHECK1-NEXT: br i1 [[CMP12]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]] // CHECK1: omp.inner.for.cond.cleanup: // CHECK1-NEXT: br label [[OMP_INNER_FOR_END:%.*]] // CHECK1: omp.inner.for.body: -// CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[MUL:%.*]] = mul i32 [[TMP23]], 1 // CHECK1-NEXT: [[ADD13:%.*]] = add i32 [[TMP22]], [[MUL]] -// CHECK1-NEXT: store i32 [[ADD13]], ptr [[I7]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[ADD13]], ptr [[I7]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[REF_TMP14]]) #[[ATTR4]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[REF_TMP15]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP24:%.*]] = load i32, ptr [[I7]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP24:%.*]] = load i32, ptr [[I7]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP24]] to float -// CHECK1-NEXT: store float [[CONV]], ptr [[REF_TMP15]], align 4, !tbaa [[TBAA16]] +// CHECK1-NEXT: store float [[CONV]], ptr [[REF_TMP15]], align 4, !tbaa [[TBAA19]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[REF_TMP16]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP25:%.*]] = load i32, ptr [[I7]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP25:%.*]] = load i32, ptr [[I7]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[CONV17:%.*]] = sitofp i32 [[TMP25]] to float -// CHECK1-NEXT: store float [[CONV17]], ptr [[REF_TMP16]], align 4, !tbaa [[TBAA16]] +// CHECK1-NEXT: store float [[CONV17]], ptr [[REF_TMP16]], align 4, !tbaa [[TBAA19]] // CHECK1-NEXT: call void @_ZNSt7complexIfEC1ERKfS2_(ptr nonnull align 4 dereferenceable(8) [[REF_TMP14]], ptr nonnull align 4 dereferenceable(4) [[REF_TMP15]], ptr nonnull align 4 dereferenceable(4) [[REF_TMP16]]) #[[ATTR11]] // CHECK1-NEXT: [[CALL:%.*]] = call nonnull align 4 dereferenceable(8) ptr @_ZNSt7complexIfEpLIfEERS0_RKS_IT_E(ptr nonnull align 4 dereferenceable(8) [[PARTIAL_SUM5]], ptr nonnull align 4 dereferenceable(8) [[REF_TMP14]]) #[[ATTR11]] // CHECK1-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[REF_TMP16]]) #[[ATTR4]] @@ -309,25 +309,25 @@ void test() { // CHECK1: omp.body.continue: // CHECK1-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] // CHECK1: omp.inner.for.inc: -// CHECK1-NEXT: [[TMP26:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP26:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[ADD18:%.*]] = add i32 [[TMP26]], 1 -// CHECK1-NEXT: store i32 [[ADD18]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[ADD18]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: br label [[OMP_INNER_FOR_COND]] // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_DISPATCH_INC:%.*]] // CHECK1: omp.dispatch.inc: -// CHECK1-NEXT: [[TMP27:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP28:%.*]] = load i32, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP27:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP28:%.*]] = load i32, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[ADD19:%.*]] = add i32 [[TMP27]], [[TMP28]] -// CHECK1-NEXT: store i32 [[ADD19]], ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP29:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP30:%.*]] = load i32, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[ADD19]], ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP29:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP30:%.*]] = load i32, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[ADD20:%.*]] = add i32 [[TMP29]], [[TMP30]] -// CHECK1-NEXT: store i32 [[ADD20]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[ADD20]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK1: omp.dispatch.end: // CHECK1-NEXT: [[TMP31:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 -// CHECK1-NEXT: [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP32]]) // CHECK1-NEXT: [[TMP33:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 // CHECK1-NEXT: store ptr [[PARTIAL_SUM5]], ptr [[TMP33]], align 8 @@ -358,21 +358,21 @@ void test() { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[__C_ADDR:%.*]] = alloca ptr, align 8 -// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[__C]], ptr [[__C_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA23]] +// CHECK1-NEXT: store ptr [[__C]], ptr [[__C_ADDR]], align 8, !tbaa [[TBAA23]] // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__C_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__C_ADDR]], align 8, !tbaa [[TBAA23]] // CHECK1-NEXT: [[CALL:%.*]] = call float @_ZNKSt7complexIfE4realEv(ptr nonnull align 4 dereferenceable(8) [[TMP0]]) #[[ATTR11]] // CHECK1-NEXT: [[__RE_:%.*]] = getelementptr inbounds nuw %"class.std::complex", ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP1:%.*]] = load float, ptr [[__RE_]], align 4, !tbaa [[TBAA18:![0-9]+]] +// CHECK1-NEXT: [[TMP1:%.*]] = load float, ptr [[__RE_]], align 4, !tbaa [[TBAA27:![0-9]+]] // CHECK1-NEXT: [[ADD:%.*]] = fadd float [[TMP1]], [[CALL]] -// CHECK1-NEXT: store float [[ADD]], ptr [[__RE_]], align 4, !tbaa [[TBAA18]] -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[__C_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store float [[ADD]], ptr [[__RE_]], align 4, !tbaa [[TBAA27]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[__C_ADDR]], align 8, !tbaa [[TBAA23]] // CHECK1-NEXT: [[CALL2:%.*]] = call float @_ZNKSt7complexIfE4imagEv(ptr nonnull align 4 dereferenceable(8) [[TMP2]]) #[[ATTR11]] // CHECK1-NEXT: [[__IM_:%.*]] = getelementptr inbounds nuw %"class.std::complex", ptr [[THIS1]], i32 0, i32 1 -// CHECK1-NEXT: [[TMP3:%.*]] = load float, ptr [[__IM_]], align 4, !tbaa [[TBAA20:![0-9]+]] +// CHECK1-NEXT: [[TMP3:%.*]] = load float, ptr [[__IM_]], align 4, !tbaa [[TBAA29:![0-9]+]] // CHECK1-NEXT: [[ADD3:%.*]] = fadd float [[TMP3]], [[CALL2]] -// CHECK1-NEXT: store float [[ADD3]], ptr [[__IM_]], align 4, !tbaa [[TBAA20]] +// CHECK1-NEXT: store float [[ADD3]], ptr [[__IM_]], align 4, !tbaa [[TBAA29]] // CHECK1-NEXT: ret ptr [[THIS1]] // // @@ -507,17 +507,17 @@ void test() { // CHECK1-NEXT: [[DOTADDR1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[DOTZERO_ADDR:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[GLOBAL_ARGS:%.*]] = alloca ptr, align 8 -// CHECK1-NEXT: store i16 [[TMP0]], ptr [[DOTADDR]], align 2, !tbaa [[TBAA21:![0-9]+]] -// CHECK1-NEXT: store i32 [[TMP1]], ptr [[DOTADDR1]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i16 [[TMP0]], ptr [[DOTADDR]], align 2, !tbaa [[TBAA30:![0-9]+]] +// CHECK1-NEXT: store i32 [[TMP1]], ptr [[DOTADDR1]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: store i32 0, ptr [[DOTZERO_ADDR]], align 4 // CHECK1-NEXT: call void @__kmpc_get_shared_variables(ptr [[GLOBAL_ARGS]]) // CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[GLOBAL_ARGS]], align 8 // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds ptr, ptr [[TMP2]], i64 0 -// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8, !tbaa [[TBAA32:![0-9]+]] // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds ptr, ptr [[TMP2]], i64 1 -// CHECK1-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP5]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP5]], align 8, !tbaa [[TBAA32]] // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds ptr, ptr [[TMP2]], i64 2 -// CHECK1-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8, !tbaa [[TBAA34:![0-9]+]] // CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z17complex_reductionIfEvv_l16_omp_outlined_omp_outlined(ptr [[DOTADDR1]], ptr [[DOTZERO_ADDR]], ptr [[TMP4]], ptr [[TMP6]], ptr [[TMP8]]) #[[ATTR4]] // CHECK1-NEXT: ret void // @@ -535,7 +535,7 @@ void test() { // CHECK1: user_code.entry: // CHECK1-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) // CHECK1-NEXT: store i32 0, ptr [[DOTZERO_ADDR]], align 4 -// CHECK1-NEXT: store i32 [[TMP1]], ptr [[DOTTHREADID_TEMP_]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[TMP1]], ptr [[DOTTHREADID_TEMP_]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z17complex_reductionIdEvv_l16_omp_outlined(ptr [[DOTTHREADID_TEMP_]], ptr [[DOTZERO_ADDR]]) #[[ATTR4]] // CHECK1-NEXT: call void @__kmpc_target_deinit() // CHECK1-NEXT: ret void @@ -558,78 +558,78 @@ void test() { // CHECK1-NEXT: [[REF_TMP:%.*]] = alloca double, align 8 // CHECK1-NEXT: [[REF_TMP2:%.*]] = alloca double, align 8 // CHECK1-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [3 x ptr], align 8 -// CHECK1-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8, !tbaa [[TBAA17]] +// CHECK1-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8, !tbaa [[TBAA17]] // CHECK1-NEXT: [[ISTART:%.*]] = call align 16 ptr @__kmpc_alloc_shared(i64 4) // CHECK1-NEXT: [[IEND:%.*]] = call align 16 ptr @__kmpc_alloc_shared(i64 4) // CHECK1-NEXT: [[PARTIAL_SUM:%.*]] = call align 16 ptr @__kmpc_alloc_shared(i64 16) // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_IV]]) #[[ATTR4]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_LB]]) #[[ATTR4]] -// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_UB]]) #[[ATTR4]] -// CHECK1-NEXT: store i32 99, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 99, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_STRIDE]]) #[[ATTR4]] -// CHECK1-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_IS_LAST]]) #[[ATTR4]] -// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[IB]]) #[[ATTR4]] // CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @__kmpc_distribute_static_init_4(ptr @[[GLOB2]], i32 [[TMP1]], i32 92, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) -// CHECK1-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP2]], 99 // CHECK1-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] // CHECK1: cond.true: // CHECK1-NEXT: br label [[COND_END:%.*]] // CHECK1: cond.false: -// CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: br label [[COND_END]] // CHECK1: cond.end: // CHECK1-NEXT: [[COND:%.*]] = phi i32 [ 99, [[COND_TRUE]] ], [ [[TMP3]], [[COND_FALSE]] ] -// CHECK1-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: store i32 [[TMP4]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: store i32 [[TMP4]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] // CHECK1: omp.inner.for.cond: -// CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[CMP1:%.*]] = icmp sle i32 [[TMP5]], [[TMP6]] // CHECK1-NEXT: br i1 [[CMP1]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]] // CHECK1: omp.inner.for.cond.cleanup: // CHECK1-NEXT: br label [[OMP_INNER_FOR_END:%.*]] // CHECK1: omp.inner.for.body: -// CHECK1-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP7]], 1 // CHECK1-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] -// CHECK1-NEXT: store i32 [[ADD]], ptr [[IB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[ADD]], ptr [[IB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[REF_TMP]]) #[[ATTR4]] -// CHECK1-NEXT: store double 0.000000e+00, ptr [[REF_TMP]], align 8, !tbaa [[TBAA23:![0-9]+]] +// CHECK1-NEXT: store double 0.000000e+00, ptr [[REF_TMP]], align 8, !tbaa [[TBAA36:![0-9]+]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[REF_TMP2]]) #[[ATTR4]] -// CHECK1-NEXT: store double 0.000000e+00, ptr [[REF_TMP2]], align 8, !tbaa [[TBAA23]] +// CHECK1-NEXT: store double 0.000000e+00, ptr [[REF_TMP2]], align 8, !tbaa [[TBAA36]] // CHECK1-NEXT: call void @_ZNSt7complexIdEC1ERKdS2_(ptr nonnull align 8 dereferenceable(16) [[PARTIAL_SUM]], ptr nonnull align 8 dereferenceable(8) [[REF_TMP]], ptr nonnull align 8 dereferenceable(8) [[REF_TMP2]]) #[[ATTR11]] // CHECK1-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[REF_TMP2]]) #[[ATTR4]] // CHECK1-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[REF_TMP]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[IB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[IB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[MUL3:%.*]] = mul nsw i32 [[TMP8]], 4 -// CHECK1-NEXT: store i32 [[MUL3]], ptr [[ISTART]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[IB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[MUL3]], ptr [[ISTART]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[IB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[ADD4:%.*]] = add nsw i32 [[TMP9]], 1 // CHECK1-NEXT: [[MUL5:%.*]] = mul nsw i32 [[ADD4]], 4 -// CHECK1-NEXT: store i32 [[MUL5]], ptr [[IEND]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[MUL5]], ptr [[IEND]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[CAPTURED_VARS_ADDRS]], i64 0, i64 0 -// CHECK1-NEXT: store ptr [[ISTART]], ptr [[TMP10]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[ISTART]], ptr [[TMP10]], align 8, !tbaa [[TBAA21]] // CHECK1-NEXT: [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[CAPTURED_VARS_ADDRS]], i64 0, i64 1 -// CHECK1-NEXT: store ptr [[IEND]], ptr [[TMP11]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[IEND]], ptr [[TMP11]], align 8, !tbaa [[TBAA21]] // CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[CAPTURED_VARS_ADDRS]], i64 0, i64 2 -// CHECK1-NEXT: store ptr [[PARTIAL_SUM]], ptr [[TMP12]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[PARTIAL_SUM]], ptr [[TMP12]], align 8, !tbaa [[TBAA21]] // CHECK1-NEXT: call void @__kmpc_parallel_51(ptr @[[GLOB1]], i32 [[TMP1]], i32 1, i32 -1, i32 -1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z17complex_reductionIdEvv_l16_omp_outlined_omp_outlined, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z17complex_reductionIdEvv_l16_omp_outlined_omp_outlined_wrapper, ptr [[CAPTURED_VARS_ADDRS]], i64 3) // CHECK1-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] // CHECK1: omp.body.continue: // CHECK1-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] // CHECK1: omp.inner.for.inc: -// CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[ADD6:%.*]] = add nsw i32 [[TMP13]], 1 -// CHECK1-NEXT: store i32 [[ADD6]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[ADD6]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: br label [[OMP_INNER_FOR_COND]] // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] @@ -653,9 +653,9 @@ void test() { // CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[__RE_ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[__IM_ADDR:%.*]] = alloca ptr, align 8 -// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[__RE]], ptr [[__RE_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[__IM]], ptr [[__IM_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA38:![0-9]+]] +// CHECK1-NEXT: store ptr [[__RE]], ptr [[__RE_ADDR]], align 8, !tbaa [[TBAA40:![0-9]+]] +// CHECK1-NEXT: store ptr [[__IM]], ptr [[__IM_ADDR]], align 8, !tbaa [[TBAA40]] // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__RE_ADDR]], align 8 // CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__IM_ADDR]], align 8 @@ -689,79 +689,79 @@ void test() { // CHECK1-NEXT: [[REF_TMP15:%.*]] = alloca double, align 8 // CHECK1-NEXT: [[REF_TMP16:%.*]] = alloca double, align 8 // CHECK1-NEXT: [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8 -// CHECK1-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[ISTART]], ptr [[ISTART_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[IEND]], ptr [[IEND_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[PARTIAL_SUM]], ptr [[PARTIAL_SUM_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ISTART_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[IEND_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[PARTIAL_SUM_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8, !tbaa [[TBAA17]] +// CHECK1-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8, !tbaa [[TBAA17]] +// CHECK1-NEXT: store ptr [[ISTART]], ptr [[ISTART_ADDR]], align 8, !tbaa [[TBAA17]] +// CHECK1-NEXT: store ptr [[IEND]], ptr [[IEND_ADDR]], align 8, !tbaa [[TBAA17]] +// CHECK1-NEXT: store ptr [[PARTIAL_SUM]], ptr [[PARTIAL_SUM_ADDR]], align 8, !tbaa [[TBAA38]] +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ISTART_ADDR]], align 8, !tbaa [[TBAA17]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[IEND_ADDR]], align 8, !tbaa [[TBAA17]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[PARTIAL_SUM_ADDR]], align 8, !tbaa [[TBAA38]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_IV]]) #[[ATTR4]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTCAPTURE_EXPR_]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP0]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: store i32 [[TMP3]], ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP0]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: store i32 [[TMP3]], ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTCAPTURE_EXPR_1]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP1]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: store i32 [[TMP4]], ptr [[DOTCAPTURE_EXPR_1]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP1]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: store i32 [[TMP4]], ptr [[DOTCAPTURE_EXPR_1]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTCAPTURE_EXPR_2]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[SUB:%.*]] = sub i32 [[TMP5]], [[TMP6]] // CHECK1-NEXT: [[SUB3:%.*]] = sub i32 [[SUB]], 1 // CHECK1-NEXT: [[ADD:%.*]] = add i32 [[SUB3]], 1 // CHECK1-NEXT: [[DIV:%.*]] = udiv i32 [[ADD]], 1 // CHECK1-NEXT: [[SUB4:%.*]] = sub i32 [[DIV]], 1 -// CHECK1-NEXT: store i32 [[SUB4]], ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[SUB4]], ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[I]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: store i32 [[TMP7]], ptr [[I]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: store i32 [[TMP7]], ptr [[I]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[I]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP8]], [[TMP9]] // CHECK1-NEXT: br i1 [[CMP]], label [[OMP_PRECOND_THEN:%.*]], label [[OMP_PRECOND_END:%.*]] // CHECK1: omp.precond.then: // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_LB]]) #[[ATTR4]] -// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_UB]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: store i32 [[TMP10]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: store i32 [[TMP10]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_STRIDE]]) #[[ATTR4]] -// CHECK1-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[DOTOMP_IS_LAST]]) #[[ATTR4]] -// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 16, ptr [[PARTIAL_SUM5]]) #[[ATTR4]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[REF_TMP]]) #[[ATTR4]] -// CHECK1-NEXT: store double 0.000000e+00, ptr [[REF_TMP]], align 8, !tbaa [[TBAA23]] +// CHECK1-NEXT: store double 0.000000e+00, ptr [[REF_TMP]], align 8, !tbaa [[TBAA36]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[REF_TMP6]]) #[[ATTR4]] -// CHECK1-NEXT: store double 0.000000e+00, ptr [[REF_TMP6]], align 8, !tbaa [[TBAA23]] +// CHECK1-NEXT: store double 0.000000e+00, ptr [[REF_TMP6]], align 8, !tbaa [[TBAA36]] // CHECK1-NEXT: call void @_ZNSt7complexIdEC1ERKdS2_(ptr nonnull align 8 dereferenceable(16) [[PARTIAL_SUM5]], ptr nonnull align 8 dereferenceable(8) [[REF_TMP]], ptr nonnull align 8 dereferenceable(8) [[REF_TMP6]]) #[[ATTR11]] // CHECK1-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[REF_TMP6]]) #[[ATTR4]] // CHECK1-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[REF_TMP]]) #[[ATTR4]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[I7]]) #[[ATTR4]] // CHECK1-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 -// CHECK1-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @__kmpc_for_static_init_4u(ptr @[[GLOB3]], i32 [[TMP12]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK1-NEXT: br label [[OMP_DISPATCH_COND:%.*]] // CHECK1: omp.dispatch.cond: -// CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[CMP8:%.*]] = icmp ugt i32 [[TMP13]], [[TMP14]] // CHECK1-NEXT: br i1 [[CMP8]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] // CHECK1: cond.true: -// CHECK1-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: br label [[COND_END:%.*]] // CHECK1: cond.false: -// CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: br label [[COND_END]] // CHECK1: cond.end: // CHECK1-NEXT: [[COND:%.*]] = phi i32 [ [[TMP15]], [[COND_TRUE]] ], [ [[TMP16]], [[COND_FALSE]] ] -// CHECK1-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: store i32 [[TMP17]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: store i32 [[TMP17]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[ADD9:%.*]] = add i32 [[TMP19]], 1 // CHECK1-NEXT: [[CMP10:%.*]] = icmp ult i32 [[TMP18]], [[ADD9]] // CHECK1-NEXT: br i1 [[CMP10]], label [[OMP_DISPATCH_BODY:%.*]], label [[OMP_DISPATCH_CLEANUP:%.*]] @@ -770,28 +770,28 @@ void test() { // CHECK1: omp.dispatch.body: // CHECK1-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] // CHECK1: omp.inner.for.cond: -// CHECK1-NEXT: [[TMP20:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP20:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[ADD11:%.*]] = add i32 [[TMP21]], 1 // CHECK1-NEXT: [[CMP12:%.*]] = icmp ult i32 [[TMP20]], [[ADD11]] // CHECK1-NEXT: br i1 [[CMP12]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]] // CHECK1: omp.inner.for.cond.cleanup: // CHECK1-NEXT: br label [[OMP_INNER_FOR_END:%.*]] // CHECK1: omp.inner.for.body: -// CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[MUL:%.*]] = mul i32 [[TMP23]], 1 // CHECK1-NEXT: [[ADD13:%.*]] = add i32 [[TMP22]], [[MUL]] -// CHECK1-NEXT: store i32 [[ADD13]], ptr [[I7]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[ADD13]], ptr [[I7]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 16, ptr [[REF_TMP14]]) #[[ATTR4]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[REF_TMP15]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP24:%.*]] = load i32, ptr [[I7]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP24:%.*]] = load i32, ptr [[I7]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP24]] to double -// CHECK1-NEXT: store double [[CONV]], ptr [[REF_TMP15]], align 8, !tbaa [[TBAA23]] +// CHECK1-NEXT: store double [[CONV]], ptr [[REF_TMP15]], align 8, !tbaa [[TBAA36]] // CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[REF_TMP16]]) #[[ATTR4]] -// CHECK1-NEXT: [[TMP25:%.*]] = load i32, ptr [[I7]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP25:%.*]] = load i32, ptr [[I7]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[CONV17:%.*]] = sitofp i32 [[TMP25]] to double -// CHECK1-NEXT: store double [[CONV17]], ptr [[REF_TMP16]], align 8, !tbaa [[TBAA23]] +// CHECK1-NEXT: store double [[CONV17]], ptr [[REF_TMP16]], align 8, !tbaa [[TBAA36]] // CHECK1-NEXT: call void @_ZNSt7complexIdEC1ERKdS2_(ptr nonnull align 8 dereferenceable(16) [[REF_TMP14]], ptr nonnull align 8 dereferenceable(8) [[REF_TMP15]], ptr nonnull align 8 dereferenceable(8) [[REF_TMP16]]) #[[ATTR11]] // CHECK1-NEXT: [[CALL:%.*]] = call nonnull align 8 dereferenceable(16) ptr @_ZNSt7complexIdEpLIdEERS0_RKS_IT_E(ptr nonnull align 8 dereferenceable(16) [[PARTIAL_SUM5]], ptr nonnull align 8 dereferenceable(16) [[REF_TMP14]]) #[[ATTR11]] // CHECK1-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[REF_TMP16]]) #[[ATTR4]] @@ -801,25 +801,25 @@ void test() { // CHECK1: omp.body.continue: // CHECK1-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] // CHECK1: omp.inner.for.inc: -// CHECK1-NEXT: [[TMP26:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP26:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[ADD18:%.*]] = add i32 [[TMP26]], 1 -// CHECK1-NEXT: store i32 [[ADD18]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[ADD18]], ptr [[DOTOMP_IV]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: br label [[OMP_INNER_FOR_COND]] // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_DISPATCH_INC:%.*]] // CHECK1: omp.dispatch.inc: -// CHECK1-NEXT: [[TMP27:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP28:%.*]] = load i32, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP27:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP28:%.*]] = load i32, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[ADD19:%.*]] = add i32 [[TMP27]], [[TMP28]] -// CHECK1-NEXT: store i32 [[ADD19]], ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP29:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] -// CHECK1-NEXT: [[TMP30:%.*]] = load i32, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[ADD19]], ptr [[DOTOMP_LB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP29:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] +// CHECK1-NEXT: [[TMP30:%.*]] = load i32, ptr [[DOTOMP_STRIDE]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: [[ADD20:%.*]] = add i32 [[TMP29]], [[TMP30]] -// CHECK1-NEXT: store i32 [[ADD20]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i32 [[ADD20]], ptr [[DOTOMP_UB]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK1: omp.dispatch.end: // CHECK1-NEXT: [[TMP31:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 -// CHECK1-NEXT: [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP32]]) // CHECK1-NEXT: [[TMP33:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 // CHECK1-NEXT: store ptr [[PARTIAL_SUM5]], ptr [[TMP33]], align 8 @@ -850,21 +850,21 @@ void test() { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[__C_ADDR:%.*]] = alloca ptr, align 8 -// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[__C]], ptr [[__C_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA38]] +// CHECK1-NEXT: store ptr [[__C]], ptr [[__C_ADDR]], align 8, !tbaa [[TBAA38]] // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__C_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__C_ADDR]], align 8, !tbaa [[TBAA38]] // CHECK1-NEXT: [[CALL:%.*]] = call double @_ZNKSt7complexIdE4realEv(ptr nonnull align 8 dereferenceable(16) [[TMP0]]) #[[ATTR11]] // CHECK1-NEXT: [[__RE_:%.*]] = getelementptr inbounds nuw %"class.std::complex.0", ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP1:%.*]] = load double, ptr [[__RE_]], align 8, !tbaa [[TBAA25:![0-9]+]] +// CHECK1-NEXT: [[TMP1:%.*]] = load double, ptr [[__RE_]], align 8, !tbaa [[TBAA42:![0-9]+]] // CHECK1-NEXT: [[ADD:%.*]] = fadd double [[TMP1]], [[CALL]] -// CHECK1-NEXT: store double [[ADD]], ptr [[__RE_]], align 8, !tbaa [[TBAA25]] -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[__C_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store double [[ADD]], ptr [[__RE_]], align 8, !tbaa [[TBAA42]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[__C_ADDR]], align 8, !tbaa [[TBAA38]] // CHECK1-NEXT: [[CALL2:%.*]] = call double @_ZNKSt7complexIdE4imagEv(ptr nonnull align 8 dereferenceable(16) [[TMP2]]) #[[ATTR11]] // CHECK1-NEXT: [[__IM_:%.*]] = getelementptr inbounds nuw %"class.std::complex.0", ptr [[THIS1]], i32 0, i32 1 -// CHECK1-NEXT: [[TMP3:%.*]] = load double, ptr [[__IM_]], align 8, !tbaa [[TBAA27:![0-9]+]] +// CHECK1-NEXT: [[TMP3:%.*]] = load double, ptr [[__IM_]], align 8, !tbaa [[TBAA44:![0-9]+]] // CHECK1-NEXT: [[ADD3:%.*]] = fadd double [[TMP3]], [[CALL2]] -// CHECK1-NEXT: store double [[ADD3]], ptr [[__IM_]], align 8, !tbaa [[TBAA27]] +// CHECK1-NEXT: store double [[ADD3]], ptr [[__IM_]], align 8, !tbaa [[TBAA44]] // CHECK1-NEXT: ret ptr [[THIS1]] // // @@ -1012,17 +1012,17 @@ void test() { // CHECK1-NEXT: [[DOTADDR1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[DOTZERO_ADDR:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[GLOBAL_ARGS:%.*]] = alloca ptr, align 8 -// CHECK1-NEXT: store i16 [[TMP0]], ptr [[DOTADDR]], align 2, !tbaa [[TBAA21]] -// CHECK1-NEXT: store i32 [[TMP1]], ptr [[DOTADDR1]], align 4, !tbaa [[TBAA14]] +// CHECK1-NEXT: store i16 [[TMP0]], ptr [[DOTADDR]], align 2, !tbaa [[TBAA30]] +// CHECK1-NEXT: store i32 [[TMP1]], ptr [[DOTADDR1]], align 4, !tbaa [[TBAA15]] // CHECK1-NEXT: store i32 0, ptr [[DOTZERO_ADDR]], align 4 // CHECK1-NEXT: call void @__kmpc_get_shared_variables(ptr [[GLOBAL_ARGS]]) // CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[GLOBAL_ARGS]], align 8 // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds ptr, ptr [[TMP2]], i64 0 -// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8, !tbaa [[TBAA32]] // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds ptr, ptr [[TMP2]], i64 1 -// CHECK1-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP5]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP5]], align 8, !tbaa [[TBAA32]] // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds ptr, ptr [[TMP2]], i64 2 -// CHECK1-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8, !tbaa [[TBAA45:![0-9]+]] // CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z17complex_reductionIdEvv_l16_omp_outlined_omp_outlined(ptr [[DOTADDR1]], ptr [[DOTZERO_ADDR]], ptr [[TMP4]], ptr [[TMP6]], ptr [[TMP8]]) #[[ATTR4]] // CHECK1-NEXT: ret void // @@ -1033,18 +1033,18 @@ void test() { // CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[__RE_ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[__IM_ADDR:%.*]] = alloca ptr, align 8 -// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[__RE]], ptr [[__RE_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[__IM]], ptr [[__IM_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA23]] +// CHECK1-NEXT: store ptr [[__RE]], ptr [[__RE_ADDR]], align 8, !tbaa [[TBAA25]] +// CHECK1-NEXT: store ptr [[__IM]], ptr [[__IM_ADDR]], align 8, !tbaa [[TBAA25]] // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[__RE_:%.*]] = getelementptr inbounds nuw %"class.std::complex", ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__RE_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: [[TMP1:%.*]] = load float, ptr [[TMP0]], align 4, !tbaa [[TBAA16]] -// CHECK1-NEXT: store float [[TMP1]], ptr [[__RE_]], align 4, !tbaa [[TBAA18]] +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__RE_ADDR]], align 8, !tbaa [[TBAA25]] +// CHECK1-NEXT: [[TMP1:%.*]] = load float, ptr [[TMP0]], align 4, !tbaa [[TBAA19]] +// CHECK1-NEXT: store float [[TMP1]], ptr [[__RE_]], align 4, !tbaa [[TBAA27]] // CHECK1-NEXT: [[__IM_:%.*]] = getelementptr inbounds nuw %"class.std::complex", ptr [[THIS1]], i32 0, i32 1 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[__IM_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: [[TMP3:%.*]] = load float, ptr [[TMP2]], align 4, !tbaa [[TBAA16]] -// CHECK1-NEXT: store float [[TMP3]], ptr [[__IM_]], align 4, !tbaa [[TBAA20]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[__IM_ADDR]], align 8, !tbaa [[TBAA25]] +// CHECK1-NEXT: [[TMP3:%.*]] = load float, ptr [[TMP2]], align 4, !tbaa [[TBAA19]] +// CHECK1-NEXT: store float [[TMP3]], ptr [[__IM_]], align 4, !tbaa [[TBAA29]] // CHECK1-NEXT: ret void // // @@ -1052,10 +1052,10 @@ void test() { // CHECK1-SAME: (ptr nonnull align 4 dereferenceable(8) [[THIS:%.*]]) #[[ATTR5]] comdat align 2 { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA23]] // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[__RE_:%.*]] = getelementptr inbounds nuw %"class.std::complex", ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load float, ptr [[__RE_]], align 4, !tbaa [[TBAA18]] +// CHECK1-NEXT: [[TMP0:%.*]] = load float, ptr [[__RE_]], align 4, !tbaa [[TBAA27]] // CHECK1-NEXT: ret float [[TMP0]] // // @@ -1063,10 +1063,10 @@ void test() { // CHECK1-SAME: (ptr nonnull align 4 dereferenceable(8) [[THIS:%.*]]) #[[ATTR5]] comdat align 2 { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA23]] // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[__IM_:%.*]] = getelementptr inbounds nuw %"class.std::complex", ptr [[THIS1]], i32 0, i32 1 -// CHECK1-NEXT: [[TMP0:%.*]] = load float, ptr [[__IM_]], align 4, !tbaa [[TBAA20]] +// CHECK1-NEXT: [[TMP0:%.*]] = load float, ptr [[__IM_]], align 4, !tbaa [[TBAA29]] // CHECK1-NEXT: ret float [[TMP0]] // // @@ -1076,18 +1076,18 @@ void test() { // CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[__RE_ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[__IM_ADDR:%.*]] = alloca ptr, align 8 -// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[__RE]], ptr [[__RE_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: store ptr [[__IM]], ptr [[__IM_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA38]] +// CHECK1-NEXT: store ptr [[__RE]], ptr [[__RE_ADDR]], align 8, !tbaa [[TBAA40]] +// CHECK1-NEXT: store ptr [[__IM]], ptr [[__IM_ADDR]], align 8, !tbaa [[TBAA40]] // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[__RE_:%.*]] = getelementptr inbounds nuw %"class.std::complex.0", ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__RE_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: [[TMP1:%.*]] = load double, ptr [[TMP0]], align 8, !tbaa [[TBAA23]] -// CHECK1-NEXT: store double [[TMP1]], ptr [[__RE_]], align 8, !tbaa [[TBAA25]] +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__RE_ADDR]], align 8, !tbaa [[TBAA40]] +// CHECK1-NEXT: [[TMP1:%.*]] = load double, ptr [[TMP0]], align 8, !tbaa [[TBAA36]] +// CHECK1-NEXT: store double [[TMP1]], ptr [[__RE_]], align 8, !tbaa [[TBAA42]] // CHECK1-NEXT: [[__IM_:%.*]] = getelementptr inbounds nuw %"class.std::complex.0", ptr [[THIS1]], i32 0, i32 1 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[__IM_ADDR]], align 8, !tbaa [[TBAA10]] -// CHECK1-NEXT: [[TMP3:%.*]] = load double, ptr [[TMP2]], align 8, !tbaa [[TBAA23]] -// CHECK1-NEXT: store double [[TMP3]], ptr [[__IM_]], align 8, !tbaa [[TBAA27]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[__IM_ADDR]], align 8, !tbaa [[TBAA40]] +// CHECK1-NEXT: [[TMP3:%.*]] = load double, ptr [[TMP2]], align 8, !tbaa [[TBAA36]] +// CHECK1-NEXT: store double [[TMP3]], ptr [[__IM_]], align 8, !tbaa [[TBAA44]] // CHECK1-NEXT: ret void // // @@ -1095,10 +1095,10 @@ void test() { // CHECK1-SAME: (ptr nonnull align 8 dereferenceable(16) [[THIS:%.*]]) #[[ATTR5]] comdat align 2 { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA38]] // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[__RE_:%.*]] = getelementptr inbounds nuw %"class.std::complex.0", ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load double, ptr [[__RE_]], align 8, !tbaa [[TBAA25]] +// CHECK1-NEXT: [[TMP0:%.*]] = load double, ptr [[__RE_]], align 8, !tbaa [[TBAA42]] // CHECK1-NEXT: ret double [[TMP0]] // // @@ -1106,9 +1106,9 @@ void test() { // CHECK1-SAME: (ptr nonnull align 8 dereferenceable(16) [[THIS:%.*]]) #[[ATTR5]] comdat align 2 { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA10]] +// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8, !tbaa [[TBAA38]] // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[__IM_:%.*]] = getelementptr inbounds nuw %"class.std::complex.0", ptr [[THIS1]], i32 0, i32 1 -// CHECK1-NEXT: [[TMP0:%.*]] = load double, ptr [[__IM_]], align 8, !tbaa [[TBAA27]] +// CHECK1-NEXT: [[TMP0:%.*]] = load double, ptr [[__IM_]], align 8, !tbaa [[TBAA44]] // CHECK1-NEXT: ret double [[TMP0]] // diff --git a/clang/test/OpenMP/taskloop_strictmodifier_codegen.cpp b/clang/test/OpenMP/taskloop_strictmodifier_codegen.cpp index 107db947d015f..82dd07a1a63bb 100644 --- a/clang/test/OpenMP/taskloop_strictmodifier_codegen.cpp +++ b/clang/test/OpenMP/taskloop_strictmodifier_codegen.cpp @@ -45,7 +45,7 @@ struct S { // CHECK-NEXT: [[TMP1:%.*]] = tail call ptr @__kmpc_omp_task_alloc(ptr nonnull @[[GLOB1]], i32 [[TMP0]], i32 1, i64 48, i64 1, ptr nonnull @.omp_task_entry..2) // CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i64 40 // CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARGC_ADDR]], align 4, !tbaa [[TBAA3]] -// CHECK-NEXT: store i32 [[TMP3]], ptr [[TMP2]], align 8, !tbaa [[TBAA9:![0-9]+]] +// CHECK-NEXT: store i32 [[TMP3]], ptr [[TMP2]], align 8, !tbaa [[TBAA10:![0-9]+]] // CHECK-NEXT: [[TMP4:%.*]] = tail call i32 @__kmpc_omp_task(ptr nonnull @[[GLOB1]], i32 [[TMP0]], ptr [[TMP1]]) // CHECK-NEXT: [[TMP5:%.*]] = tail call i32 @__kmpc_master(ptr nonnull @[[GLOB1]], i32 [[TMP0]]) // CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP5]], 0 @@ -54,11 +54,11 @@ struct S { // CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[ARGC_ADDR]], align 4, !tbaa [[TBAA3]] // CHECK-NEXT: [[TMP7:%.*]] = tail call ptr @__kmpc_omp_task_alloc(ptr nonnull @[[GLOB1]], i32 [[TMP0]], i32 1, i64 80, i64 1, ptr nonnull @.omp_task_entry..4) // CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP7]], i64 40 -// CHECK-NEXT: store i64 0, ptr [[TMP8]], align 8, !tbaa [[TBAA13:![0-9]+]] +// CHECK-NEXT: store i64 0, ptr [[TMP8]], align 8, !tbaa [[TBAA15:![0-9]+]] // CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP7]], i64 48 -// CHECK-NEXT: store i64 9, ptr [[TMP9]], align 8, !tbaa [[TBAA13]] +// CHECK-NEXT: store i64 9, ptr [[TMP9]], align 8, !tbaa [[TBAA15]] // CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP7]], i64 56 -// CHECK-NEXT: store i64 1, ptr [[TMP10]], align 8, !tbaa [[TBAA13]] +// CHECK-NEXT: store i64 1, ptr [[TMP10]], align 8, !tbaa [[TBAA15]] // CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP7]], i64 72 // CHECK-NEXT: store i64 0, ptr [[TMP11]], align 8 // CHECK-NEXT: [[TMP12:%.*]] = zext i32 [[TMP6]] to i64 @@ -75,28 +75,28 @@ struct S { // CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[ARGV_ADDR]], align 8, !tbaa [[TBAA7]] // CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP14]] to i64 // CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP15]], i64 [[IDXPROM]] -// CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA7]] +// CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA17:![0-9]+]] // CHECK-NEXT: [[ARRAYIDX9:%.*]] = getelementptr inbounds i8, ptr [[TMP16]], i64 [[IDXPROM]] -// CHECK-NEXT: [[TMP17:%.*]] = load i8, ptr [[ARRAYIDX9]], align 1, !tbaa [[TBAA15:![0-9]+]] +// CHECK-NEXT: [[TMP17:%.*]] = load i8, ptr [[ARRAYIDX9]], align 1, !tbaa [[TBAA19:![0-9]+]] // CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP17]] to i32 // CHECK-NEXT: [[SUB12:%.*]] = sub i32 [[CONV]], [[TMP14]] // CHECK-NEXT: [[CONV15:%.*]] = zext i32 [[SUB12]] to i64 // CHECK-NEXT: [[MUL:%.*]] = mul nsw i64 [[CONV15]], [[IDXPROM]] // CHECK-NEXT: [[SUB16:%.*]] = add nsw i64 [[MUL]], -1 // CHECK-NEXT: [[TMP18:%.*]] = tail call ptr @__kmpc_omp_task_alloc(ptr nonnull @[[GLOB1]], i32 [[TMP0]], i32 1, i64 80, i64 16, ptr nonnull @.omp_task_entry..6) -// CHECK-NEXT: [[TMP19:%.*]] = load ptr, ptr [[TMP18]], align 8, !tbaa [[TBAA16:![0-9]+]] -// CHECK-NEXT: store ptr [[ARGC_ADDR]], ptr [[TMP19]], align 8, !tbaa [[TBAA7]] -// CHECK-NEXT: [[AGG_CAPTURED3_SROA_2_0__SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[TMP19]], i64 8 -// CHECK-NEXT: store ptr [[ARGV_ADDR]], ptr [[AGG_CAPTURED3_SROA_2_0__SROA_IDX]], align 8, !tbaa [[TBAA7]] +// CHECK-NEXT: [[TMP19:%.*]] = load ptr, ptr [[TMP18]], align 8, !tbaa [[TBAA20:![0-9]+]] +// CHECK-NEXT: store ptr [[ARGC_ADDR]], ptr [[TMP19]], align 8, !tbaa [[TBAA23:![0-9]+]] +// CHECK-NEXT: [[AGG_CAPTURED3_SROA_2_0__SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP19]], i64 8 +// CHECK-NEXT: store ptr [[ARGV_ADDR]], ptr [[AGG_CAPTURED3_SROA_2_0__SROA_IDX]], align 8, !tbaa [[TBAA25:![0-9]+]] // CHECK-NEXT: [[TMP20:%.*]] = load i32, ptr [[ARGC_ADDR]], align 4, !tbaa [[TBAA3]] // CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP20]], 0 // CHECK-NEXT: [[TMP21:%.*]] = sext i1 [[TOBOOL]] to i32 // CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP18]], i64 40 -// CHECK-NEXT: store i64 0, ptr [[TMP22]], align 8, !tbaa [[TBAA13]] +// CHECK-NEXT: store i64 0, ptr [[TMP22]], align 8, !tbaa [[TBAA15]] // CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP18]], i64 48 -// CHECK-NEXT: store i64 [[SUB16]], ptr [[TMP23]], align 8, !tbaa [[TBAA13]] +// CHECK-NEXT: store i64 [[SUB16]], ptr [[TMP23]], align 8, !tbaa [[TBAA15]] // CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP18]], i64 56 -// CHECK-NEXT: store i64 1, ptr [[TMP24]], align 8, !tbaa [[TBAA13]] +// CHECK-NEXT: store i64 1, ptr [[TMP24]], align 8, !tbaa [[TBAA15]] // CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP18]], i64 72 // CHECK-NEXT: store i64 0, ptr [[TMP25]], align 8 // CHECK-NEXT: call void @__kmpc_taskloop_5(ptr nonnull @[[GLOB1]], i32 [[TMP0]], ptr nonnull [[TMP18]], i32 [[TMP21]], ptr nonnull [[TMP22]], ptr nonnull [[TMP23]], i64 1, i32 1, i32 2, i64 4, i32 1, ptr null) #[[ATTR1]] @@ -111,11 +111,11 @@ struct S { // CHECK-NEXT: call void @__kmpc_taskgroup(ptr nonnull @[[GLOB1]], i32 [[TMP0]]) // CHECK-NEXT: [[TMP27:%.*]] = call ptr @__kmpc_omp_task_alloc(ptr nonnull @[[GLOB1]], i32 [[TMP0]], i32 1, i64 80, i64 1, ptr nonnull @.omp_task_entry..8) // CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP27]], i64 40 -// CHECK-NEXT: store i64 0, ptr [[TMP28]], align 8, !tbaa [[TBAA13]] +// CHECK-NEXT: store i64 0, ptr [[TMP28]], align 8, !tbaa [[TBAA15]] // CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP27]], i64 48 -// CHECK-NEXT: store i64 9, ptr [[TMP29]], align 8, !tbaa [[TBAA13]] +// CHECK-NEXT: store i64 9, ptr [[TMP29]], align 8, !tbaa [[TBAA15]] // CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP27]], i64 56 -// CHECK-NEXT: store i64 1, ptr [[TMP30]], align 8, !tbaa [[TBAA13]] +// CHECK-NEXT: store i64 1, ptr [[TMP30]], align 8, !tbaa [[TBAA15]] // CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP27]], i64 72 // CHECK-NEXT: store i64 0, ptr [[TMP31]], align 8 // CHECK-NEXT: call void @__kmpc_taskloop(ptr nonnull @[[GLOB1]], i32 [[TMP0]], ptr [[TMP27]], i32 1, ptr nonnull [[TMP28]], ptr nonnull [[TMP29]], i64 1, i32 1, i32 0, i64 0, ptr null) @@ -137,22 +137,22 @@ struct S { // CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP1]], 0 // CHECK-NEXT: br i1 [[DOTNOT]], label %[[OMP_IF_END:.*]], label %[[OMP_IF_THEN:.*]] // CHECK: [[OMP_IF_THEN]]: -// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[THIS]], align 4, !tbaa [[TBAA27:![0-9]+]] +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[THIS]], align 4, !tbaa [[TBAA35:![0-9]+]] // CHECK-NEXT: tail call void @__kmpc_taskgroup(ptr nonnull @[[GLOB1]], i32 [[TMP0]]) // CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[C_ADDR]], align 4, !tbaa [[TBAA3]] // CHECK-NEXT: [[SUB4:%.*]] = add nsw i32 [[TMP3]], -1 // CHECK-NEXT: [[TMP4:%.*]] = tail call ptr @__kmpc_omp_task_alloc(ptr nonnull @[[GLOB1]], i32 [[TMP0]], i32 1, i64 80, i64 16, ptr nonnull @.omp_task_entry..10) -// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8, !tbaa [[TBAA16]] -// CHECK-NEXT: store ptr [[THIS]], ptr [[TMP5]], align 8, !tbaa [[TBAA7]] -// CHECK-NEXT: [[AGG_CAPTURED_SROA_2_0__SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[TMP5]], i64 8 -// CHECK-NEXT: store ptr [[C_ADDR]], ptr [[AGG_CAPTURED_SROA_2_0__SROA_IDX]], align 8, !tbaa [[TBAA7]] +// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8, !tbaa [[TBAA20]] +// CHECK-NEXT: store ptr [[THIS]], ptr [[TMP5]], align 8, !tbaa [[TBAA37:![0-9]+]] +// CHECK-NEXT: [[AGG_CAPTURED_SROA_2_0__SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP5]], i64 8 +// CHECK-NEXT: store ptr [[C_ADDR]], ptr [[AGG_CAPTURED_SROA_2_0__SROA_IDX]], align 8, !tbaa [[TBAA23]] // CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP4]], i64 40 -// CHECK-NEXT: store i64 0, ptr [[TMP6]], align 8, !tbaa [[TBAA13]] +// CHECK-NEXT: store i64 0, ptr [[TMP6]], align 8, !tbaa [[TBAA15]] // CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP4]], i64 48 // CHECK-NEXT: [[CONV:%.*]] = sext i32 [[SUB4]] to i64 -// CHECK-NEXT: store i64 [[CONV]], ptr [[TMP7]], align 8, !tbaa [[TBAA13]] +// CHECK-NEXT: store i64 [[CONV]], ptr [[TMP7]], align 8, !tbaa [[TBAA15]] // CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP4]], i64 56 -// CHECK-NEXT: store i64 1, ptr [[TMP8]], align 8, !tbaa [[TBAA13]] +// CHECK-NEXT: store i64 1, ptr [[TMP8]], align 8, !tbaa [[TBAA15]] // CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP4]], i64 72 // CHECK-NEXT: store i64 0, ptr [[TMP9]], align 8 // CHECK-NEXT: [[TMP10:%.*]] = zext i32 [[TMP2]] to i64 diff --git a/clang/test/Parser/cxx1z-decomposition.cpp b/clang/test/Parser/cxx1z-decomposition.cpp index 4b17f72effb0f..acf3f99069185 100644 --- a/clang/test/Parser/cxx1z-decomposition.cpp +++ b/clang/test/Parser/cxx1z-decomposition.cpp @@ -110,7 +110,7 @@ namespace BadSpecifiers { int [5] arr = {0}; // expected-error {{place the brackets after the name}} auto *[f] = s; // expected-error {{cannot be declared with type 'auto *'}} expected-error {{incompatible initializer}} - auto S::*[g] = s; // expected-error {{cannot be declared with type 'auto BadSpecifiers::S::*'}} expected-error {{incompatible initializer}} + auto S::*[g] = s; // expected-error {{cannot be declared with type 'auto S::*'}} expected-error {{incompatible initializer}} // ref-qualifiers are OK. auto &&[ok_1] = S(); diff --git a/clang/test/Parser/cxx2c-pack-indexing.cpp b/clang/test/Parser/cxx2c-pack-indexing.cpp index c279bdd7af8c4..99347a2f8f157 100644 --- a/clang/test/Parser/cxx2c-pack-indexing.cpp +++ b/clang/test/Parser/cxx2c-pack-indexing.cpp @@ -74,3 +74,12 @@ struct SS { } }; } + +namespace GH119072 { + +template +void foo() { + decltype(Ts...[0]::t) value; +} + +} diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index 037a3e186ee55..86265f630296c 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -39,6 +39,7 @@ // CHECK-NOT: __ARM_FP_FAST 1 // CHECK: __ARM_NEON 1 // CHECK: __ARM_NEON_FP 0xE +// CHECK: __ARM_NEON_SVE_BRIDGE 1 // CHECK: __ARM_PCS_AAPCS64 1 // CHECK-NOT: __ARM_PCS 1 // CHECK-NOT: __ARM_PCS_VFP 1 diff --git a/clang/test/Preprocessor/init-aarch64.c b/clang/test/Preprocessor/init-aarch64.c index 8ee6c6ba60af4..3d2f4b83abcb8 100644 --- a/clang/test/Preprocessor/init-aarch64.c +++ b/clang/test/Preprocessor/init-aarch64.c @@ -30,6 +30,7 @@ // AARCH64-NEXT: #define __ARM_FP 0xE // AARCH64-NEXT: #define __ARM_FP16_ARGS 1 // AARCH64-NEXT: #define __ARM_FP16_FORMAT_IEEE 1 +// AARCH64-NEXT: #define __ARM_NEON_SVE_BRIDGE 1 // AARCH64-NEXT: #define __ARM_PCS_AAPCS64 1 // AARCH64-NEXT: #define __ARM_SIZEOF_MINIMAL_ENUM 4 // AARCH64-NEXT: #define __ARM_SIZEOF_WCHAR_T 4 diff --git a/clang/test/Preprocessor/sycl-macro.cpp b/clang/test/Preprocessor/sycl-macro.cpp index eecddaa09d1c3..a509086f99e41 100644 --- a/clang/test/Preprocessor/sycl-macro.cpp +++ b/clang/test/Preprocessor/sycl-macro.cpp @@ -10,5 +10,5 @@ // CHECK-NOT:#define __SYCL_DEVICE_ONLY__ 1 // CHECK-NOT:#define CL_SYCL_LANGUAGE_VERSION 121 // CHECK-SYCL-STD:#define CL_SYCL_LANGUAGE_VERSION 121 -// CHECK-SYCL-STD-2020:#define SYCL_LANGUAGE_VERSION 202001 +// CHECK-SYCL-STD-2020:#define SYCL_LANGUAGE_VERSION 202012 // CHECK-SYCL:#define __SYCL_DEVICE_ONLY__ 1 diff --git a/clang/test/Sema/aarch64-fixed-global-register.c b/clang/test/Sema/aarch64-fixed-global-register.c index 9b4a422d8c1b2..f66c3475dae38 100644 --- a/clang/test/Sema/aarch64-fixed-global-register.c +++ b/clang/test/Sema/aarch64-fixed-global-register.c @@ -1,4 +1,13 @@ -// RUN: %clang_cc1 -triple aarch64-unknown-none-gnu %s -verify -fsyntax-only +// RUN: %clang_cc1 -triple aarch64-unknown-none-gnu %s -target-feature +reserve-x4 -target-feature +reserve-x15 -verify -verify=no_x18 -fsyntax-only +// RUN: %clang_cc1 -triple aarch64-unknown-android %s -target-feature +reserve-x4 -target-feature +reserve-x15 -verify -fsyntax-only +register int w0 __asm__ ("w0"); +register long x0 __asm__ ("x0"); register char i1 __asm__ ("x15"); // expected-error {{size of register 'x15' does not match variable size}} -register long long l2 __asm__ ("w14"); // expected-error {{size of register 'w14' does not match variable size}} +register long long l2 __asm__ ("w15"); // expected-error {{size of register 'w15' does not match variable size}} +register int w3 __asm__ ("w3"); // expected-error {{register 'w3' unsuitable for global register variables on this target}} +register long x3 __asm__ ("x3"); // expected-error {{register 'x3' unsuitable for global register variables on this target}} +register int w4 __asm__ ("w4"); +register long x4 __asm__ ("x4"); +register int w18 __asm__ ("w18"); // no_x18-error {{register 'w18' unsuitable for global register variables on this target}} +register long x18 __asm__ ("x18"); // no_x18-error {{register 'x18' unsuitable for global register variables on this target}} diff --git a/clang/test/Sema/aarch64-fp8-intrinsics/acle_sme2_fp8_cvt.c b/clang/test/Sema/aarch64-fp8-intrinsics/acle_sme2_fp8_cvt.c index 09a80c9dff03e..af1ef46ea6972 100644 --- a/clang/test/Sema/aarch64-fp8-intrinsics/acle_sme2_fp8_cvt.c +++ b/clang/test/Sema/aarch64-fp8-intrinsics/acle_sme2_fp8_cvt.c @@ -14,4 +14,13 @@ void test_features_sme2_fp8(svmfloat8_t zn, fpm_t fpmr) __arm_streaming { svcvtl1_bf16_mf8_x2_fpm(zn, fpmr); // expected-error@+1 {{'svcvtl2_bf16_mf8_x2_fpm' needs target feature sme,sme2,fp8}} svcvtl2_bf16_mf8_x2_fpm(zn, fpmr); + + // expected-error@+1 {{'svcvt1_f16_mf8_x2_fpm' needs target feature sme,sme2,fp8}} + svcvt1_f16_mf8_x2_fpm(zn, fpmr); + // expected-error@+1 {{'svcvt2_f16_mf8_x2_fpm' needs target feature sme,sme2,fp8}} + svcvt2_f16_mf8_x2_fpm(zn, fpmr); + // expected-error@+1 {{'svcvt1_bf16_mf8_x2_fpm' needs target feature sme,sme2,fp8}} + svcvt1_bf16_mf8_x2_fpm(zn, fpmr); + // expected-error@+1 {{'svcvt2_bf16_mf8_x2_fpm' needs target feature sme,sme2,fp8}} + svcvt2_bf16_mf8_x2_fpm(zn, fpmr); } \ No newline at end of file diff --git a/clang/test/Sema/aarch64-fp8-intrinsics/acle_sme2_fp8_imm.c b/clang/test/Sema/aarch64-fp8-intrinsics/acle_sme2_fp8_imm.c new file mode 100644 index 0000000000000..62cad9cfa4c8f --- /dev/null +++ b/clang/test/Sema/aarch64-fp8-intrinsics/acle_sme2_fp8_imm.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -fsyntax-only -verify %s + +// REQUIRES: aarch64-registered-target + +#include + +void test_svmopa(svbool_t pn, svbool_t pm, svmfloat8_t zn, svmfloat8_t zm, + fpm_t fpmr) __arm_streaming __arm_inout("za") { + // expected-error@+1 {{argument value 18446744073709551615 is outside the valid range [0, 1]}} + svmopa_za16_mf8_m_fpm(-1, pn, pm, zn, zm, fpmr); + // expected-error@+1 {{argument value 2 is outside the valid range [0, 1]}} + svmopa_za16_mf8_m_fpm(2, pn, pm, zn, zm, fpmr); + + // expected-error@+1 {{argument value 18446744073709551615 is outside the valid range [0, 3]}} + svmopa_za32_mf8_m_fpm(-1, pn, pm, zn, zm, fpmr); + // expected-error@+1 {{argument value 4 is outside the valid range [0, 3]}} + svmopa_za32_mf8_m_fpm(4, pn, pm, zn, zm, fpmr); +} diff --git a/clang/test/Sema/aarch64-fp8-intrinsics/acle_sme2_fp8_mopa.c b/clang/test/Sema/aarch64-fp8-intrinsics/acle_sme2_fp8_mopa.c new file mode 100644 index 0000000000000..86426abcd4329 --- /dev/null +++ b/clang/test/Sema/aarch64-fp8-intrinsics/acle_sme2_fp8_mopa.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -verify -emit-llvm-only %s + +// REQUIRES: aarch64-registered-target + +#include + +void test_features(svbool_t pn, svbool_t pm, svmfloat8_t zn, svmfloat8_t zm, + fpm_t fpmr) __arm_streaming __arm_inout("za") { + // expected-error@+1 {{'svmopa_za16_mf8_m_fpm' needs target feature sme,sme-f8f16}} + svmopa_za16_mf8_m_fpm(0, pn, pm, zn, zm, fpmr); + // expected-error@+1 {{'svmopa_za32_mf8_m_fpm' needs target feature sme,sme-f8f32}} + svmopa_za32_mf8_m_fpm(0, pn, pm, zn, zm, fpmr); +} diff --git a/clang/test/Sema/aarch64-sve-intrinsics/acle_neon_sve_bridge.cpp b/clang/test/Sema/aarch64-sve-intrinsics/acle_neon_sve_bridge.cpp new file mode 100644 index 0000000000000..a3f3764939156 --- /dev/null +++ b/clang/test/Sema/aarch64-sve-intrinsics/acle_neon_sve_bridge.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -verify -emit-llvm -o - %s +// REQUIRES: aarch64-registered-target + +// Test that we can use __ARM_NEON_SVE_BRIDGE to guard to inclusion of arm_neon_sve_bridge.h, +// and use the associated intrinsics via a target() attribute. + +// expected-no-diagnostics + +#ifdef __ARM_NEON_SVE_BRIDGE +#include +#endif + +uint32x4_t __attribute__((target("+sve"))) foo(svuint32_t a) { + return svget_neonq_u32(a); +} \ No newline at end of file diff --git a/clang/test/Sema/constant_builtins_vector.cpp b/clang/test/Sema/constant_builtins_vector.cpp index 45c729f76418d..b2f56e5a87ab1 100644 --- a/clang/test/Sema/constant_builtins_vector.cpp +++ b/clang/test/Sema/constant_builtins_vector.cpp @@ -822,3 +822,19 @@ static_assert(__builtin_elementwise_bitreverse(0x12345678) == 0x1E6A2C48); static_assert(__builtin_elementwise_bitreverse(0x0123456789ABCDEFULL) == 0xF7B3D591E6A2C480); static_assert(__builtin_bit_cast(unsigned, __builtin_elementwise_bitreverse((vector4char){1, 2, 4, 8})) == (LITTLE_END ? 0x10204080 : 0x80402010)); static_assert(__builtin_bit_cast(unsigned long long, __builtin_elementwise_bitreverse((vector4short){1, 2, 4, 8})) == (LITTLE_END ? 0x1000200040008000 : 0x8000400020001000)); + +static_assert(__builtin_elementwise_add_sat(1, 2) == 3); +static_assert(__builtin_elementwise_add_sat(1U, 2U) == 3U); +static_assert(__builtin_elementwise_add_sat(~(1 << 31), 42) == ~(1 << 31)); +static_assert(__builtin_elementwise_add_sat((1 << 31), -42) == (1 << 31)); +static_assert(__builtin_elementwise_add_sat(~0U, 1U) == ~0U); +static_assert(__builtin_bit_cast(unsigned, __builtin_elementwise_add_sat((vector4char){1, 2, 3, 4}, (vector4char){1, 2, 3, 4})) == (LITTLE_END ? 0x08060402 : 0x02040608)); +static_assert(__builtin_bit_cast(unsigned long long, __builtin_elementwise_add_sat((vector4short){(short)0x8000, (short)0x8001, (short)0x8002, (short)0x8003}, (vector4short){-7, -8, -9, -10}) == (LITTLE_END ? 0x8000800080008000 : 0x8000800080008000))); + +static_assert(__builtin_elementwise_sub_sat(1, 2) == -1); +static_assert(__builtin_elementwise_sub_sat(2U, 1U) == 1U); +static_assert(__builtin_elementwise_sub_sat(~(1 << 31), -42) == ~(1 << 31)); +static_assert(__builtin_elementwise_sub_sat((1 << 31), 42) == (1 << 31)); +static_assert(__builtin_elementwise_sub_sat(0U, 1U) == 0U); +static_assert(__builtin_bit_cast(unsigned, __builtin_elementwise_sub_sat((vector4char){5, 4, 3, 2}, (vector4char){1, 1, 1, 1})) == (LITTLE_END ? 0x01020304 : 0x04030201)); +static_assert(__builtin_bit_cast(unsigned long long, __builtin_elementwise_sub_sat((vector4short){(short)0x8000, (short)0x8001, (short)0x8002, (short)0x8003}, (vector4short){7, 8, 9, 10}) == (LITTLE_END ? 0x8000800080008000 : 0x8000800080008000))); diff --git a/clang/test/Sema/warn-stringcompare.c b/clang/test/Sema/warn-stringcompare.c index 77876ad6abd6e..44dc0a5de3a4e 100644 --- a/clang/test/Sema/warn-stringcompare.c +++ b/clang/test/Sema/warn-stringcompare.c @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -x c -fsyntax-only -verify %s -// RUN: %clang_cc1 -x c++ -fsyntax-only -verify %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=expected,cxx %s +// RUN: %clang_cc1 -x c++ -std=c++26 -fsyntax-only -verify=expected,cxx26 %s #define DELIM "/" #define DOT "." @@ -15,15 +16,15 @@ void test(const char *d) { if (NULL == "/") return; if ("/" != DELIM) // expected-warning {{result of comparison against a string literal is unspecified (use an explicit string comparison function instead)}} - return; + return; // cxx-warning@-1 {{comparison between two arrays}} cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}} if (DELIM == "/") // expected-warning {{result of comparison against a string literal is unspecified (use an explicit string comparison function instead)}} - return; + return; // cxx-warning@-1 {{comparison between two arrays}} cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}} if (DELIM != NULL) return; if (NULL == DELIM) return; if (DOT != DELIM) // expected-warning {{result of comparison against a string literal is unspecified (use an explicit string comparison function instead)}} - return; + return; // cxx-warning@-1 {{comparison between two arrays}} cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}} if (DELIM == DOT) // expected-warning {{result of comparison against a string literal is unspecified (use an explicit string comparison function instead)}} - return; + return; // cxx-warning@-1 {{comparison between two arrays}} cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}} } diff --git a/clang/test/SemaCXX/addr-of-overloaded-function.cpp b/clang/test/SemaCXX/addr-of-overloaded-function.cpp index dd1c3462c8c1f..99f5ba613938d 100644 --- a/clang/test/SemaCXX/addr-of-overloaded-function.cpp +++ b/clang/test/SemaCXX/addr-of-overloaded-function.cpp @@ -221,20 +221,20 @@ namespace test1 { void QualifierTest() { void (Qualifiers::*X)(); - X = &Qualifiers::C; // expected-error-re {{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const': different qualifiers (unqualified vs 'const')}} - X = &Qualifiers::V; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile': different qualifiers (unqualified vs 'volatile')}} - X = &Qualifiers::R; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} __restrict': different qualifiers (unqualified vs '__restrict')}} - X = &Qualifiers::CV; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile': different qualifiers (unqualified vs 'const volatile')}} - X = &Qualifiers::CR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const __restrict': different qualifiers (unqualified vs 'const __restrict')}} - X = &Qualifiers::VR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile __restrict': different qualifiers (unqualified vs 'volatile __restrict')}} - X = &Qualifiers::CVR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile __restrict': different qualifiers (unqualified vs 'const volatile __restrict')}} + X = &Qualifiers::C; // expected-error-re {{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const': different qualifiers (unqualified vs 'const')}} + X = &Qualifiers::V; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile': different qualifiers (unqualified vs 'volatile')}} + X = &Qualifiers::R; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} __restrict': different qualifiers (unqualified vs '__restrict')}} + X = &Qualifiers::CV; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile': different qualifiers (unqualified vs 'const volatile')}} + X = &Qualifiers::CR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const __restrict': different qualifiers (unqualified vs 'const __restrict')}} + X = &Qualifiers::VR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile __restrict': different qualifiers (unqualified vs 'volatile __restrict')}} + X = &Qualifiers::CVR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile __restrict': different qualifiers (unqualified vs 'const volatile __restrict')}} } struct Dummy { void N() {}; }; - void (Qualifiers::*X)() = &Dummy::N; // expected-error-re{{cannot initialize a variable of type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' with an rvalue of type 'void (test1::Dummy::*)(){{( __attribute__\(\(thiscall\)\))?}}': different classes ('test1::Qualifiers' vs 'test1::Dummy')}} + void (Qualifiers::*X)() = &Dummy::N; // expected-error-re{{cannot initialize a variable of type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' with an rvalue of type 'void (test1::Dummy::*)(){{( __attribute__\(\(thiscall\)\))?}}': different classes ('Qualifiers' vs 'test1::Dummy')}} } template class PR16561 { diff --git a/clang/test/SemaCXX/calling-conv-compat.cpp b/clang/test/SemaCXX/calling-conv-compat.cpp index 2af944defd4bc..5a51e34b1478c 100644 --- a/clang/test/SemaCXX/calling-conv-compat.cpp +++ b/clang/test/SemaCXX/calling-conv-compat.cpp @@ -183,31 +183,31 @@ typedef void ( C::*memb_c_default)(); typedef void (__cdecl C::*memb_c_cdecl)(); typedef void (__thiscall C::*memb_c_thiscall)(); -// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_a_default' (aka 'void (NonVariadic::A::*)() __attribute__((thiscall))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_a_default' (aka 'void (A::*)() __attribute__((thiscall))') for 1st argument}} void cb_memb_a_default(memb_a_default ptr); -// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (NonVariadic::A::*)() __attribute__((cdecl))') for 1st argument}} -// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (NonVariadic::A::*)() __attribute__((cdecl))') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (A::*)() __attribute__((cdecl))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (A::*)() __attribute__((cdecl))') for 1st argument}} void cb_memb_a_cdecl(memb_a_cdecl ptr); -// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_a_thiscall' (aka 'void (NonVariadic::A::*)() __attribute__((thiscall))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_a_thiscall' (aka 'void (A::*)() __attribute__((thiscall))') for 1st argument}} void cb_memb_a_thiscall(memb_a_thiscall ptr); -// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_b_default' (aka 'void (NonVariadic::B::*)() __attribute__((thiscall))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_b_default' (aka 'void (B::*)() __attribute__((thiscall))') for 1st argument}} void cb_memb_b_default(memb_b_default ptr); -// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (NonVariadic::B::*)() __attribute__((cdecl))') for 1st argument}} -// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (NonVariadic::B::*)() __attribute__((cdecl))') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (B::*)() __attribute__((cdecl))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (B::*)() __attribute__((cdecl))') for 1st argument}} void cb_memb_b_cdecl(memb_b_cdecl ptr); -// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_b_thiscall' (aka 'void (NonVariadic::B::*)() __attribute__((thiscall))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_b_thiscall' (aka 'void (B::*)() __attribute__((thiscall))') for 1st argument}} void cb_memb_b_thiscall(memb_b_thiscall ptr); -// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}} -// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_default' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}} -// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}} +// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}} void cb_memb_c_default(memb_c_default ptr); -// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (NonVariadic::C::*)() __attribute__((cdecl))') for 1st argument}} -// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (NonVariadic::C::*)() __attribute__((cdecl))') for 1st argument}} -// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (NonVariadic::C::*)() __attribute__((cdecl))') for 1st argument}} +// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}} void cb_memb_c_cdecl(memb_c_cdecl ptr); -// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}} -// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_thiscall' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}} -// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}} +// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}} void cb_memb_c_thiscall(memb_c_thiscall ptr); void call_member() { @@ -279,11 +279,11 @@ void cb_memb_a_default(memb_a_default ptr); void cb_memb_a_cdecl(memb_a_cdecl ptr); void cb_memb_b_default(memb_b_default ptr); void cb_memb_b_cdecl(memb_b_cdecl ptr); -// expected-note@+2 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...)' to 'memb_c_default' (aka 'void (Variadic::C::*)(int, ...)') for 1st argument}} -// expected-note@+1 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_default' (aka 'void (Variadic::C::*)(int, ...)') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...)' to 'memb_c_default' (aka 'void (C::*)(int, ...)') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_default' (aka 'void (C::*)(int, ...)') for 1st argument}} void cb_memb_c_default(memb_c_default ptr); -// expected-note@+2 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...)' to 'memb_c_cdecl' (aka 'void (Variadic::C::*)(int, ...) __attribute__((cdecl))') for 1st argument}} -// expected-note@+1 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (Variadic::C::*)(int, ...) __attribute__((cdecl))') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...)' to 'memb_c_cdecl' (aka 'void (C::*)(int, ...) __attribute__((cdecl))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (C::*)(int, ...) __attribute__((cdecl))') for 1st argument}} void cb_memb_c_cdecl(memb_c_cdecl ptr); void call_member() { @@ -330,7 +330,7 @@ mptr_t __stdcall return_mptr_std(short) { void (A::*(*return_fptr_std_mptr(char))(short))(int) { return return_mptr_std; #if !_M_X64 - // expected-error@-2 {{cannot initialize return object of type 'void (MultiChunkDecls::A::*(*)(short))(int) __attribute__((thiscall))' with an lvalue of type 'mptr_t (short) __attribute__((stdcall))'}} + // expected-error@-2 {{cannot initialize return object of type 'void (A::*(*)(short))(int) __attribute__((thiscall))' with an lvalue of type 'mptr_t (short) __attribute__((stdcall))'}} #endif } diff --git a/clang/test/SemaCXX/deprecated.cpp b/clang/test/SemaCXX/deprecated.cpp index 667f4d7d3edb0..4282239af81b4 100644 --- a/clang/test/SemaCXX/deprecated.cpp +++ b/clang/test/SemaCXX/deprecated.cpp @@ -246,17 +246,19 @@ namespace ArithConv { namespace ArrayComp { int arr1[3], arr2[4]; - bool b1 = arr1 == arr2; // expected-warning {{array comparison always evaluates to false}} cxx20-warning {{comparison between two arrays is deprecated}} - bool b2 = arr1 < arr2; // expected-warning {{array comparison always evaluates to a constant}} cxx20-warning {{comparison between two arrays is deprecated}} + bool b1 = arr1 == arr2; // not-cxx20-warning {{comparison between two arrays compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}} + // expected-warning@-1 {{array comparison always evaluates to false}} + bool b2 = arr1 < arr2; // not-cxx20-warning {{comparison between two arrays compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}} + // expected-warning@-1 {{array comparison always evaluates to a constant}} __attribute__((weak)) int arr3[3]; - bool b3 = arr1 == arr3; // cxx20-warning {{comparison between two arrays is deprecated}} - bool b4 = arr1 < arr3; // cxx20-warning {{comparison between two arrays is deprecated}} + bool b3 = arr1 == arr3; // not-cxx20-warning {{comparison between two arrays compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}} + bool b4 = arr1 < arr3; // not-cxx20-warning {{comparison between two arrays compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}} #if __cplusplus > 201703L bool b5 = arr1 <=> arr2; // cxx20-error {{invalid operands}} #endif int (&f())[3]; - bool b6 = arr1 == f(); // cxx20-warning {{comparison between two arrays is deprecated}} + bool b6 = arr1 == f(); // not-cxx20-warning {{comparison between two arrays compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}} bool b7 = arr1 == +f(); } diff --git a/clang/test/SemaCXX/ms-constexpr-new.cpp b/clang/test/SemaCXX/ms-constexpr-new.cpp index 30567740b2ecb..096014be803e7 100644 --- a/clang/test/SemaCXX/ms-constexpr-new.cpp +++ b/clang/test/SemaCXX/ms-constexpr-new.cpp @@ -12,5 +12,12 @@ namespace std { } } -constexpr bool check_construct_at() { int x; return *std::construct_at(&x, 42) == 42; } -static_assert(check_construct_at()); +constexpr bool check_std_construct_at() { int x; return *std::construct_at(&x, 42) == 42; } +static_assert(check_std_construct_at()); + +constexpr int* construct_at(int* p, int v) { [[msvc::constexpr]] return ::new (p) int(v); } // unsupported-error {{constexpr function never produces a constant expression}} \ + // unsupported-warning {{unknown attribute 'constexpr' ignored}} \ + // unsupported-note 2{{this placement new expression is not supported in constant expressions before C++2c}} +constexpr bool check_construct_at() { int x; return *construct_at(&x, 42) == 42; } // unsupported-note {{in call to 'construct_at(&x, 42)'}} +static_assert(check_construct_at()); // unsupported-error {{static assertion expression is not an integral constant expression}}\ + // unsupported-note {{in call to 'check_construct_at()'}} diff --git a/clang/test/SemaCXX/new-delete.cpp b/clang/test/SemaCXX/new-delete.cpp index 595bdc689d694..fb4810ad673ad 100644 --- a/clang/test/SemaCXX/new-delete.cpp +++ b/clang/test/SemaCXX/new-delete.cpp @@ -540,6 +540,22 @@ namespace PR10504 { void f(A *x) { delete x; } // expected-warning {{delete called on 'PR10504::A' that is abstract but has non-virtual destructor}} } +#if __cplusplus >= 201103L +enum GH99278_1 { + zero = decltype(delete static_cast(nullptr), 0){} + // expected-warning@-1 {{expression with side effects has no effect in an unevaluated context}} +}; +template +struct GH99278_2 { + union b {}; + struct c { + c() { delete d; } + b *d; + } f; +}; +GH99278_2 e; +#endif + struct PlacementArg {}; inline void *operator new[](size_t, const PlacementArg &) throw () { return 0; diff --git a/clang/test/SemaCXX/noexcept-destroying-delete.cpp b/clang/test/SemaCXX/noexcept-destroying-delete.cpp new file mode 100644 index 0000000000000..92ccbc1fb3f96 --- /dev/null +++ b/clang/test/SemaCXX/noexcept-destroying-delete.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fcxx-exceptions -Wno-unevaluated-expression -std=c++20 %s +// expected-no-diagnostics + +namespace std { + struct destroying_delete_t { + explicit destroying_delete_t() = default; + }; + + inline constexpr destroying_delete_t destroying_delete{}; +} + +struct Explicit { + ~Explicit() noexcept(false) {} + + void operator delete(Explicit*, std::destroying_delete_t) noexcept { + } +}; + +Explicit *qn = nullptr; +// This assertion used to fail, see GH118660 +static_assert(noexcept(delete(qn))); + +struct ThrowingDestroyingDelete { + ~ThrowingDestroyingDelete() noexcept(false) {} + + void operator delete(ThrowingDestroyingDelete*, std::destroying_delete_t) noexcept(false) { + } +}; + +ThrowingDestroyingDelete *pn = nullptr; +// noexcept should return false here because the destroying delete itself is a +// potentially throwing function. +static_assert(!noexcept(delete(pn))); diff --git a/clang/test/SemaCXX/static-cast.cpp b/clang/test/SemaCXX/static-cast.cpp index 7cc4bea423d60..4b36dad64a06b 100644 --- a/clang/test/SemaCXX/static-cast.cpp +++ b/clang/test/SemaCXX/static-cast.cpp @@ -199,6 +199,6 @@ namespace PR6072 { (void)static_cast(&B::f); (void)static_cast(&B::f); (void)static_cast(&B::f); - (void)static_cast(&B::f); // expected-error-re{{address of overloaded function 'f' cannot be static_cast to type 'void (PR6072::D::*)(){{( __attribute__\(\(thiscall\)\))?}}'}} + (void)static_cast(&B::f); // expected-error-re{{address of overloaded function 'f' cannot be static_cast to type 'void (D::*)(){{( __attribute__\(\(thiscall\)\))?}}'}} } } diff --git a/clang/test/SemaCXX/warn-array-comparion.cpp b/clang/test/SemaCXX/warn-array-comparion.cpp new file mode 100644 index 0000000000000..2bd4218f3a279 --- /dev/null +++ b/clang/test/SemaCXX/warn-array-comparion.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s -verify=expected,not-cxx20 +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -Wno-deprecated-array-compare -verify %s -verify=expected,not-cxx20 +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -Wdeprecated -verify %s -verify=expected,cxx20 +// RUN: %clang_cc1 -std=c++26 -fsyntax-only -Wdeprecated -verify %s -verify=expected,cxx26 + +typedef struct { + char str[16]; + int id[16]; +} Object; + +bool object_equal(const Object &obj1, const Object &obj2) { + if (obj1.str != obj2.str) // not-cxx20-warning {{comparison between two arrays compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}} + return false; // cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}} + if (obj1.id != obj2.id) // not-cxx20-warning {{comparison between two arrays compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}} + return false; // cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}} + return true; +} + + +void foo(int (&array1)[2], int (&array2)[2]) { + if (array1 == array2) { } // not-cxx20-warning {{comparison between two arrays compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}} + // cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}} +} diff --git a/clang/test/SemaCXX/warn-self-comparisons.cpp b/clang/test/SemaCXX/warn-self-comparisons.cpp index 2e8d130bcd5a0..1ea8b971fcd56 100644 --- a/clang/test/SemaCXX/warn-self-comparisons.cpp +++ b/clang/test/SemaCXX/warn-self-comparisons.cpp @@ -1,6 +1,8 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s -verify=expected,not-cxx20 +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -Wdeprecated -verify %s -verify=expected,cxx20 +// RUN: %clang_cc1 -std=c++26 -fsyntax-only -Wdeprecated -verify %s -verify=expected,cxx26 void f(int (&array1)[2], int (&array2)[2]) { - if (array1 == array2) { } // no warning + if (array1 == array2) { } // not-cxx20-warning {{comparison between two arrays compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}} + // cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}} } diff --git a/clang/test/SemaCXX/warn-unused-private-field.cpp b/clang/test/SemaCXX/warn-unused-private-field.cpp index bf104b1a76a65..0cc6f687f1b35 100644 --- a/clang/test/SemaCXX/warn-unused-private-field.cpp +++ b/clang/test/SemaCXX/warn-unused-private-field.cpp @@ -40,6 +40,20 @@ class FriendEqDefaultCompareOutOfClass { bool operator==(const FriendEqDefaultCompareOutOfClass &, const FriendEqDefaultCompareOutOfClass &) = default; +class HasUnusedField { + int unused_; // expected-warning{{private field 'unused_' is not used}} +}; + +class FriendEqDefaultCompare { + int used; + friend auto operator==(FriendEqDefaultCompare, FriendEqDefaultCompare) -> bool = default; +}; + +class UnrelatedFriendEqDefaultCompare { + friend auto operator==(UnrelatedFriendEqDefaultCompare, UnrelatedFriendEqDefaultCompare) -> bool = default; + int operator<=>(const UnrelatedFriendEqDefaultCompare &) const = default; +}; + #endif class NotFullyDefined { diff --git a/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c b/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c index a6f57a63a91dd..45eede2e30f1f 100644 --- a/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c +++ b/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c @@ -46,10 +46,8 @@ void uses() { // expected-warning@+1{{OpenACC clause 'if_present' not yet implemented}} #pragma acc parallel loop auto if_present for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'worker' not yet implemented}} #pragma acc parallel loop auto worker for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'vector' not yet implemented}} #pragma acc parallel loop auto vector for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'nohost' not yet implemented}} @@ -155,7 +153,6 @@ void uses() { #pragma acc parallel loop auto tile(1+2, 1) for(unsigned j = 0; j < 5; ++j) for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'gang' not yet implemented}} #pragma acc parallel loop auto gang for(unsigned i = 0; i < 5; ++i); #pragma acc parallel loop auto wait @@ -167,10 +164,8 @@ void uses() { // expected-warning@+1{{OpenACC clause 'if_present' not yet implemented}} #pragma acc parallel loop if_present auto for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'worker' not yet implemented}} #pragma acc parallel loop worker auto for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'vector' not yet implemented}} #pragma acc parallel loop vector auto for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'nohost' not yet implemented}} @@ -276,7 +271,6 @@ void uses() { #pragma acc parallel loop tile(1+2, 1) auto for(unsigned j = 0; j < 5; ++j) for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'gang' not yet implemented}} #pragma acc parallel loop gang auto for(unsigned i = 0; i < 5; ++i); #pragma acc parallel loop wait auto @@ -289,10 +283,8 @@ void uses() { // expected-warning@+1{{OpenACC clause 'if_present' not yet implemented}} #pragma acc parallel loop independent if_present for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'worker' not yet implemented}} #pragma acc parallel loop independent worker for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'vector' not yet implemented}} #pragma acc parallel loop independent vector for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'nohost' not yet implemented}} @@ -398,7 +390,6 @@ void uses() { #pragma acc parallel loop independent tile(1+2, 1) for(unsigned j = 0; j < 5; ++j) for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'gang' not yet implemented}} #pragma acc parallel loop independent gang for(unsigned i = 0; i < 5; ++i); #pragma acc parallel loop independent wait @@ -410,10 +401,8 @@ void uses() { // expected-warning@+1{{OpenACC clause 'if_present' not yet implemented}} #pragma acc parallel loop if_present independent for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'worker' not yet implemented}} #pragma acc parallel loop worker independent for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'vector' not yet implemented}} #pragma acc parallel loop vector independent for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'nohost' not yet implemented}} @@ -519,7 +508,6 @@ void uses() { #pragma acc parallel loop tile(1+2, 1) independent for(unsigned j = 0; j < 5; ++j) for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'gang' not yet implemented}} #pragma acc parallel loop gang independent for(unsigned i = 0; i < 5; ++i); #pragma acc parallel loop wait independent @@ -650,19 +638,16 @@ void uses() { #pragma acc parallel loop seq wait for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+2{{OpenACC clause 'seq' may not appear on the same construct as a 'gang' clause on a 'parallel loop' construct}} - // TODOexpected-note@+1{{previous clause is here}} - // expected-warning@+1{{OpenACC clause 'gang' not yet implemented}} + // expected-error@+2{{OpenACC clause 'seq' may not appear on the same construct as a 'gang' clause on a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} #pragma acc parallel loop gang seq for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+2{{OpenACC clause 'seq' may not appear on the same construct as a 'worker' clause on a 'parallel loop' construct}} - // TODOexpected-note@+1{{previous clause is here}} - // expected-warning@+1{{OpenACC clause 'worker' not yet implemented}} + // expected-error@+2{{OpenACC clause 'seq' may not appear on the same construct as a 'worker' clause on a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} #pragma acc parallel loop worker seq for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+2{{OpenACC clause 'seq' may not appear on the same construct as a 'vector' clause on a 'parallel loop' construct}} - // TODOexpected-note@+1{{previous clause is here}} - // expected-warning@+1{{OpenACC clause 'vector' not yet implemented}} + // expected-error@+2{{OpenACC clause 'seq' may not appear on the same construct as a 'vector' clause on a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} #pragma acc parallel loop vector seq for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'finalize' not yet implemented}} diff --git a/clang/test/SemaOpenACC/combined-construct-device_type-clause.c b/clang/test/SemaOpenACC/combined-construct-device_type-clause.c index 9a60fb4c665e5..11bb342a2f638 100644 --- a/clang/test/SemaOpenACC/combined-construct-device_type-clause.c +++ b/clang/test/SemaOpenACC/combined-construct-device_type-clause.c @@ -39,7 +39,6 @@ void uses() { // 'worker', 'vector', 'seq', 'independent', 'auto', and 'tile' after // 'device_type'. - //expected-warning@+1{{OpenACC clause 'vector' not yet implemented, clause ignored}} #pragma acc parallel loop device_type(*) vector for(int i = 0; i < 5; ++i); @@ -57,7 +56,6 @@ void uses() { for(int i = 0; i < 5; ++i); #pragma acc kernels loop device_type(*) auto for(int i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'worker' not yet implemented, clause ignored}} #pragma acc parallel loop device_type(*) worker for(int i = 0; i < 5; ++i); // expected-error@+2{{OpenACC clause 'nohost' may not follow a 'device_type' clause in a 'serial loop' construct}} @@ -212,7 +210,6 @@ void uses() { for(int j = 0; j < 5; ++j) for(int i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}} #pragma acc serial loop dtype(*) gang for(int i = 0; i < 5; ++i); #pragma acc parallel loop device_type(*) wait diff --git a/clang/test/SemaOpenACC/combined-construct-gang-ast.cpp b/clang/test/SemaOpenACC/combined-construct-gang-ast.cpp new file mode 100644 index 0000000000000..167f56289c58d --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-gang-ast.cpp @@ -0,0 +1,215 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s +#ifndef PCH_HELPER +#define PCH_HELPER +void NormalUses() { + // CHECK: FunctionDecl{{.*}}NormalUses + // CHECK-NEXT: CompoundStmt + + int Val; + +#pragma acc parallel loop gang(dim:1) + for(int i = 0; i < 5; ++i); + // CHECK: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: gang clause dim + // CHECK-NEXT: ConstantExpr + // CHECK-NEXT: value: Int 1 + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1 + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop gang(static:Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: gang clause static + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop gang(num:1) gang(static:Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: gang clause num + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1 + // CHECK-NEXT: gang clause static + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop gang(dim:1, static:Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: gang clause dim static + // CHECK-NEXT: ConstantExpr + // CHECK-NEXT: value: Int 1 + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1 + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc serial loop gang(static:Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: gang clause static + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc serial loop gang(static:*) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: gang clause static + // CHECK-NEXT: OpenACCAsteriskSizeExpr + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc serial loop gang + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: gang clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop gang(num:1) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: gang clause num + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1 + // CHECK-NEXT: ForStmt + // CHECK: NullStmt +} + +template +void TemplateUses(T Val) { + // CHECK: FunctionTemplateDecl{{.*}}TemplateUses + // CHECK-NEXT: TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 T + // CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} referenced 'unsigned int' depth 0 index 1 One + // CHECK-NEXT: FunctionDecl{{.*}} TemplateUses 'void (T)' + // CHECK-NEXT: ParmVarDecl{{.*}} referenced Val 'T' + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel loop gang(dim:One) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: gang clause dim + // CHECK-NEXT: DeclRefExpr{{.*}}'One' 'unsigned int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop gang(static:Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: gang clause static + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + +#pragma acc parallel loop gang(static:*) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: gang clause static + // CHECK-NEXT: OpenACCAsteriskSizeExpr + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop gang(dim:One) gang(static:Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: gang clause dim + // CHECK-NEXT: DeclRefExpr{{.*}}'One' 'unsigned int' + // CHECK-NEXT: gang clause static + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop gang(dim:One, static:Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: gang clause dim static + // CHECK-NEXT: DeclRefExpr{{.*}}'One' 'unsigned int' + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc serial loop gang + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: gang clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // Instantiation: + // CHECK-NEXT: FunctionDecl{{.*}} used TemplateUses 'void (int)' implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'int' + // CHECK-NEXT: BuiltinType{{.*}} 'int' + // CHECK-NEXT: TemplateArgument integral '1U' + // CHECK-NEXT: ParmVarDecl{{.*}} used Val 'int' + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: gang clause dim + // CHECK-NEXT: ConstantExpr + // CHECK-NEXT: value: Int 1 + // CHECK-NEXT: SubstNonTypeTemplateParmExpr + // CHECK-NEXT: NonTypeTemplateParmDecl + // CHECK-NEXT: IntegerLiteral{{.*}}'unsigned int' 1 + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: gang clause static + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: gang clause static + // CHECK-NEXT: OpenACCAsteriskSizeExpr + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: gang clause dim + // CHECK-NEXT: ConstantExpr + // CHECK-NEXT: value: Int 1 + // CHECK-NEXT: SubstNonTypeTemplateParmExpr + // CHECK-NEXT: NonTypeTemplateParmDecl + // CHECK-NEXT: IntegerLiteral{{.*}}'unsigned int' 1 + // CHECK-NEXT: gang clause static + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: gang clause dim static + // CHECK-NEXT: ConstantExpr + // CHECK-NEXT: value: Int 1 + // CHECK-NEXT: SubstNonTypeTemplateParmExpr + // CHECK-NEXT: NonTypeTemplateParmDecl + // CHECK-NEXT: IntegerLiteral{{.*}}'unsigned int' 1 + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: gang clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt +} + +void inst() { + TemplateUses(5); +} + +#endif // PCH_HELPER diff --git a/clang/test/SemaOpenACC/combined-construct-gang-clause.cpp b/clang/test/SemaOpenACC/combined-construct-gang-clause.cpp new file mode 100644 index 0000000000000..c5346c4cf5b90 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-gang-clause.cpp @@ -0,0 +1,307 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +struct S{}; +struct Converts{ + operator int(); +}; + +template +void ParallelTempl() { + T i; + + // expected-error@+1{{'num' argument on 'gang' clause is not permitted on a 'parallel loop' construct}} +#pragma acc parallel loop gang(i) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{'num' argument on 'gang' clause is not permitted on a 'parallel loop' construct}} +#pragma acc parallel loop gang(num:i) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{argument to 'gang' clause dimension must be a constant expression}} +#pragma acc parallel loop gang(dim:i) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{argument to 'gang' clause dimension must be 1, 2, or 3: evaluated to 0}} +#pragma acc parallel loop gang(dim:Zero) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop gang(dim:Two) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{argument to 'gang' clause dimension must be 1, 2, or 3: evaluated to 4}} +#pragma acc parallel loop gang(dim:Four) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop gang(static:i) gang(dim:Two) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop gang(static:i, dim:Two) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop gang(dim:Two) gang(static:*) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop gang(dim:Two, static:*) + for(int i = 0; i < 5; ++i); + + // expected-error@+4{{OpenACC 'gang' clause may have at most one 'static' argument}} + // expected-note@+3{{previous expression is here}} + // expected-error@+2{{OpenACC 'gang' clause may have at most one 'dim' argument}} + // expected-note@+1{{previous expression is here}} +#pragma acc parallel loop gang(dim:Two, static:*, dim:1, static:i) + for(int i = 0; i < 5; ++i); +} + +void Parallel() { + ParallelTempl(); // expected-note{{in instantiation of function template}} + int i; + + // expected-error@+1{{'num' argument on 'gang' clause is not permitted on a 'parallel loop' construct}} +#pragma acc parallel loop gang(i) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{'num' argument on 'gang' clause is not permitted on a 'parallel loop' construct}} +#pragma acc parallel loop gang(num:i) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{argument to 'gang' clause dimension must be a constant expression}} +#pragma acc parallel loop gang(dim:i) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{argument to 'gang' clause dimension must be 1, 2, or 3: evaluated to 0}} +#pragma acc parallel loop gang(dim:0) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop gang(dim:2) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{argument to 'gang' clause dimension must be 1, 2, or 3: evaluated to 4}} +#pragma acc parallel loop gang(dim:4) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop gang(static:i) gang(dim:2) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop gang(static:i, dim:2) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop gang(dim:2) gang(static:*) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop gang(dim:2, static:*) + for(int i = 0; i < 5; ++i); + + // expected-error@+4{{OpenACC 'gang' clause may have at most one 'static' argument}} + // expected-note@+3{{previous expression is here}} + // expected-error@+2{{OpenACC 'gang' clause may have at most one 'dim' argument}} + // expected-note@+1{{previous expression is here}} +#pragma acc parallel loop gang(dim:2, static:*, dim:1, static:i) + for(int i = 0; i < 5; ++i); +} + +template +void StaticIsIntegralTempl() { + SomeS s; + // expected-error@+1{{OpenACC clause 'gang' requires expression of integer type ('S' invalid)}} +#pragma acc parallel loop gang(dim:2) gang(static:s) + for(int i = 0; i < 5; ++i); + + SomeC C; +#pragma acc parallel loop gang(dim:2) gang(static:C) + for(int i = 0; i < 5; ++i); + Int i; +#pragma acc parallel loop gang(dim:2) gang(static:i) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop gang(dim:2) gang(static:*) + for(int i = 0; i < 5; ++i); +} + +void StaticIsIntegral() { + StaticIsIntegralTempl();// expected-note{{in instantiation of function template}} + + S s; + // expected-error@+1{{OpenACC clause 'gang' requires expression of integer type ('S' invalid)}} +#pragma acc parallel loop gang(dim:2) gang(static:s) + for(int i = 0; i < 5; ++i); + + Converts C; +#pragma acc parallel loop gang(dim:2) gang(static:C) + for(int i = 0; i < 5; ++i); +} + +template +void SerialTempl() { + // expected-error@+1{{'num' argument on 'gang' clause is not permitted on a 'serial loop'}} +#pragma acc serial loop gang(I) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{'num' argument on 'gang' clause is not permitted on a 'serial loop'}} +#pragma acc serial loop gang(num:I) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{'dim' argument on 'gang' clause is not permitted on a 'serial loop'}} +#pragma acc serial loop gang(dim:I) + for(int i = 0; i < 5; ++i); + +#pragma acc serial loop gang(static:I) + for(int i = 0; i < 5; ++i); +} + +void Serial() { + SerialTempl<2>(); + + // expected-error@+1{{'num' argument on 'gang' clause is not permitted on a 'serial loop'}} +#pragma acc serial loop gang(1) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{'num' argument on 'gang' clause is not permitted on a 'serial loop'}} +#pragma acc serial loop gang(num:1) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{'dim' argument on 'gang' clause is not permitted on a 'serial loop'}} +#pragma acc serial loop gang(dim:1) + for(int i = 0; i < 5; ++i); + +#pragma acc serial loop gang(static:1) + for(int i = 0; i < 5; ++i); + + int i; +#pragma acc serial loop gang(static:i) + for(int i = 0; i < 5; ++i); +} + +template +void KernelsTempl() { + T t; + // expected-error@+1{{'dim' argument on 'gang' clause is not permitted on a 'kernels loop'}} +#pragma acc kernels loop gang(dim:t) + for(int i = 0; i < 5; ++i); + +#pragma acc kernels loop gang(static:t) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{'num_gangs' clause not allowed on a 'kernels loop' construct that has a 'gang' clause with a 'num' argument}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop gang(t) num_gangs(t) + for(int i = 0; i < 5; ++i); + + // OK, kernels loop should block this. +#pragma acc kernels num_gangs(t) +#pragma acc kernels loop gang(static:t) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{'num' argument to 'gang' clause not allowed on a 'kernels loop' construct that has a 'num_gangs' clause}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop num_gangs(t) gang(t) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{'num_gangs' clause not allowed on a 'kernels loop' construct that has a 'gang' clause with a 'num' argument}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop gang(num:t) num_gangs(t) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{'num' argument to 'gang' clause not allowed on a 'kernels loop' construct that has a 'num_gangs' clause}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop num_gangs(t) gang(num:t) + for(int i = 0; i < 5; ++i); +} + +void Kernels() { + KernelsTempl(); + + // expected-error@+1{{'dim' argument on 'gang' clause is not permitted on a 'kernels loop'}} +#pragma acc kernels loop gang(dim:1) + for(int i = 0; i < 5; ++i); + + unsigned t; +#pragma acc kernels loop gang(static:t) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{'num_gangs' clause not allowed on a 'kernels loop' construct that has a 'gang' clause with a 'num' argument}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop gang(t) num_gangs(t) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{'num' argument to 'gang' clause not allowed on a 'kernels loop' construct that has a 'num_gangs' clause}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop num_gangs(t) gang(t) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{'num_gangs' clause not allowed on a 'kernels loop' construct that has a 'gang' clause with a 'num' argument}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop gang(num:t) num_gangs(t) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{'num' argument to 'gang' clause not allowed on a 'kernels loop' construct that has a 'num_gangs' clause}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop num_gangs(t) gang(num:t) + for(int i = 0; i < 5; ++i); + + // OK, intervening compute/combined construct. +#pragma acc kernels loop gang(num:1) + for(int i = 0; i < 5; ++i) { +#pragma acc serial loop gang(static:1) + for(int i = 0; i < 5; ++i); + } +#pragma acc kernels loop gang(num:1) + for(int i = 0; i < 5; ++i) { +#pragma acc serial +#pragma acc loop gang(static:1) + for(int i = 0; i < 5; ++i); + } +#pragma acc kernels +#pragma acc loop gang(num:1) + for(int i = 0; i < 5; ++i) { +#pragma acc serial loop gang(static:1) + for(int i = 0; i < 5; ++i); + } + +#pragma acc kernels loop gang(num:1) + for(int i = 0; i < 5; ++i) { + // expected-error@+2{{loop with a 'gang' clause may not exist in the region of a 'gang' clause on a 'kernels loop' construct}} + // expected-note@-3{{previous clause is here}} +#pragma acc loop gang(static:1) + for(int i = 0; i < 5; ++i); + } + + // OK, on a different 'loop', not in the associated stmt. +#pragma acc kernels loop gang(num:1) + for(int i = 0; i < 5; ++i); +#pragma acc loop gang(static:1) + for(int i = 0; i < 5; ++i); + + // OK, on a different 'loop', not in the associated stmt. +#pragma acc kernels loop gang(num:1) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop gang(static:1) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{OpenACC 'gang' clause may have at most one unnamed or 'num' argument}} + // expected-note@+1{{previous expression is here}} +#pragma acc kernels loop gang(5, num:1) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{OpenACC 'gang' clause may have at most one unnamed or 'num' argument}} + // expected-note@+1{{previous expression is here}} +#pragma acc kernels loop gang(num:5, 1) + for(int i = 0; i < 5; ++i); + + // expected-error@+3{{OpenACC 'gang' clause may have at most one unnamed or 'num' argument}} + // expected-note@+2{{previous expression is here}} +#pragma acc kernels +#pragma acc kernels loop gang(num:5, num:1) + for(int i = 0; i < 5; ++i); +} + +void MaxOneEntry() { + // expected-error@+2{{OpenACC 'gang' clause may have at most one 'static' argument}} + // expected-note@+1{{previous expression is here}} +#pragma acc kernels loop gang(static: 1, static:1) + for(int i = 0; i < 5; ++i); + +#pragma acc kernels loop gang gang(static:1) + for(int i = 0; i < 5; ++i); +} + + diff --git a/clang/test/SemaOpenACC/combined-construct-vector-ast.cpp b/clang/test/SemaOpenACC/combined-construct-vector-ast.cpp new file mode 100644 index 0000000000000..7b103021ccd55 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-vector-ast.cpp @@ -0,0 +1,176 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s +#ifndef PCH_HELPER +#define PCH_HELPER +void NormalUses() { + // CHECK: FunctionDecl{{.*}}NormalUses + // CHECK-NEXT: CompoundStmt + + int Val; + +#pragma acc parallel loop vector + for(int i = 0; i < 5; ++i); + // CHECK: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop vector(Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc serial loop vector + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop vector + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop vector(Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt +} + +template +void TemplateUses(T Val) { + // CHECK: FunctionTemplateDecl{{.*}}TemplateUses + // CHECK-NEXT: TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 T + // CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} referenced 'unsigned int' depth 0 index 1 One + // CHECK-NEXT: FunctionDecl{{.*}} TemplateUses 'void (T)' + // CHECK-NEXT: ParmVarDecl{{.*}} referenced Val 'T' + // CHECK-NEXT: CompoundStmt + + +#pragma acc parallel loop vector + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop vector(Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop vector(length:One) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: DeclRefExpr{{.*}}'One' 'unsigned int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc serial loop vector + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop vector + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop vector(Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop vector(length:One) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: DeclRefExpr{{.*}}'One' 'unsigned int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + + // Instantiation: + // CHECK-NEXT: FunctionDecl{{.*}} used TemplateUses 'void (int)' implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'int' + // CHECK-NEXT: BuiltinType{{.*}} 'int' + // CHECK-NEXT: TemplateArgument integral '1U' + // CHECK-NEXT: ParmVarDecl{{.*}} used Val 'int' + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}} 'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: SubstNonTypeTemplateParmExpr + // CHECK-NEXT: NonTypeTemplateParmDecl + // CHECK-NEXT: IntegerLiteral{{.*}}1 + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}} 'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: vector clause + // CHECK-NEXT: SubstNonTypeTemplateParmExpr + // CHECK-NEXT: NonTypeTemplateParmDecl + // CHECK-NEXT: IntegerLiteral{{.*}}1 + // CHECK-NEXT: ForStmt + // CHECK: NullStmt +} + +void inst() { + TemplateUses(5); +} + +#endif // PCH_HELPER diff --git a/clang/test/SemaOpenACC/combined-construct-vector-clause.cpp b/clang/test/SemaOpenACC/combined-construct-vector-clause.cpp new file mode 100644 index 0000000000000..f96a36c1e395b --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-vector-clause.cpp @@ -0,0 +1,171 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +template +void TemplUses(T t) { + +#pragma acc parallel loop vector + for(int j = 0; j < 5; ++j); + +#pragma acc parallel loop vector(I) + for(int j = 0; j < 5; ++j); + +#pragma acc parallel loop vector(length:I) + for(int j = 0; j < 5; ++j); + +#pragma acc serial loop vector + for(int j = 0; j < 5; ++j); + + // expected-error@+1{{'length' argument on 'vector' clause is not permitted on a 'serial loop' construct}} +#pragma acc serial loop vector(I) + for(int j = 0; j < 5; ++j); + + // expected-error@+1{{'length' argument on 'vector' clause is not permitted on a 'serial loop' construct}} +#pragma acc serial loop vector(length:I) + for(int j = 0; j < 5; ++j); + +#pragma acc kernels loop vector + for(int j = 0; j < 5; ++j); + +#pragma acc kernels loop vector(I) + for(int j = 0; j < 5; ++j); + +#pragma acc kernels loop vector(length:I) + for(int j = 0; j < 5; ++j); + +#pragma acc kernels loop vector vector_length(t) + for(int j = 0; j < 5; ++j); + +#pragma acc kernels loop vector_length(t) vector + for(int j = 0; j < 5; ++j); + + // expected-error@+2{{'vector_length' clause not allowed on a 'kernels loop' construct that has a 'vector' clause with an argument}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop vector(I) vector_length(t) + for(int j = 0; j < 5; ++j); + + // expected-error@+2{{'length' argument to 'vector' clause not allowed on a 'kernels loop' construct that has a 'vector_length' clause}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop vector_length(t) vector(I) + for(int j = 0; j < 5; ++j); + +#pragma acc parallel loop vector + for(int j = 0; j < 5; ++j) { + // expected-error@+4{{loop with a 'vector' clause may not exist in the region of a 'vector' clause}} + // expected-error@+3{{loop with a 'worker' clause may not exist in the region of a 'vector' clause}} + // expected-error@+2{{loop with a 'gang' clause may not exist in the region of a 'vector' clause}} + // expected-note@-5 3{{previous clause is here}} +#pragma acc loop vector worker, gang + for(int j = 0; j < 5; ++j); + } +#pragma acc parallel loop vector + for(int j = 0; j < 5; ++j) { +#pragma acc serial loop vector worker, gang + for(int j = 0; j < 5; ++j); + } + +#pragma acc loop vector + for(int j = 0; j < 5; ++j) { +#pragma acc serial loop vector worker, gang + for(int j = 0; j < 5; ++j); + } + +#pragma acc kernels vector_length(t) + for(int j = 0; j < 5; ++j) { + // expected-error@+1{{'length' argument on 'vector' clause is not permitted on a 'serial loop' construct}} +#pragma acc serial loop vector(I) + for(int j = 0; j < 5; ++j); + } + +#pragma acc kernels vector_length(t) + for(int j = 0; j < 5; ++j) { +#pragma acc parallel loop vector(I) + for(int j = 0; j < 5; ++j); + } +} + +void uses() { + TemplUses(5); + + unsigned I; + int t; + +#pragma acc parallel loop vector + for(int j = 0; j < 5; ++j); + +#pragma acc parallel loop vector(I) + for(int j = 0; j < 5; ++j); + +#pragma acc parallel loop vector(length:I) + for(int j = 0; j < 5; ++j); + +#pragma acc serial loop vector + for(int j = 0; j < 5; ++j); + + // expected-error@+1{{'length' argument on 'vector' clause is not permitted on a 'serial loop' construct}} +#pragma acc serial loop vector(I) + for(int j = 0; j < 5; ++j); + + // expected-error@+1{{'length' argument on 'vector' clause is not permitted on a 'serial loop' construct}} +#pragma acc serial loop vector(length:I) + for(int j = 0; j < 5; ++j); + +#pragma acc kernels loop vector + for(int j = 0; j < 5; ++j); + +#pragma acc kernels loop vector(I) + for(int j = 0; j < 5; ++j); + +#pragma acc kernels loop vector(length:I) + for(int j = 0; j < 5; ++j); + +#pragma acc kernels loop vector vector_length(t) + for(int j = 0; j < 5; ++j); + +#pragma acc kernels loop vector_length(t) vector + for(int j = 0; j < 5; ++j); + + // expected-error@+2{{'vector_length' clause not allowed on a 'kernels loop' construct that has a 'vector' clause with an argument}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop vector(I) vector_length(t) + for(int j = 0; j < 5; ++j); + + // expected-error@+2{{'length' argument to 'vector' clause not allowed on a 'kernels loop' construct that has a 'vector_length' clause}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop vector_length(t) vector(I) + for(int j = 0; j < 5; ++j); + +#pragma acc parallel loop vector + for(int j = 0; j < 5; ++j) { + // expected-error@+4{{loop with a 'vector' clause may not exist in the region of a 'vector' clause}} + // expected-error@+3{{loop with a 'worker' clause may not exist in the region of a 'vector' clause}} + // expected-error@+2{{loop with a 'gang' clause may not exist in the region of a 'vector' clause}} + // expected-note@-5 3{{previous clause is here}} +#pragma acc loop vector worker, gang + for(int j = 0; j < 5; ++j); + } +#pragma acc parallel loop vector + for(int j = 0; j < 5; ++j) { +#pragma acc serial loop vector worker, gang + for(int j = 0; j < 5; ++j); + } + +#pragma acc loop vector + for(int j = 0; j < 5; ++j) { +#pragma acc serial loop vector worker, gang + for(int j = 0; j < 5; ++j); + } + +#pragma acc kernels vector_length(t) + for(int j = 0; j < 5; ++j) { +#pragma acc parallel loop vector(I) + for(int j = 0; j < 5; ++j); + } + +#pragma acc kernels vector_length(t) + for(int j = 0; j < 5; ++j) { + // expected-error@+1{{'length' argument on 'vector' clause is not permitted on a 'serial loop' construct}} +#pragma acc serial loop vector(I) + for(int j = 0; j < 5; ++j); + } +} + diff --git a/clang/test/SemaOpenACC/combined-construct-worker-ast.cpp b/clang/test/SemaOpenACC/combined-construct-worker-ast.cpp new file mode 100644 index 0000000000000..6ac0fdb35709f --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-worker-ast.cpp @@ -0,0 +1,135 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s +#ifndef PCH_HELPER +#define PCH_HELPER +void NormalUses() { + // CHECK: FunctionDecl{{.*}}NormalUses + // CHECK-NEXT: CompoundStmt + + int Val; + +#pragma acc parallel loop worker + for(int i = 0; i < 5; ++i); + // CHECK: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: worker clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt +#pragma acc serial loop worker + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: worker clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop worker(Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: worker clause + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}} 'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt +#pragma acc kernels loop worker(num:Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: worker clause + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}} 'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt +} + +template +void TemplateUses(T Val) { + // CHECK: FunctionTemplateDecl{{.*}}TemplateUses + // CHECK-NEXT: TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 T + // CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} referenced 'unsigned int' depth 0 index 1 One + // CHECK-NEXT: FunctionDecl{{.*}} TemplateUses 'void (T)' + // CHECK-NEXT: ParmVarDecl{{.*}} referenced Val 'T' + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel loop worker + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: worker clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt +#pragma acc serial loop worker + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: worker clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop worker(Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: worker clause + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt +#pragma acc kernels loop worker(num:Val) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: worker clause + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop worker(num:One) + for(int i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: worker clause + // CHECK-NEXT: DeclRefExpr{{.*}}'One' 'unsigned int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // Instantiation: + // CHECK-NEXT: FunctionDecl{{.*}} used TemplateUses 'void (int)' implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'int' + // CHECK-NEXT: BuiltinType{{.*}} 'int' + // CHECK-NEXT: TemplateArgument integral '1U' + // CHECK-NEXT: ParmVarDecl{{.*}} used Val 'int' + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: worker clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: worker clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: worker clause + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: worker clause + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'Val' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: worker clause + // CHECK-NEXT: SubstNonTypeTemplateParmExpr + // CHECK-NEXT: NonTypeTemplateParmDecl + // CHECK-NEXT: IntegerLiteral{{.*}}'unsigned int' 1 + // CHECK-NEXT: ForStmt + // CHECK: NullStmt +} + +void inst() { + TemplateUses(5); +} + +#endif // PCH_HELPER diff --git a/clang/test/SemaOpenACC/combined-construct-worker-clause.cpp b/clang/test/SemaOpenACC/combined-construct-worker-clause.cpp new file mode 100644 index 0000000000000..1351f9ea0c69c --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-worker-clause.cpp @@ -0,0 +1,150 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +template +void TemplUses() { + +#pragma acc parallel loop worker + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{expected expression}} +#pragma acc parallel loop worker() + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{'num' argument on 'worker' clause is not permitted on a 'parallel loop' construct}} +#pragma acc parallel loop worker(I) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{'num' argument on 'worker' clause is not permitted on a 'parallel loop' construct}} +#pragma acc parallel loop worker(num:I) + for(int i = 0; i < 5; ++i); + +#pragma acc serial loop worker + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{expected expression}} +#pragma acc serial loop worker() + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{'num' argument on 'worker' clause is not permitted on a 'serial loop' construct}} +#pragma acc serial loop worker(I) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{'num' argument on 'worker' clause is not permitted on a 'serial loop' construct}} +#pragma acc serial loop worker(num:I) + for(int i = 0; i < 5; ++i); + +#pragma acc kernels loop worker(I) + for(int i = 0; i < 5; ++i); + +#pragma acc kernels loop worker(num:I) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{'num' argument to 'worker' clause not allowed on a 'kernels loop' construct that has a 'num_workers' clause}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop num_workers(1) worker(num:I) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{'num_workers' clause not allowed on a 'kernels loop' construct that has a 'worker' clause with an argument}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop worker(num:I) num_workers(1) + for(int i = 0; i < 5; ++i); +} + +void NormalUses() { + TemplUses<4>(); + + int I; +#pragma acc parallel loop worker + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{expected expression}} +#pragma acc parallel loop worker() + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{'num' argument on 'worker' clause is not permitted on a 'parallel loop' construct}} +#pragma acc parallel loop worker(I) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{'num' argument on 'worker' clause is not permitted on a 'parallel loop' construct}} +#pragma acc parallel loop worker(num:I) + for(int i = 0; i < 5; ++i); + +#pragma acc serial loop worker + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{expected expression}} +#pragma acc serial loop worker() + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{'num' argument on 'worker' clause is not permitted on a 'serial loop' construct}} +#pragma acc serial loop worker(I) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{'num' argument on 'worker' clause is not permitted on a 'serial loop' construct}} +#pragma acc serial loop worker(num:I) + for(int i = 0; i < 5; ++i); + +#pragma acc kernels loop worker(I) + for(int i = 0; i < 5; ++i); + +#pragma acc kernels loop worker(num:I) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{'num' argument to 'worker' clause not allowed on a 'kernels loop' construct that has a 'num_workers' clause}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop num_workers(1) worker(num:I) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{'num_workers' clause not allowed on a 'kernels loop' construct that has a 'worker' clause with an argument}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop worker(num:I) num_workers(1) + for(int i = 0; i < 5; ++i); + + // OK, kernels loop is a new compute construct +#pragma acc kernels num_workers(1) + for(int i = 0; i < 5; ++i) { +#pragma acc kernels loop worker(num:1) + for(int i = 0; i < 5; ++i); + } +#pragma acc kernels loop num_workers(1) + for(int i = 0; i < 5; ++i) { +#pragma acc kernels loop worker(num:1) + for(int i = 0; i < 5; ++i); + } + +#pragma acc kernels loop num_workers(1) + for(int i = 0; i < 5; ++i) { + // expected-error@+2{{'num' argument to 'worker' clause not allowed on a 'loop' construct associated with a 'kernels loop' construct that has a 'num_workers' clause}} + // expected-note@-3{{previous clause is here}} +#pragma acc loop worker(num:1) + for(int i = 0; i < 5; ++i); + } + +#pragma acc parallel loop worker + for(int i = 0; i < 5; ++i) { + // expected-error@+4{{loop with a 'gang' clause may not exist in the region of a 'worker' clause}} + // expected-note@-3{{previous clause is here}} + // expected-error@+2{{loop with a 'worker' clause may not exist in the region of a 'worker' clause}} + // expected-note@-5{{previous clause is here}} +#pragma acc loop gang, worker, vector + for(int i = 0; i < 5; ++i); + } +#pragma acc kernels loop worker + for(int i = 0; i < 5; ++i) { + // expected-error@+4{{loop with a 'gang' clause may not exist in the region of a 'worker' clause}} + // expected-note@-3{{previous clause is here}} + // expected-error@+2{{loop with a 'worker' clause may not exist in the region of a 'worker' clause}} + // expected-note@-5{{previous clause is here}} +#pragma acc loop gang, worker, vector + for(int i = 0; i < 5; ++i); + } +#pragma acc serial loop worker + for(int i = 0; i < 5; ++i) { + // expected-error@+4{{loop with a 'gang' clause may not exist in the region of a 'worker' clause}} + // expected-note@-3{{previous clause is here}} + // expected-error@+2{{loop with a 'worker' clause may not exist in the region of a 'worker' clause}} + // expected-note@-5{{previous clause is here}} +#pragma acc loop gang, worker, vector + for(int i = 0; i < 5; ++i); + } +} diff --git a/clang/test/SemaOpenACC/loop-construct-gang-clause.cpp b/clang/test/SemaOpenACC/loop-construct-gang-clause.cpp index a22e7e865a801..6b4c03bbc50c6 100644 --- a/clang/test/SemaOpenACC/loop-construct-gang-clause.cpp +++ b/clang/test/SemaOpenACC/loop-construct-gang-clause.cpp @@ -278,12 +278,19 @@ void Kernels() { #pragma acc kernels #pragma acc loop gang(num:1) for(int j = 0; j < 5; ++j) { - // expected-error@+2{{loop with a 'gang' clause may not exist in the region of a 'gang' clause on a 'kernels' compute construct}} + // expected-error@+2{{loop with a 'gang' clause may not exist in the region of a 'gang' clause on a 'kernels' construct}} // expected-note@-3{{previous clause is here}} #pragma acc loop gang(static:1) for(int i = 0; i < 5; ++i); } +#pragma acc kernels +#pragma acc loop gang(num:1) + for(int j = 0; j < 5; ++j) { +#pragma acc loop worker(1) vector(1) + for(int i = 0; i < 5; ++i); + } + #pragma acc kernels #pragma acc loop gang(num:1) for(int j = 0; j < 5; ++j) { diff --git a/clang/test/SemaOpenACC/loop-construct-vector-clause.cpp b/clang/test/SemaOpenACC/loop-construct-vector-clause.cpp index 3260e368fbb42..1fed82c510208 100644 --- a/clang/test/SemaOpenACC/loop-construct-vector-clause.cpp +++ b/clang/test/SemaOpenACC/loop-construct-vector-clause.cpp @@ -18,12 +18,12 @@ void TemplUses(Int I, NotInt NI, ConvertsToInt CTI) { #pragma acc loop vector(length: NI) for(int j = 0; j < 5; ++j); - // expected-error@+2{{'num' argument on 'vector' clause is not permitted on a 'loop' construct associated with a 'serial' compute construct}} + // expected-error@+2{{'length' argument on 'vector' clause is not permitted on a 'loop' construct associated with a 'serial' compute construct}} #pragma acc serial #pragma acc loop vector(length: I) for(int j = 0; j < 5; ++j); - // expected-error@+3{{'num' argument to 'vector' clause not allowed on a 'loop' construct associated with a 'kernels' construct that has a 'vector_length' clause}} + // expected-error@+3{{'length' argument to 'vector' clause not allowed on a 'loop' construct associated with a 'kernels' construct that has a 'vector_length' clause}} // expected-note@+1{{previous clause is here}} #pragma acc kernels vector_length(I) #pragma acc loop vector(length: CTI) @@ -87,12 +87,12 @@ void uses() { #pragma acc loop vector(length: NI) for(int j = 0; j < 5; ++j); - // expected-error@+2{{'num' argument on 'vector' clause is not permitted on a 'loop' construct associated with a 'serial' compute construct}} + // expected-error@+2{{'length' argument on 'vector' clause is not permitted on a 'loop' construct associated with a 'serial' compute construct}} #pragma acc serial #pragma acc loop vector(length: i) for(int j = 0; j < 5; ++j); - // expected-error@+3{{'num' argument to 'vector' clause not allowed on a 'loop' construct associated with a 'kernels' construct that has a 'vector_length' clause}} + // expected-error@+3{{'length' argument to 'vector' clause not allowed on a 'loop' construct associated with a 'kernels' construct that has a 'vector_length' clause}} // expected-note@+1{{previous clause is here}} #pragma acc kernels vector_length(i) #pragma acc loop vector(length: i) diff --git a/clang/test/SemaOpenACC/loop-construct-worker-clause.cpp b/clang/test/SemaOpenACC/loop-construct-worker-clause.cpp index 8b95981c2b80f..35c63e467a505 100644 --- a/clang/test/SemaOpenACC/loop-construct-worker-clause.cpp +++ b/clang/test/SemaOpenACC/loop-construct-worker-clause.cpp @@ -138,6 +138,12 @@ void uses() { for(int k = 0; k < 5; ++k); } +#pragma acc loop worker + for(int i= 0; i< 5; ++i) { +#pragma acc loop vector + for(int k = 0; k < 5; ++k); + } + #pragma acc loop worker for(int i= 0; i< 5; ++i) { #pragma acc parallel diff --git a/clang/tools/clang-format/git-clang-format b/clang/tools/clang-format/git-clang-format index a322d4abf0ec2..da271bbe6e3a0 100755 --- a/clang/tools/clang-format/git-clang-format +++ b/clang/tools/clang-format/git-clang-format @@ -1,12 +1,12 @@ #!/usr/bin/env python3 # -#===- git-clang-format - ClangFormat Git Integration ---------*- python -*--===# +# ===- git-clang-format - ClangFormat Git Integration -------*- python -*--=== # # # 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 # -#===------------------------------------------------------------------------===# +# ===----------------------------------------------------------------------=== # r""" clang-format git integration @@ -32,10 +32,11 @@ import re import subprocess import sys -usage = ('git clang-format [OPTIONS] [] [|--staged] ' - '[--] [...]') +usage = ( + "git clang-format [OPTIONS] [] [|--staged] [--] [...]" +) -desc = ''' +desc = """ If zero or one commits are given, run clang-format on all lines that differ between the working directory and , which defaults to HEAD. Changes are only applied to the working directory, or in the stage/index. @@ -58,639 +59,815 @@ The following git-config settings set the default of the corresponding option: clangFormat.commit clangFormat.extensions clangFormat.style -''' +""" # Name of the temporary index file in which save the output of clang-format. # This file is created within the .git directory. -temp_index_basename = 'clang-format-index' +temp_index_basename = "clang-format-index" -Range = collections.namedtuple('Range', 'start, count') +Range = collections.namedtuple("Range", "start, count") def main(): - config = load_git_config() - - # In order to keep '--' yet allow options after positionals, we need to - # check for '--' ourselves. (Setting nargs='*' throws away the '--', while - # nargs=argparse.REMAINDER disallows options after positionals.) - argv = sys.argv[1:] - try: - idx = argv.index('--') - except ValueError: - dash_dash = [] - else: - dash_dash = argv[idx:] - argv = argv[:idx] - - default_extensions = ','.join([ - # From clang/lib/Frontend/FrontendOptions.cpp, all lower case - 'c', 'h', # C - 'm', # ObjC - 'mm', # ObjC++ - 'cc', 'cp', 'cpp', 'c++', 'cxx', 'hh', 'hpp', 'hxx', 'inc', # C++ - 'ccm', 'cppm', 'cxxm', 'c++m', # C++ Modules - 'cu', 'cuh', # CUDA - # Other languages that clang-format supports - 'proto', 'protodevel', # Protocol Buffers - 'java', # Java - 'js', 'mjs', 'cjs', # JavaScript - 'ts', # TypeScript - 'cs', # C Sharp - 'json', # Json - 'sv', 'svh', 'v', 'vh', # Verilog - 'td', # TableGen - 'txtpb', 'textpb', 'pb.txt', 'textproto', 'asciipb', # TextProto - ]) - - p = argparse.ArgumentParser( - usage=usage, formatter_class=argparse.RawDescriptionHelpFormatter, - description=desc) - p.add_argument('--binary', - default=config.get('clangformat.binary', 'clang-format'), - help='path to clang-format'), - p.add_argument('--commit', - default=config.get('clangformat.commit', 'HEAD'), - help='default commit to use if none is specified'), - p.add_argument('--diff', action='store_true', - help='print a diff instead of applying the changes') - p.add_argument('--diffstat', action='store_true', - help='print a diffstat instead of applying the changes') - p.add_argument('--extensions', - default=config.get('clangformat.extensions', - default_extensions), - help=('comma-separated list of file extensions to format, ' - 'excluding the period and case-insensitive')), - p.add_argument('-f', '--force', action='store_true', - help='allow changes to unstaged files') - p.add_argument('-p', '--patch', action='store_true', - help='select hunks interactively') - p.add_argument('-q', '--quiet', action='count', default=0, - help='print less information') - p.add_argument('--staged', '--cached', action='store_true', - help='format lines in the stage instead of the working dir') - p.add_argument('--style', - default=config.get('clangformat.style', None), - help='passed to clang-format'), - p.add_argument('-v', '--verbose', action='count', default=0, - help='print extra information') - p.add_argument('--diff_from_common_commit', action='store_true', - help=('diff from the last common commit for commits in ' - 'separate branches rather than the exact point of the ' - 'commits')) - # We gather all the remaining positional arguments into 'args' since we need - # to use some heuristics to determine whether or not was present. - # However, to print pretty messages, we make use of metavar and help. - p.add_argument('args', nargs='*', metavar='', - help='revision from which to compute the diff') - p.add_argument('ignored', nargs='*', metavar='...', - help='if specified, only consider differences in these files') - opts = p.parse_args(argv) - - opts.verbose -= opts.quiet - del opts.quiet - - commits, files = interpret_args(opts.args, dash_dash, opts.commit) - if len(commits) > 2: - die('at most two commits allowed; %d given' % len(commits)) - if len(commits) == 2: - if opts.staged: - die('--staged is not allowed when two commits are given') - if not opts.diff: - die('--diff is required when two commits are given') - elif opts.diff_from_common_commit: - die('--diff_from_common_commit is only allowed when two commits are given') - - if os.path.dirname(opts.binary): - opts.binary = os.path.abspath(opts.binary) - - changed_lines = compute_diff_and_extract_lines(commits, - files, - opts.staged, - opts.diff_from_common_commit) - if opts.verbose >= 1: - ignored_files = set(changed_lines) - filter_by_extension(changed_lines, opts.extensions.lower().split(',')) - # The computed diff outputs absolute paths, so we must cd before accessing - # those files. - cd_to_toplevel() - filter_symlinks(changed_lines) - filter_ignored_files(changed_lines, binary=opts.binary) - if opts.verbose >= 1: - ignored_files.difference_update(changed_lines) - if ignored_files: - print('Ignoring the following files (wrong extension, symlink, or ' - 'ignored by clang-format):') - for filename in ignored_files: - print(' %s' % filename) - if changed_lines: - print('Running clang-format on the following files:') - for filename in changed_lines: - print(' %s' % filename) - - if not changed_lines: - if opts.verbose >= 0: - print('no modified files to format') - return 0 - - if len(commits) > 1: - old_tree = commits[1] - revision = old_tree - elif opts.staged: - old_tree = create_tree_from_index(changed_lines) - revision = '' - else: - old_tree = create_tree_from_workdir(changed_lines) - revision = None - new_tree = run_clang_format_and_save_to_tree(changed_lines, - revision, - binary=opts.binary, - style=opts.style) - if opts.verbose >= 1: - print('old tree: %s' % old_tree) - print('new tree: %s' % new_tree) - - if old_tree == new_tree: - if opts.verbose >= 0: - print('clang-format did not modify any files') - return 0 - - if opts.diff: - return print_diff(old_tree, new_tree) - if opts.diffstat: - return print_diffstat(old_tree, new_tree) - - changed_files = apply_changes(old_tree, new_tree, force=opts.force, - patch_mode=opts.patch) - if (opts.verbose >= 0 and not opts.patch) or opts.verbose >= 1: - print('changed files:') - for filename in changed_files: - print(' %s' % filename) - - return 1 + config = load_git_config() + + # In order to keep '--' yet allow options after positionals, we need to + # check for '--' ourselves. (Setting nargs='*' throws away the '--', while + # nargs=argparse.REMAINDER disallows options after positionals.) + argv = sys.argv[1:] + try: + idx = argv.index("--") + except ValueError: + dash_dash = [] + else: + dash_dash = argv[idx:] + argv = argv[:idx] + + default_extensions = ",".join( + [ + # From clang/lib/Frontend/FrontendOptions.cpp, all lower case + "c", + "h", # C + "m", # ObjC + "mm", # ObjC++ + "cc", + "cp", + "cpp", + "c++", + "cxx", + "hh", + "hpp", + "hxx", + "inc", # C++ + "ccm", + "cppm", + "cxxm", + "c++m", # C++ Modules + "cu", + "cuh", # CUDA + # Other languages that clang-format supports + "proto", + "protodevel", # Protocol Buffers + "java", # Java + "js", + "mjs", + "cjs", # JavaScript + "ts", # TypeScript + "cs", # C Sharp + "json", # Json + "sv", + "svh", + "v", + "vh", # Verilog + "td", # TableGen + "txtpb", + "textpb", + "pb.txt", + "textproto", + "asciipb", # TextProto + ] + ) + + p = argparse.ArgumentParser( + usage=usage, + formatter_class=argparse.RawDescriptionHelpFormatter, + description=desc, + ) + p.add_argument( + "--binary", + default=config.get("clangformat.binary", "clang-format"), + help="path to clang-format", + ), + p.add_argument( + "--commit", + default=config.get("clangformat.commit", "HEAD"), + help="default commit to use if none is specified", + ), + p.add_argument( + "--diff", + action="store_true", + help="print a diff instead of applying the changes", + ) + p.add_argument( + "--diffstat", + action="store_true", + help="print a diffstat instead of applying the changes", + ) + p.add_argument( + "--extensions", + default=config.get("clangformat.extensions", default_extensions), + help=( + "comma-separated list of file extensions to format, " + "excluding the period and case-insensitive" + ), + ), + p.add_argument( + "-f", + "--force", + action="store_true", + help="allow changes to unstaged files", + ) + p.add_argument( + "-p", "--patch", action="store_true", help="select hunks interactively" + ) + p.add_argument( + "-q", + "--quiet", + action="count", + default=0, + help="print less information", + ) + p.add_argument( + "--staged", + "--cached", + action="store_true", + help="format lines in the stage instead of the working dir", + ) + p.add_argument( + "--style", + default=config.get("clangformat.style", None), + help="passed to clang-format", + ), + p.add_argument( + "-v", + "--verbose", + action="count", + default=0, + help="print extra information", + ) + p.add_argument( + "--diff_from_common_commit", + action="store_true", + help=( + "diff from the last common commit for commits in " + "separate branches rather than the exact point of the " + "commits" + ), + ) + # We gather all the remaining positional arguments into 'args' since we need + # to use some heuristics to determine whether or not was present. + # However, to print pretty messages, we make use of metavar and help. + p.add_argument( + "args", + nargs="*", + metavar="", + help="revision from which to compute the diff", + ) + p.add_argument( + "ignored", + nargs="*", + metavar="...", + help="if specified, only consider differences in these files", + ) + opts = p.parse_args(argv) + + opts.verbose -= opts.quiet + del opts.quiet + + commits, files = interpret_args(opts.args, dash_dash, opts.commit) + if len(commits) > 2: + die("at most two commits allowed; %d given" % len(commits)) + if len(commits) == 2: + if opts.staged: + die("--staged is not allowed when two commits are given") + if not opts.diff: + die("--diff is required when two commits are given") + elif opts.diff_from_common_commit: + die( + "--diff_from_common_commit is only allowed when two commits are " + "given" + ) + + if os.path.dirname(opts.binary): + opts.binary = os.path.abspath(opts.binary) + + changed_lines = compute_diff_and_extract_lines( + commits, files, opts.staged, opts.diff_from_common_commit + ) + if opts.verbose >= 1: + ignored_files = set(changed_lines) + filter_by_extension(changed_lines, opts.extensions.lower().split(",")) + # The computed diff outputs absolute paths, so we must cd before accessing + # those files. + cd_to_toplevel() + filter_symlinks(changed_lines) + filter_ignored_files(changed_lines, binary=opts.binary) + if opts.verbose >= 1: + ignored_files.difference_update(changed_lines) + if ignored_files: + print( + "Ignoring the following files (wrong extension, symlink, or " + "ignored by clang-format):" + ) + for filename in ignored_files: + print(" %s" % filename) + if changed_lines: + print("Running clang-format on the following files:") + for filename in changed_lines: + print(" %s" % filename) + + if not changed_lines: + if opts.verbose >= 0: + print("no modified files to format") + return 0 + + if len(commits) > 1: + old_tree = commits[1] + revision = old_tree + elif opts.staged: + old_tree = create_tree_from_index(changed_lines) + revision = "" + else: + old_tree = create_tree_from_workdir(changed_lines) + revision = None + new_tree = run_clang_format_and_save_to_tree( + changed_lines, revision, binary=opts.binary, style=opts.style + ) + if opts.verbose >= 1: + print("old tree: %s" % old_tree) + print("new tree: %s" % new_tree) + + if old_tree == new_tree: + if opts.verbose >= 0: + print("clang-format did not modify any files") + return 0 + + if opts.diff: + return print_diff(old_tree, new_tree) + if opts.diffstat: + return print_diffstat(old_tree, new_tree) + + changed_files = apply_changes( + old_tree, new_tree, force=opts.force, patch_mode=opts.patch + ) + if (opts.verbose >= 0 and not opts.patch) or opts.verbose >= 1: + print("changed files:") + for filename in changed_files: + print(" %s" % filename) + + return 1 def load_git_config(non_string_options=None): - """Return the git configuration as a dictionary. - - All options are assumed to be strings unless in `non_string_options`, in which - is a dictionary mapping option name (in lower case) to either "--bool" or - "--int".""" - if non_string_options is None: - non_string_options = {} - out = {} - for entry in run('git', 'config', '--list', '--null').split('\0'): - if entry: - if '\n' in entry: - name, value = entry.split('\n', 1) - else: - # A setting with no '=' ('\n' with --null) is implicitly 'true' - name = entry - value = 'true' - if name in non_string_options: - value = run('git', 'config', non_string_options[name], name) - out[name] = value - return out + """Return the git configuration as a dictionary. + + All options are assumed to be strings unless in `non_string_options`, in + which is a dictionary mapping option name (in lower case) to either "--bool" + or "--int".""" + if non_string_options is None: + non_string_options = {} + out = {} + for entry in run("git", "config", "--list", "--null").split("\0"): + if entry: + if "\n" in entry: + name, value = entry.split("\n", 1) + else: + # A setting with no '=' ('\n' with --null) is implicitly 'true' + name = entry + value = "true" + if name in non_string_options: + value = run("git", "config", non_string_options[name], name) + out[name] = value + return out def interpret_args(args, dash_dash, default_commit): - """Interpret `args` as "[commits] [--] [files]" and return (commits, files). - - It is assumed that "--" and everything that follows has been removed from - args and placed in `dash_dash`. - - If "--" is present (i.e., `dash_dash` is non-empty), the arguments to its - left (if present) are taken as commits. Otherwise, the arguments are checked - from left to right if they are commits or files. If commits are not given, - a list with `default_commit` is used.""" - if dash_dash: - if len(args) == 0: - commits = [default_commit] - else: - commits = args - for commit in commits: - object_type = get_object_type(commit) - if object_type not in ('commit', 'tag'): - if object_type is None: - die("'%s' is not a commit" % commit) + """Interpret `args` as "[commits] [--] [files]" and return (commits, files). + + It is assumed that "--" and everything that follows has been removed from + args and placed in `dash_dash`. + + If "--" is present (i.e., `dash_dash` is non-empty), the arguments to its + left (if present) are taken as commits. Otherwise, the arguments are + checked from left to right if they are commits or files. If commits are not + given, a list with `default_commit` is used.""" + if dash_dash: + if len(args) == 0: + commits = [default_commit] else: - die("'%s' is a %s, but a commit was expected" % (commit, object_type)) - files = dash_dash[1:] - elif args: - commits = [] - while args: - if not disambiguate_revision(args[0]): - break - commits.append(args.pop(0)) - if not commits: - commits = [default_commit] - files = args - else: - commits = [default_commit] - files = [] - return commits, files + commits = args + for commit in commits: + object_type = get_object_type(commit) + if object_type not in ("commit", "tag"): + if object_type is None: + die("'%s' is not a commit" % commit) + else: + die( + "'%s' is a %s, but a commit was expected" + % (commit, object_type) + ) + files = dash_dash[1:] + elif args: + commits = [] + while args: + if not disambiguate_revision(args[0]): + break + commits.append(args.pop(0)) + if not commits: + commits = [default_commit] + files = args + else: + commits = [default_commit] + files = [] + return commits, files def disambiguate_revision(value): - """Returns True if `value` is a revision, False if it is a file, or dies.""" - # If `value` is ambiguous (neither a commit nor a file), the following - # command will die with an appropriate error message. - run('git', 'rev-parse', value, verbose=False) - object_type = get_object_type(value) - if object_type is None: - return False - if object_type in ('commit', 'tag'): - return True - die('`%s` is a %s, but a commit or filename was expected' % - (value, object_type)) + """Returns True if `value` is a revision, False if it is a file, or dies.""" + # If `value` is ambiguous (neither a commit nor a file), the following + # command will die with an appropriate error message. + run("git", "rev-parse", value, verbose=False) + object_type = get_object_type(value) + if object_type is None: + return False + if object_type in ("commit", "tag"): + return True + die( + "`%s` is a %s, but a commit or filename was expected" + % (value, object_type) + ) def get_object_type(value): - """Returns a string description of an object's type, or None if it is not - a valid git object.""" - cmd = ['git', 'cat-file', '-t', value] - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = p.communicate() - if p.returncode != 0: - return None - return convert_string(stdout.strip()) + """Returns a string description of an object's type, or None if it is not + a valid git object.""" + cmd = ["git", "cat-file", "-t", value] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + if p.returncode != 0: + return None + return convert_string(stdout.strip()) def compute_diff_and_extract_lines(commits, files, staged, diff_common_commit): - """Calls compute_diff() followed by extract_lines().""" - diff_process = compute_diff(commits, files, staged, diff_common_commit) - changed_lines = extract_lines(diff_process.stdout) - diff_process.stdout.close() - diff_process.wait() - if diff_process.returncode != 0: - # Assume error was already printed to stderr. - sys.exit(2) - return changed_lines + """Calls compute_diff() followed by extract_lines().""" + diff_process = compute_diff(commits, files, staged, diff_common_commit) + changed_lines = extract_lines(diff_process.stdout) + diff_process.stdout.close() + diff_process.wait() + if diff_process.returncode != 0: + # Assume error was already printed to stderr. + sys.exit(2) + return changed_lines def compute_diff(commits, files, staged, diff_common_commit): - """Return a subprocess object producing the diff from `commits`. - - The return value's `stdin` file object will produce a patch with the - differences between the working directory (or stage if --staged is used) and - the first commit if a single one was specified, or the difference between - both specified commits, filtered on `files` (if non-empty). - Zero context lines are used in the patch.""" - git_tool = 'diff-index' - extra_args = [] - if len(commits) == 2: - git_tool = 'diff-tree' - if diff_common_commit: - commits = [f'{commits[0]}...{commits[1]}'] - elif staged: - extra_args += ['--cached'] - - cmd = ['git', git_tool, '-p', '-U0'] + extra_args + commits + ['--'] - cmd.extend(files) - p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) - p.stdin.close() - return p + """Return a subprocess object producing the diff from `commits`. + + The return value's `stdin` file object will produce a patch with the + differences between the working directory (or stage if --staged is used) and + the first commit if a single one was specified, or the difference between + both specified commits, filtered on `files` (if non-empty). + Zero context lines are used in the patch.""" + git_tool = "diff-index" + extra_args = [] + if len(commits) == 2: + git_tool = "diff-tree" + if diff_common_commit: + commits = [f"{commits[0]}...{commits[1]}"] + elif staged: + extra_args += ["--cached"] + + cmd = ["git", git_tool, "-p", "-U0"] + extra_args + commits + ["--"] + cmd.extend(files) + p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) + p.stdin.close() + return p def extract_lines(patch_file): - """Extract the changed lines in `patch_file`. - - The return value is a dictionary mapping filename to a list of (start_line, - line_count) pairs. - - The input must have been produced with ``-U0``, meaning unidiff format with - zero lines of context. The return value is a dict mapping filename to a - list of line `Range`s.""" - matches = {} - for line in patch_file: - line = convert_string(line) - match = re.search(r'^\+\+\+\ [^/]+/(.*)', line) - if match: - filename = match.group(1).rstrip('\r\n\t') - match = re.search(r'^@@ -[0-9,]+ \+(\d+)(,(\d+))?', line) - if match: - start_line = int(match.group(1)) - line_count = 1 - if match.group(3): - line_count = int(match.group(3)) - if line_count == 0: - line_count = 1 - if start_line == 0: - continue - matches.setdefault(filename, []).append(Range(start_line, line_count)) - return matches + """Extract the changed lines in `patch_file`. + + The return value is a dictionary mapping filename to a list of (start_line, + line_count) pairs. + + The input must have been produced with ``-U0``, meaning unidiff format with + zero lines of context. The return value is a dict mapping filename to a + list of line `Range`s.""" + matches = {} + for line in patch_file: + line = convert_string(line) + match = re.search(r"^\+\+\+\ [^/]+/(.*)", line) + if match: + filename = match.group(1).rstrip("\r\n\t") + match = re.search(r"^@@ -[0-9,]+ \+(\d+)(,(\d+))?", line) + if match: + start_line = int(match.group(1)) + line_count = 1 + if match.group(3): + line_count = int(match.group(3)) + if line_count == 0: + line_count = 1 + if start_line == 0: + continue + matches.setdefault(filename, []).append( + Range(start_line, line_count) + ) + return matches def filter_by_extension(dictionary, allowed_extensions): - """Delete every key in `dictionary` that doesn't have an allowed extension. + """Delete every key in `dictionary` that doesn't have an allowed extension. - `allowed_extensions` must be a collection of lowercase file extensions, - excluding the period.""" - allowed_extensions = frozenset(allowed_extensions) - for filename in list(dictionary.keys()): - base_ext = filename.rsplit('.', 1) - if len(base_ext) == 1 and '' in allowed_extensions: - continue - if len(base_ext) == 1 or base_ext[1].lower() not in allowed_extensions: - del dictionary[filename] + `allowed_extensions` must be a collection of lowercase file extensions, + excluding the period.""" + allowed_extensions = frozenset(allowed_extensions) + for filename in list(dictionary.keys()): + base_ext = filename.rsplit(".", 1) + if len(base_ext) == 1 and "" in allowed_extensions: + continue + if len(base_ext) == 1 or base_ext[1].lower() not in allowed_extensions: + del dictionary[filename] def filter_symlinks(dictionary): - """Delete every key in `dictionary` that is a symlink.""" - for filename in list(dictionary.keys()): - if os.path.islink(filename): - del dictionary[filename] + """Delete every key in `dictionary` that is a symlink.""" + for filename in list(dictionary.keys()): + if os.path.islink(filename): + del dictionary[filename] def filter_ignored_files(dictionary, binary): - """Delete every key in `dictionary` that is ignored by clang-format.""" - ignored_files = run(binary, '-list-ignored', *dictionary.keys()) - if not ignored_files: - return - ignored_files = ignored_files.split('\n') - for filename in ignored_files: - del dictionary[filename] + """Delete every key in `dictionary` that is ignored by clang-format.""" + ignored_files = run(binary, "-list-ignored", *dictionary.keys()) + if not ignored_files: + return + ignored_files = ignored_files.split("\n") + for filename in ignored_files: + del dictionary[filename] def cd_to_toplevel(): - """Change to the top level of the git repository.""" - toplevel = run('git', 'rev-parse', '--show-toplevel') - os.chdir(toplevel) + """Change to the top level of the git repository.""" + toplevel = run("git", "rev-parse", "--show-toplevel") + os.chdir(toplevel) def create_tree_from_workdir(filenames): - """Create a new git tree with the given files from the working directory. + """Create a new git tree with the given files from the working directory. - Returns the object ID (SHA-1) of the created tree.""" - return create_tree(filenames, '--stdin') + Returns the object ID (SHA-1) of the created tree.""" + return create_tree(filenames, "--stdin") def create_tree_from_index(filenames): - # Copy the environment, because the files have to be read from the original - # index. - env = os.environ.copy() - def index_contents_generator(): - for filename in filenames: - git_ls_files_cmd = ['git', 'ls-files', '--stage', '-z', '--', filename] - git_ls_files = subprocess.Popen(git_ls_files_cmd, env=env, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE) - stdout = git_ls_files.communicate()[0] - yield convert_string(stdout.split(b'\0')[0]) - return create_tree(index_contents_generator(), '--index-info') - - -def run_clang_format_and_save_to_tree(changed_lines, revision=None, - binary='clang-format', style=None): - """Run clang-format on each file and save the result to a git tree. - - Returns the object ID (SHA-1) of the created tree.""" - # Copy the environment when formatting the files in the index, because the - # files have to be read from the original index. - env = os.environ.copy() if revision == '' else None - def iteritems(container): - try: - return container.iteritems() # Python 2 - except AttributeError: - return container.items() # Python 3 - def index_info_generator(): - for filename, line_ranges in iteritems(changed_lines): - if revision is not None: - if len(revision) > 0: - git_metadata_cmd = ['git', 'ls-tree', - '%s:%s' % (revision, os.path.dirname(filename)), - os.path.basename(filename)] - else: - git_metadata_cmd = ['git', 'ls-files', '--stage', '--', filename] - git_metadata = subprocess.Popen(git_metadata_cmd, env=env, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE) - stdout = git_metadata.communicate()[0] - mode = oct(int(stdout.split()[0], 8)) - else: - mode = oct(os.stat(filename).st_mode) - # Adjust python3 octal format so that it matches what git expects - if mode.startswith('0o'): - mode = '0' + mode[2:] - blob_id = clang_format_to_blob(filename, line_ranges, - revision=revision, - binary=binary, - style=style, - env=env) - yield '%s %s\t%s' % (mode, blob_id, filename) - return create_tree(index_info_generator(), '--index-info') + # Copy the environment, because the files have to be read from the original + # index. + env = os.environ.copy() + + def index_contents_generator(): + for filename in filenames: + git_ls_files_cmd = [ + "git", + "ls-files", + "--stage", + "-z", + "--", + filename, + ] + git_ls_files = subprocess.Popen( + git_ls_files_cmd, + env=env, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + stdout = git_ls_files.communicate()[0] + yield convert_string(stdout.split(b"\0")[0]) + + return create_tree(index_contents_generator(), "--index-info") + + +def run_clang_format_and_save_to_tree( + changed_lines, revision=None, binary="clang-format", style=None +): + """Run clang-format on each file and save the result to a git tree. + + Returns the object ID (SHA-1) of the created tree.""" + # Copy the environment when formatting the files in the index, because the + # files have to be read from the original index. + env = os.environ.copy() if revision == "" else None + + def iteritems(container): + try: + return container.iteritems() # Python 2 + except AttributeError: + return container.items() # Python 3 + + def index_info_generator(): + for filename, line_ranges in iteritems(changed_lines): + if revision is not None: + if len(revision) > 0: + git_metadata_cmd = [ + "git", + "ls-tree", + "%s:%s" % (revision, os.path.dirname(filename)), + os.path.basename(filename), + ] + else: + git_metadata_cmd = [ + "git", + "ls-files", + "--stage", + "--", + filename, + ] + git_metadata = subprocess.Popen( + git_metadata_cmd, + env=env, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + stdout = git_metadata.communicate()[0] + mode = oct(int(stdout.split()[0], 8)) + else: + mode = oct(os.stat(filename).st_mode) + # Adjust python3 octal format so that it matches what git expects + if mode.startswith("0o"): + mode = "0" + mode[2:] + blob_id = clang_format_to_blob( + filename, + line_ranges, + revision=revision, + binary=binary, + style=style, + env=env, + ) + yield "%s %s\t%s" % (mode, blob_id, filename) + + return create_tree(index_info_generator(), "--index-info") def create_tree(input_lines, mode): - """Create a tree object from the given input. - - If mode is '--stdin', it must be a list of filenames. If mode is - '--index-info' is must be a list of values suitable for "git update-index - --index-info", such as " ". Any other mode - is invalid.""" - assert mode in ('--stdin', '--index-info') - cmd = ['git', 'update-index', '--add', '-z', mode] - with temporary_index_file(): - p = subprocess.Popen(cmd, stdin=subprocess.PIPE) - for line in input_lines: - p.stdin.write(to_bytes('%s\0' % line)) - p.stdin.close() - if p.wait() != 0: - die('`%s` failed' % ' '.join(cmd)) - tree_id = run('git', 'write-tree') - return tree_id - - -def clang_format_to_blob(filename, line_ranges, revision=None, - binary='clang-format', style=None, env=None): - """Run clang-format on the given file and save the result to a git blob. - - Runs on the file in `revision` if not None, or on the file in the working - directory if `revision` is None. Revision can be set to an empty string to run - clang-format on the file in the index. - - Returns the object ID (SHA-1) of the created blob.""" - clang_format_cmd = [binary] - if style: - clang_format_cmd.extend(['--style='+style]) - clang_format_cmd.extend([ - '--lines=%s:%s' % (start_line, start_line+line_count-1) - for start_line, line_count in line_ranges]) - if revision is not None: - clang_format_cmd.extend(['--assume-filename='+filename]) - git_show_cmd = ['git', 'cat-file', 'blob', '%s:%s' % (revision, filename)] - git_show = subprocess.Popen(git_show_cmd, env=env, stdin=subprocess.PIPE, - stdout=subprocess.PIPE) - git_show.stdin.close() - clang_format_stdin = git_show.stdout - else: - clang_format_cmd.extend([filename]) - git_show = None - clang_format_stdin = subprocess.PIPE - try: - clang_format = subprocess.Popen(clang_format_cmd, stdin=clang_format_stdin, - stdout=subprocess.PIPE) - if clang_format_stdin == subprocess.PIPE: - clang_format_stdin = clang_format.stdin - except OSError as e: - if e.errno == errno.ENOENT: - die('cannot find executable "%s"' % binary) + """Create a tree object from the given input. + + If mode is '--stdin', it must be a list of filenames. If mode is + '--index-info' is must be a list of values suitable for "git update-index + --index-info", such as " ". Any other + mode is invalid.""" + assert mode in ("--stdin", "--index-info") + cmd = ["git", "update-index", "--add", "-z", mode] + with temporary_index_file(): + p = subprocess.Popen(cmd, stdin=subprocess.PIPE) + for line in input_lines: + p.stdin.write(to_bytes("%s\0" % line)) + p.stdin.close() + if p.wait() != 0: + die("`%s` failed" % " ".join(cmd)) + tree_id = run("git", "write-tree") + return tree_id + + +def clang_format_to_blob( + filename, + line_ranges, + revision=None, + binary="clang-format", + style=None, + env=None, +): + """Run clang-format on the given file and save the result to a git blob. + + Runs on the file in `revision` if not None, or on the file in the working + directory if `revision` is None. Revision can be set to an empty string to + run clang-format on the file in the index. + + Returns the object ID (SHA-1) of the created blob.""" + clang_format_cmd = [binary] + if style: + clang_format_cmd.extend(["--style=" + style]) + clang_format_cmd.extend( + [ + "--lines=%s:%s" % (start_line, start_line + line_count - 1) + for start_line, line_count in line_ranges + ] + ) + if revision is not None: + clang_format_cmd.extend(["--assume-filename=" + filename]) + git_show_cmd = [ + "git", + "cat-file", + "blob", + "%s:%s" % (revision, filename), + ] + git_show = subprocess.Popen( + git_show_cmd, env=env, stdin=subprocess.PIPE, stdout=subprocess.PIPE + ) + git_show.stdin.close() + clang_format_stdin = git_show.stdout else: - raise - clang_format_stdin.close() - hash_object_cmd = ['git', 'hash-object', '-w', '--path='+filename, '--stdin'] - hash_object = subprocess.Popen(hash_object_cmd, stdin=clang_format.stdout, - stdout=subprocess.PIPE) - clang_format.stdout.close() - stdout = hash_object.communicate()[0] - if hash_object.returncode != 0: - die('`%s` failed' % ' '.join(hash_object_cmd)) - if clang_format.wait() != 0: - die('`%s` failed' % ' '.join(clang_format_cmd)) - if git_show and git_show.wait() != 0: - die('`%s` failed' % ' '.join(git_show_cmd)) - return convert_string(stdout).rstrip('\r\n') + clang_format_cmd.extend([filename]) + git_show = None + clang_format_stdin = subprocess.PIPE + try: + clang_format = subprocess.Popen( + clang_format_cmd, stdin=clang_format_stdin, stdout=subprocess.PIPE + ) + if clang_format_stdin == subprocess.PIPE: + clang_format_stdin = clang_format.stdin + except OSError as e: + if e.errno == errno.ENOENT: + die('cannot find executable "%s"' % binary) + else: + raise + clang_format_stdin.close() + hash_object_cmd = [ + "git", + "hash-object", + "-w", + "--path=" + filename, + "--stdin", + ] + hash_object = subprocess.Popen( + hash_object_cmd, stdin=clang_format.stdout, stdout=subprocess.PIPE + ) + clang_format.stdout.close() + stdout = hash_object.communicate()[0] + if hash_object.returncode != 0: + die("`%s` failed" % " ".join(hash_object_cmd)) + if clang_format.wait() != 0: + die("`%s` failed" % " ".join(clang_format_cmd)) + if git_show and git_show.wait() != 0: + die("`%s` failed" % " ".join(git_show_cmd)) + return convert_string(stdout).rstrip("\r\n") @contextlib.contextmanager def temporary_index_file(tree=None): - """Context manager for setting GIT_INDEX_FILE to a temporary file and deleting - the file afterward.""" - index_path = create_temporary_index(tree) - old_index_path = os.environ.get('GIT_INDEX_FILE') - os.environ['GIT_INDEX_FILE'] = index_path - try: - yield - finally: - if old_index_path is None: - del os.environ['GIT_INDEX_FILE'] - else: - os.environ['GIT_INDEX_FILE'] = old_index_path - os.remove(index_path) + """Context manager for setting GIT_INDEX_FILE to a temporary file and + deleting the file afterward.""" + index_path = create_temporary_index(tree) + old_index_path = os.environ.get("GIT_INDEX_FILE") + os.environ["GIT_INDEX_FILE"] = index_path + try: + yield + finally: + if old_index_path is None: + del os.environ["GIT_INDEX_FILE"] + else: + os.environ["GIT_INDEX_FILE"] = old_index_path + os.remove(index_path) def create_temporary_index(tree=None): - """Create a temporary index file and return the created file's path. + """Create a temporary index file and return the created file's path. - If `tree` is not None, use that as the tree to read in. Otherwise, an - empty index is created.""" - gitdir = run('git', 'rev-parse', '--git-dir') - path = os.path.join(gitdir, temp_index_basename) - if tree is None: - tree = '--empty' - run('git', 'read-tree', '--index-output='+path, tree) - return path + If `tree` is not None, use that as the tree to read in. Otherwise, an + empty index is created.""" + gitdir = run("git", "rev-parse", "--git-dir") + path = os.path.join(gitdir, temp_index_basename) + if tree is None: + tree = "--empty" + run("git", "read-tree", "--index-output=" + path, tree) + return path def print_diff(old_tree, new_tree): - """Print the diff between the two trees to stdout.""" - # We use the porcelain 'diff' and not plumbing 'diff-tree' because the output - # is expected to be viewed by the user, and only the former does nice things - # like color and pagination. - # - # We also only print modified files since `new_tree` only contains the files - # that were modified, so unmodified files would show as deleted without the - # filter. - return subprocess.run(['git', 'diff', '--diff-filter=M', - '--exit-code', old_tree, new_tree]).returncode + """Print the diff between the two trees to stdout.""" + # We use the porcelain 'diff' and not plumbing 'diff-tree' because the + # output is expected to be viewed by the user, and only the former does nice + # things like color and pagination. + # + # We also only print modified files since `new_tree` only contains the files + # that were modified, so unmodified files would show as deleted without the + # filter. + return subprocess.run( + ["git", "diff", "--diff-filter=M", "--exit-code", old_tree, new_tree] + ).returncode + def print_diffstat(old_tree, new_tree): - """Print the diffstat between the two trees to stdout.""" - # We use the porcelain 'diff' and not plumbing 'diff-tree' because the output - # is expected to be viewed by the user, and only the former does nice things - # like color and pagination. - # - # We also only print modified files since `new_tree` only contains the files - # that were modified, so unmodified files would show as deleted without the - # filter. - return subprocess.run(['git', 'diff', '--diff-filter=M', '--exit-code', - '--stat', old_tree, new_tree]).returncode + """Print the diffstat between the two trees to stdout.""" + # We use the porcelain 'diff' and not plumbing 'diff-tree' because the + # output is expected to be viewed by the user, and only the former does nice + # things like color and pagination. + # + # We also only print modified files since `new_tree` only contains the files + # that were modified, so unmodified files would show as deleted without the + # filter. + return subprocess.run( + [ + "git", + "diff", + "--diff-filter=M", + "--exit-code", + "--stat", + old_tree, + new_tree, + ] + ).returncode + def apply_changes(old_tree, new_tree, force=False, patch_mode=False): - """Apply the changes in `new_tree` to the working directory. - - Bails if there are local changes in those files and not `force`. If - `patch_mode`, runs `git checkout --patch` to select hunks interactively.""" - changed_files = run('git', 'diff-tree', '--diff-filter=M', '-r', '-z', - '--name-only', old_tree, - new_tree).rstrip('\0').split('\0') - if not force: - unstaged_files = run('git', 'diff-files', '--name-status', *changed_files) - if unstaged_files: - print('The following files would be modified but ' - 'have unstaged changes:', file=sys.stderr) - print(unstaged_files, file=sys.stderr) - print('Please commit, stage, or stash them first.', file=sys.stderr) - sys.exit(2) - if patch_mode: - # In patch mode, we could just as well create an index from the new tree - # and checkout from that, but then the user will be presented with a - # message saying "Discard ... from worktree". Instead, we use the old - # tree as the index and checkout from new_tree, which gives the slightly - # better message, "Apply ... to index and worktree". This is not quite - # right, since it won't be applied to the user's index, but oh well. - with temporary_index_file(old_tree): - subprocess.run(['git', 'checkout', '--patch', new_tree], check=True) - index_tree = old_tree - else: - with temporary_index_file(new_tree): - run('git', 'checkout-index', '-f', '--', *changed_files) - return changed_files + """Apply the changes in `new_tree` to the working directory. + + Bails if there are local changes in those files and not `force`. If + `patch_mode`, runs `git checkout --patch` to select hunks interactively.""" + changed_files = ( + run( + "git", + "diff-tree", + "--diff-filter=M", + "-r", + "-z", + "--name-only", + old_tree, + new_tree, + ) + .rstrip("\0") + .split("\0") + ) + if not force: + unstaged_files = run( + "git", "diff-files", "--name-status", *changed_files + ) + if unstaged_files: + print( + "The following files would be modified but have unstaged " + "changes:", + file=sys.stderr, + ) + print(unstaged_files, file=sys.stderr) + print("Please commit, stage, or stash them first.", file=sys.stderr) + sys.exit(2) + if patch_mode: + # In patch mode, we could just as well create an index from the new tree + # and checkout from that, but then the user will be presented with a + # message saying "Discard ... from worktree". Instead, we use the old + # tree as the index and checkout from new_tree, which gives the slightly + # better message, "Apply ... to index and worktree". This is not quite + # right, since it won't be applied to the user's index, but oh well. + with temporary_index_file(old_tree): + subprocess.run(["git", "checkout", "--patch", new_tree], check=True) + index_tree = old_tree + else: + with temporary_index_file(new_tree): + run("git", "checkout-index", "-f", "--", *changed_files) + return changed_files def run(*args, **kwargs): - stdin = kwargs.pop('stdin', '') - verbose = kwargs.pop('verbose', True) - strip = kwargs.pop('strip', True) - for name in kwargs: - raise TypeError("run() got an unexpected keyword argument '%s'" % name) - p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - stdin=subprocess.PIPE) - stdout, stderr = p.communicate(input=stdin) - - stdout = convert_string(stdout) - stderr = convert_string(stderr) - - if p.returncode == 0: + stdin = kwargs.pop("stdin", "") + verbose = kwargs.pop("verbose", True) + strip = kwargs.pop("strip", True) + for name in kwargs: + raise TypeError("run() got an unexpected keyword argument '%s'" % name) + p = subprocess.Popen( + args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + stdin=subprocess.PIPE, + ) + stdout, stderr = p.communicate(input=stdin) + + stdout = convert_string(stdout) + stderr = convert_string(stderr) + + if p.returncode == 0: + if stderr: + if verbose: + print( + "`%s` printed to stderr:" % " ".join(args), file=sys.stderr + ) + print(stderr.rstrip(), file=sys.stderr) + if strip: + stdout = stdout.rstrip("\r\n") + return stdout + if verbose: + print( + "`%s` returned %s" % (" ".join(args), p.returncode), file=sys.stderr + ) if stderr: - if verbose: - print('`%s` printed to stderr:' % ' '.join(args), file=sys.stderr) - print(stderr.rstrip(), file=sys.stderr) - if strip: - stdout = stdout.rstrip('\r\n') - return stdout - if verbose: - print('`%s` returned %s' % (' '.join(args), p.returncode), file=sys.stderr) - if stderr: - print(stderr.rstrip(), file=sys.stderr) - sys.exit(2) + print(stderr.rstrip(), file=sys.stderr) + sys.exit(2) def die(message): - print('error:', message, file=sys.stderr) - sys.exit(2) + print("error:", message, file=sys.stderr) + sys.exit(2) def to_bytes(str_input): # Encode to UTF-8 to get binary data. if isinstance(str_input, bytes): return str_input - return str_input.encode('utf-8') + return str_input.encode("utf-8") def to_string(bytes_input): if isinstance(bytes_input, str): return bytes_input - return bytes_input.encode('utf-8') + return bytes_input.encode("utf-8") def convert_string(bytes_input): try: - return to_string(bytes_input.decode('utf-8')) - except AttributeError: # 'str' object has no attribute 'decode'. + return to_string(bytes_input.decode("utf-8")) + except AttributeError: # 'str' object has no attribute 'decode'. return str(bytes_input) except UnicodeError: return str(bytes_input) -if __name__ == '__main__': - sys.exit(main()) + +if __name__ == "__main__": + sys.exit(main()) diff --git a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp index 0189fe5d56ab2..14c584064e311 100644 --- a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp +++ b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp @@ -196,13 +196,14 @@ int main(int argc, const char **argv) { auto reportError = [argv](Error E) { logAllUnhandledErrors(std::move(E), WithColor::error(errs(), argv[0])); - exit(1); + return 1; }; auto doWork = [&](std::function Work) { if (llvm::Error Err = Work()) { - reportError(std::move(Err)); + return reportError(std::move(Err)); } + return 0; }; auto warningOS = [argv]() -> raw_ostream & { @@ -223,14 +224,14 @@ int main(int argc, const char **argv) { if (!Objcopy) Objcopy = sys::findProgramByName("llvm-objcopy"); if (!Objcopy) - reportError(createStringError(Objcopy.getError(), - "unable to find 'llvm-objcopy' in path")); + return reportError(createStringError( + Objcopy.getError(), "unable to find 'llvm-objcopy' in path")); else BundlerConfig.ObjcopyPath = *Objcopy; if (InputFileNames.getNumOccurrences() != 0 && InputFileNamesDeprecatedOpt.getNumOccurrences() != 0) { - reportError(createStringError( + return reportError(createStringError( errc::invalid_argument, "-inputs and -input cannot be used together, use only -input instead")); } @@ -246,9 +247,9 @@ int main(int argc, const char **argv) { if (OutputFileNames.getNumOccurrences() != 0 && OutputFileNamesDeprecatedOpt.getNumOccurrences() != 0) { - reportError(createStringError(errc::invalid_argument, - "-outputs and -output cannot be used " - "together, use only -output instead")); + return reportError(createStringError(errc::invalid_argument, + "-outputs and -output cannot be used " + "together, use only -output instead")); } if (OutputFileNamesDeprecatedOpt.size()) { @@ -262,77 +263,77 @@ int main(int argc, const char **argv) { if (ListBundleIDs) { if (Unbundle) { - reportError( + return reportError( createStringError(errc::invalid_argument, "-unbundle and -list cannot be used together")); } if (InputFileNames.size() != 1) { - reportError(createStringError(errc::invalid_argument, - "only one input file supported for -list")); + return reportError(createStringError( + errc::invalid_argument, "only one input file supported for -list")); } if (OutputFileNames.size()) { - reportError(createStringError(errc::invalid_argument, - "-outputs option is invalid for -list")); + return reportError(createStringError( + errc::invalid_argument, "-outputs option is invalid for -list")); } if (TargetNames.size()) { - reportError(createStringError(errc::invalid_argument, - "-targets option is invalid for -list")); + return reportError(createStringError( + errc::invalid_argument, "-targets option is invalid for -list")); } - doWork([&]() { return OffloadBundler::ListBundleIDsInFile( - InputFileNames.front(), - BundlerConfig); }); - return 0; + return doWork([&]() { + return OffloadBundler::ListBundleIDsInFile(InputFileNames.front(), + BundlerConfig); + }); } if (BundlerConfig.CheckInputArchive) { if (!Unbundle) { - reportError(createStringError(errc::invalid_argument, - "-check-input-archive cannot be used while " - "bundling")); + return reportError(createStringError( + errc::invalid_argument, "-check-input-archive cannot be used while " + "bundling")); } if (Unbundle && BundlerConfig.FilesType != "a") { - reportError(createStringError(errc::invalid_argument, - "-check-input-archive can only be used for " - "unbundling archives (-type=a)")); + return reportError(createStringError( + errc::invalid_argument, "-check-input-archive can only be used for " + "unbundling archives (-type=a)")); } } if (OutputFileNames.size() == 0) { - reportError( + return reportError( createStringError(errc::invalid_argument, "no output file specified!")); } if (TargetNames.getNumOccurrences() == 0) { - reportError(createStringError( + return reportError(createStringError( errc::invalid_argument, "for the --targets option: must be specified at least once!")); } if (Unbundle) { if (InputFileNames.size() != 1) { - reportError(createStringError( + return reportError(createStringError( errc::invalid_argument, "only one input file supported in unbundling mode")); } if (OutputFileNames.size() != TargetNames.size()) { - reportError(createStringError(errc::invalid_argument, - "number of output files and targets should " - "match in unbundling mode")); + return reportError(createStringError( + errc::invalid_argument, "number of output files and targets should " + "match in unbundling mode")); } } else { if (BundlerConfig.FilesType == "a") { - reportError(createStringError(errc::invalid_argument, - "Archive files are only supported " - "for unbundling")); + return reportError(createStringError(errc::invalid_argument, + "Archive files are only supported " + "for unbundling")); } if (OutputFileNames.size() != 1) { - reportError(createStringError( - errc::invalid_argument, - "only one output file supported in bundling mode")); + return reportError( + createStringError(errc::invalid_argument, + "only one output file supported in bundling mode")); } if (InputFileNames.size() != TargetNames.size()) { - reportError(createStringError( + return reportError(createStringError( errc::invalid_argument, "number of input files and targets should match in bundling mode")); } @@ -350,8 +351,8 @@ int main(int argc, const char **argv) { std::vector StandardizedTargetNames; for (StringRef Target : TargetNames) { if (!ParsedTargets.insert(Target).second) { - reportError(createStringError(errc::invalid_argument, - "Duplicate targets are not allowed")); + return reportError(createStringError( + errc::invalid_argument, "Duplicate targets are not allowed")); } auto OffloadInfo = OffloadTargetInfo(Target, BundlerConfig); @@ -368,7 +369,7 @@ int main(int argc, const char **argv) { Msg << ", unknown offloading kind '" << OffloadInfo.OffloadKind << "'"; if (!TripleIsValid) Msg << ", unknown target triple '" << OffloadInfo.Triple.str() << "'"; - reportError(createStringError(errc::invalid_argument, Msg.str())); + return reportError(createStringError(errc::invalid_argument, Msg.str())); } TargetIDs[OffloadInfo.OffloadKind.str() + "-" + OffloadInfo.Triple.str()] @@ -395,7 +396,7 @@ int main(int argc, const char **argv) { Msg << "Cannot bundle inputs with conflicting targets: '" << TargetID.first + "-" + ConflictingTID->first << "' and '" << TargetID.first + "-" + ConflictingTID->second << "'"; - reportError(createStringError(errc::invalid_argument, Msg.str())); + return reportError(createStringError(errc::invalid_argument, Msg.str())); } } @@ -408,14 +409,14 @@ int main(int argc, const char **argv) { // treat missing host triple as error if we do unbundling. if ((Unbundle && HostTargetNum > 1) || (!Unbundle && HostTargetNum != 1 && !BundlerConfig.AllowNoHost)) { - reportError(createStringError(errc::invalid_argument, - "expecting exactly one host target but got " + - Twine(HostTargetNum))); + return reportError(createStringError( + errc::invalid_argument, + "expecting exactly one host target but got " + Twine(HostTargetNum))); } OffloadBundler Bundler(BundlerConfig); - doWork([&]() { + return doWork([&]() { if (Unbundle) { if (BundlerConfig.FilesType == "a") return Bundler.UnbundleArchive(); @@ -424,5 +425,4 @@ int main(int argc, const char **argv) { } else return Bundler.BundleFiles(); }); - return 0; } diff --git a/clang/unittests/AST/ByteCode/BitcastBuffer.cpp b/clang/unittests/AST/ByteCode/BitcastBuffer.cpp new file mode 100644 index 0000000000000..02c38a2201363 --- /dev/null +++ b/clang/unittests/AST/ByteCode/BitcastBuffer.cpp @@ -0,0 +1,87 @@ +#include "../../../lib/AST/ByteCode/BitcastBuffer.h" +#include "clang/AST/ASTContext.h" +#include "gtest/gtest.h" +#include +#include +#include +#include +#include + +using namespace clang; +using namespace clang::interp; + +TEST(BitcastBuffer, PushData) { + BitcastBuffer Buff1(Bytes(sizeof(int)).toBits()); + + const unsigned V = 0xCAFEBABE; + Bits VSize = Bytes(sizeof(V)).toBits(); + std::byte Data[sizeof(V)]; + std::memcpy(Data, &V, sizeof(V)); + + Endian HostEndianness = + llvm::sys::IsLittleEndianHost ? Endian::Little : Endian::Big; + + Buff1.pushData(Data, Bits::zero(), VSize, HostEndianness); + + // The buffer is in host-endianness. + if (llvm::sys::IsLittleEndianHost) { + ASSERT_EQ(Buff1.Data[0], std::byte{0xbe}); + ASSERT_EQ(Buff1.Data[1], std::byte{0xba}); + ASSERT_EQ(Buff1.Data[2], std::byte{0xfe}); + ASSERT_EQ(Buff1.Data[3], std::byte{0xca}); + } else { + ASSERT_EQ(Buff1.Data[0], std::byte{0xca}); + ASSERT_EQ(Buff1.Data[1], std::byte{0xfe}); + ASSERT_EQ(Buff1.Data[2], std::byte{0xba}); + ASSERT_EQ(Buff1.Data[3], std::byte{0xbe}); + } + + { + unsigned V2; + auto D = Buff1.copyBits(Bits::zero(), VSize, VSize, Endian::Little); + std::memcpy(&V2, D.get(), sizeof(V)); + ASSERT_EQ(V, V2); + + D = Buff1.copyBits(Bits::zero(), VSize, VSize, Endian::Big); + std::memcpy(&V2, D.get(), sizeof(V)); + ASSERT_EQ(V, V2); + } + + BitcastBuffer Buff2(Bytes(sizeof(int)).toBits()); + { + short s1 = 0xCAFE; + short s2 = 0xBABE; + std::byte sdata[2]; + + std::memcpy(sdata, &s1, sizeof(s1)); + Buff2.pushData(sdata, Bits::zero(), Bits(sizeof(s1) * 8), HostEndianness); + std::memcpy(sdata, &s2, sizeof(s2)); + Buff2.pushData(sdata, Bits(sizeof(s1) * 8), Bits(sizeof(s2) * 8), + HostEndianness); + } + + if (llvm::sys::IsLittleEndianHost) { + ASSERT_EQ(Buff2.Data[0], std::byte{0xfe}); + ASSERT_EQ(Buff2.Data[1], std::byte{0xca}); + ASSERT_EQ(Buff2.Data[2], std::byte{0xbe}); + ASSERT_EQ(Buff2.Data[3], std::byte{0xba}); + } else { + ASSERT_EQ(Buff2.Data[0], std::byte{0xba}); + ASSERT_EQ(Buff2.Data[1], std::byte{0xbe}); + ASSERT_EQ(Buff2.Data[2], std::byte{0xca}); + ASSERT_EQ(Buff2.Data[3], std::byte{0xfe}); + } + + { + unsigned V; + auto D = Buff2.copyBits(Bits::zero(), Bits(sizeof(V) * 8), + Bits(sizeof(V) * 8), Endian::Little); + std::memcpy(&V, D.get(), sizeof(V)); + ASSERT_EQ(V, 0xBABECAFE); + + D = Buff2.copyBits(Bits::zero(), Bits(sizeof(V) * 8), Bits(sizeof(V) * 8), + Endian::Big); + std::memcpy(&V, D.get(), sizeof(V)); + ASSERT_EQ(V, 0xBABECAFE); + } +} diff --git a/clang/unittests/AST/ByteCode/CMakeLists.txt b/clang/unittests/AST/ByteCode/CMakeLists.txt index ea727cdd4412b..b862fb4834fbd 100644 --- a/clang/unittests/AST/ByteCode/CMakeLists.txt +++ b/clang/unittests/AST/ByteCode/CMakeLists.txt @@ -1,4 +1,5 @@ add_clang_unittest(InterpTests + BitcastBuffer.cpp Descriptor.cpp toAPValue.cpp ) diff --git a/clang/unittests/Basic/DiagnosticTest.cpp b/clang/unittests/Basic/DiagnosticTest.cpp index 36a77c7247655..e03d9a464df7f 100644 --- a/clang/unittests/Basic/DiagnosticTest.cpp +++ b/clang/unittests/Basic/DiagnosticTest.cpp @@ -12,6 +12,7 @@ #include "clang/Basic/DiagnosticLex.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -20,6 +21,7 @@ #include "llvm/Support/VirtualFileSystem.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include #include #include @@ -196,7 +198,17 @@ class SuppressionMappingTest : public testing::Test { return CaptureConsumer.StoredDiags; } + SourceLocation locForFile(llvm::StringRef FileName) { + auto Buf = MemoryBuffer::getMemBuffer("", FileName); + SourceManager &SM = Diags.getSourceManager(); + FileID FooID = SM.createFileID(std::move(Buf)); + return SM.getLocForStartOfFile(FooID); + } + private: + FileManager FM{{}, FS}; + SourceManager SM{Diags, FM}; + class CaptureDiagnosticConsumer : public DiagnosticConsumer { public: std::vector StoredDiags; @@ -255,9 +267,9 @@ TEST_F(SuppressionMappingTest, SuppressesGroup) { clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS); EXPECT_THAT(diags(), IsEmpty()); - EXPECT_TRUE( - Diags.isSuppressedViaMapping(diag::warn_unused_function, "foo.cpp")); - EXPECT_FALSE(Diags.isSuppressedViaMapping(diag::warn_deprecated, "foo.cpp")); + SourceLocation FooLoc = locForFile("foo.cpp"); + EXPECT_TRUE(Diags.isSuppressedViaMapping(diag::warn_unused_function, FooLoc)); + EXPECT_FALSE(Diags.isSuppressedViaMapping(diag::warn_deprecated, FooLoc)); } TEST_F(SuppressionMappingTest, EmitCategoryIsExcluded) { @@ -271,10 +283,10 @@ TEST_F(SuppressionMappingTest, EmitCategoryIsExcluded) { clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS); EXPECT_THAT(diags(), IsEmpty()); - EXPECT_TRUE( - Diags.isSuppressedViaMapping(diag::warn_unused_function, "bar.cpp")); - EXPECT_FALSE( - Diags.isSuppressedViaMapping(diag::warn_unused_function, "foo.cpp")); + EXPECT_TRUE(Diags.isSuppressedViaMapping(diag::warn_unused_function, + locForFile("bar.cpp"))); + EXPECT_FALSE(Diags.isSuppressedViaMapping(diag::warn_unused_function, + locForFile("foo.cpp"))); } TEST_F(SuppressionMappingTest, LongestMatchWins) { @@ -289,12 +301,12 @@ TEST_F(SuppressionMappingTest, LongestMatchWins) { clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS); EXPECT_THAT(diags(), IsEmpty()); + EXPECT_TRUE(Diags.isSuppressedViaMapping( + diag::warn_unused_function, locForFile("clang/lib/Basic/foo.h"))); + EXPECT_FALSE(Diags.isSuppressedViaMapping( + diag::warn_unused_function, locForFile("clang/lib/Sema/bar.h"))); EXPECT_TRUE(Diags.isSuppressedViaMapping(diag::warn_unused_function, - "clang/lib/Basic/foo.h")); - EXPECT_FALSE(Diags.isSuppressedViaMapping(diag::warn_unused_function, - "clang/lib/Sema/bar.h")); - EXPECT_TRUE(Diags.isSuppressedViaMapping(diag::warn_unused_function, - "clang/lib/Sema/foo.h")); + locForFile("clang/lib/Sema/foo.h"))); } TEST_F(SuppressionMappingTest, IsIgnored) { @@ -308,9 +320,7 @@ TEST_F(SuppressionMappingTest, IsIgnored) { clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS); ASSERT_THAT(diags(), IsEmpty()); - FileManager FM({}, FS); - SourceManager SM(Diags, FM); - + SourceManager &SM = Diags.getSourceManager(); auto ClangID = SM.createFileID(llvm::MemoryBuffer::getMemBuffer("", "clang/foo.h")); auto NonClangID = diff --git a/clang/unittests/CodeGen/TBAAMetadataTest.cpp b/clang/unittests/CodeGen/TBAAMetadataTest.cpp index 9f64008358e4f..cad8783ea73fb 100644 --- a/clang/unittests/CodeGen/TBAAMetadataTest.cpp +++ b/clang/unittests/CodeGen/TBAAMetadataTest.cpp @@ -39,6 +39,11 @@ auto OmnipotentCharC = MMTuple( MConstInt(0, 64) ); +auto AnyPtr = MMTuple( + MMString("any pointer"), + OmnipotentCharC, + MConstInt(0, 64) +); auto OmnipotentCharCXX = MMTuple( MMString("omnipotent char"), @@ -116,8 +121,8 @@ TEST(TBAAMetadataTest, BasicTypes) { MValType(PointerType::getUnqual(Compiler.Context)), MMTuple( MMTuple( - MMString("any pointer"), - OmnipotentCharC, + MMString("p1 void"), + AnyPtr, MConstInt(0)), MSameAs(0), MConstInt(0)))); @@ -128,8 +133,8 @@ TEST(TBAAMetadataTest, BasicTypes) { MValType(PointerType::getUnqual(Compiler.Context)), MMTuple( MMTuple( - MMString("any pointer"), - OmnipotentCharC, + MMString("p1 int"), + AnyPtr, MConstInt(0)), MSameAs(0), MConstInt(0)))); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 250e51b542166..63d8dc2486e45 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -27386,6 +27386,13 @@ TEST_F(FormatTest, RemoveSemicolon) { Style); #endif + verifyFormat("auto sgf = [] {\n" + " ogl = {\n" + " a, b, c, d, e,\n" + " };\n" + "};", + Style); + Style.TypenameMacros.push_back("STRUCT"); verifyFormat("STRUCT(T, B) { int i; };", Style); } diff --git a/clang/unittests/Lex/LexerTest.cpp b/clang/unittests/Lex/LexerTest.cpp index 47aa2c131a304..aead7fb899d0a 100644 --- a/clang/unittests/Lex/LexerTest.cpp +++ b/clang/unittests/Lex/LexerTest.cpp @@ -652,6 +652,38 @@ TEST_F(LexerTest, RawAndNormalLexSameForLineComments) { EXPECT_TRUE(ToksView.empty()); } +TEST_F(LexerTest, GetRawTokenOnEscapedNewLineChecksWhitespace) { + const llvm::StringLiteral Source = R"cc( + #define ONE \ + 1 + + int i = ONE; + )cc"; + std::vector Toks = + CheckLex(Source, {tok::kw_int, tok::identifier, tok::equal, + tok::numeric_constant, tok::semi}); + + // Set up by getting the raw token for the `1` in the macro definition. + const Token &OneExpanded = Toks[3]; + Token Tok; + ASSERT_FALSE( + Lexer::getRawToken(OneExpanded.getLocation(), Tok, SourceMgr, LangOpts)); + // The `ONE`. + ASSERT_EQ(Tok.getKind(), tok::raw_identifier); + ASSERT_FALSE( + Lexer::getRawToken(SourceMgr.getSpellingLoc(OneExpanded.getLocation()), + Tok, SourceMgr, LangOpts)); + // The `1` in the macro definition. + ASSERT_EQ(Tok.getKind(), tok::numeric_constant); + + // Go back 4 characters: two spaces, one newline, and the backslash. + SourceLocation EscapedNewLineLoc = Tok.getLocation().getLocWithOffset(-4); + // Expect true (=failure) because the whitespace immediately after the + // escaped newline is not ignored. + EXPECT_TRUE(Lexer::getRawToken(EscapedNewLineLoc, Tok, SourceMgr, LangOpts, + /*IgnoreWhiteSpace=*/false)); +} + TEST(LexerPreambleTest, PreambleBounds) { std::vector Cases = { R"cc([[ diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 4ff5e8b65a686..a551f83ff3f9c 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -5659,8 +5659,6 @@ struct X { }; [[void (X::*xp)();]] [[void (X::**xpp)(const int*);]] -// FIXME: Generate the right syntax tree for this type, -// i.e. create a syntax node for the outer member pointer [[void (X::Y::*xyp)(const int*, char);]] )cpp", {R"txt( @@ -5714,9 +5712,9 @@ SimpleDeclaration | `-SimpleDeclarator ListElement | |-ParenDeclarator | | |-'(' OpenParen -| | |-'X' -| | |-'::' | | |-MemberPointer +| | | |-'X' +| | | |-'::' | | | |-'Y' | | | |-'::' | | | `-'*' diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 534bf2d01d795..630beaef983bc 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -5178,6 +5178,9 @@ GetAttributeHeadingAndSpellings(const Record &Documentation, static void WriteDocumentation(const RecordKeeper &Records, const DocumentationData &Doc, raw_ostream &OS) { + if (StringRef Label = Doc.Documentation->getValueAsString("Label"); + !Label.empty()) + OS << ".. _" << Label << ":\n\n"; OS << Doc.Heading << "\n" << std::string(Doc.Heading.length(), '-') << "\n"; // List what spelling syntaxes the attribute supports. diff --git a/clang/utils/perf-training/perf-helper.py b/clang/utils/perf-training/perf-helper.py index 3ed42a187fd80..d76c6ede3fe5a 100644 --- a/clang/utils/perf-training/perf-helper.py +++ b/clang/utils/perf-training/perf-helper.py @@ -36,7 +36,7 @@ def clean(args): + "\tRemoves all files with extension from ." ) return 1 - for path in args[1:-1]: + for path in args[0:-1]: for filename in findFilesWithExtension(path, args[-1]): os.remove(filename) return 0 diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index fdb9807b1168c..a8e79cd3475ab 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -239,7 +239,7 @@

C++2c implementation status

Remove Deprecated Array Comparisons from C++26 P2865R6 - No + Clang 20 Structured Bindings can introduce a Pack diff --git a/clang/www/hacking.html b/clang/www/hacking.html index 78b67cd05c53c..a17e791eed477 100755 --- a/clang/www/hacking.html +++ b/clang/www/hacking.html @@ -89,9 +89,9 @@

Debugging

qualifiers, and the getTypePtr() method to get the wrapped Type* which you can then dump.
  • For LLDB users there are - data formatters for clang data structures in - - clang/utils/ClangDataFormat.py.
  • + data formatters for LLVM data structures in + + llvm/utils/lldbDataFormatters.py. diff --git a/compiler-rt/include/sanitizer/memprof_interface.h b/compiler-rt/include/sanitizer/memprof_interface.h index 4660a7818c92b..6d9b2a2394f41 100644 --- a/compiler-rt/include/sanitizer/memprof_interface.h +++ b/compiler-rt/include/sanitizer/memprof_interface.h @@ -47,9 +47,9 @@ void SANITIZER_CDECL __memprof_print_accumulated_stats(void); /// User-provided default option settings. /// -/// You can provide your own implementation of this function to return a string -/// containing MemProf runtime options (for example, -/// verbosity=1:print_stats=1). +/// You can set these options via the -memprof-runtime-default-options LLVM flag +/// or you can provide your own implementation of this function. See +/// memprof_flags.h for more info. /// /// \returns Default options string. const char *SANITIZER_CDECL __memprof_default_options(void); diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp index 4129ee8076122..e6c95dfb82c32 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cpp +++ b/compiler-rt/lib/asan/asan_interceptors.cpp @@ -85,7 +85,7 @@ int OnExit() { // ---------------------- Wrappers ---------------- {{{1 using namespace __asan; -DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr) +DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, usize) DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \ @@ -529,13 +529,13 @@ DEFINE_REAL(char*, index, const char *string, int c) return REAL(strcat)(to, from); } -INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { +INTERCEPTOR(char*, strncat, char *to, const char *from, usize size) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strncat); AsanInitFromRtl(); if (flags()->replace_str) { uptr from_length = MaybeRealStrnlen(from, size); - uptr copy_length = Min(size, from_length + 1); + uptr copy_length = Min(size, from_length + 1); ASAN_READ_RANGE(ctx, from, copy_length); uptr to_length = internal_strlen(to); ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); @@ -617,12 +617,12 @@ INTERCEPTOR(char*, __strdup, const char *s) { } #endif // ASAN_INTERCEPT___STRDUP -INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { +INTERCEPTOR(char*, strncpy, char *to, const char *from, usize size) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strncpy); AsanInitFromRtl(); if (flags()->replace_str) { - uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); + uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); ASAN_READ_RANGE(ctx, from, from_size); ASAN_WRITE_RANGE(ctx, to, size); diff --git a/compiler-rt/lib/asan/asan_interceptors.h b/compiler-rt/lib/asan/asan_interceptors.h index 826b45f5ada8c..3e2386eaf8092 100644 --- a/compiler-rt/lib/asan/asan_interceptors.h +++ b/compiler-rt/lib/asan/asan_interceptors.h @@ -124,11 +124,11 @@ void InitializePlatformInterceptors(); # define ASAN_INTERCEPT_PTHREAD_ATFORK 0 #endif -DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size) +DECLARE_REAL(int, memcmp, const void *a1, const void *a2, SIZE_T size) DECLARE_REAL(char*, strchr, const char *str, int c) DECLARE_REAL(SIZE_T, strlen, const char *s) -DECLARE_REAL(char*, strncpy, char *to, const char *from, uptr size) -DECLARE_REAL(uptr, strnlen, const char *s, uptr maxlen) +DECLARE_REAL(char*, strncpy, char *to, const char *from, SIZE_T size) +DECLARE_REAL(SIZE_T, strnlen, const char *s, SIZE_T maxlen) DECLARE_REAL(char*, strstr, const char *s1, const char *s2) # if !SANITIZER_APPLE diff --git a/compiler-rt/lib/asan/asan_interceptors_memintrinsics.h b/compiler-rt/lib/asan/asan_interceptors_memintrinsics.h index eb44f8f2f729b..14727a5d665ed 100644 --- a/compiler-rt/lib/asan/asan_interceptors_memintrinsics.h +++ b/compiler-rt/lib/asan/asan_interceptors_memintrinsics.h @@ -18,8 +18,8 @@ #include "asan_mapping.h" #include "interception/interception.h" -DECLARE_REAL(void *, memcpy, void *to, const void *from, uptr size) -DECLARE_REAL(void *, memset, void *block, int c, uptr size) +DECLARE_REAL(void *, memcpy, void *to, const void *from, SIZE_T size) +DECLARE_REAL(void *, memset, void *block, int c, SIZE_T size) namespace __asan { diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index 73c1b5062ec9a..70dc7d860d8f6 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -574,7 +574,7 @@ set(aarch64_SOURCES if (COMPILER_RT_HAS_AARCH64_SME) if (NOT COMPILER_RT_DISABLE_AARCH64_FMV AND COMPILER_RT_HAS_FNO_BUILTIN_FLAG AND (COMPILER_RT_HAS_AUXV OR COMPILER_RT_BAREMETAL_BUILD)) - list(APPEND aarch64_SOURCES aarch64/sme-abi.S aarch64/sme-libc-mem-routines.S aarch64/sme-abi-init.c aarch64/sme-abi-vg.c aarch64/sme-libc-routines.c) + list(APPEND aarch64_SOURCES aarch64/sme-abi.S aarch64/sme-libc-mem-routines.S aarch64/sme-abi-init.c aarch64/sme-libc-routines.c) message(STATUS "AArch64 SME ABI routines enabled") set_source_files_properties(aarch64/sme-libc-routines.c PROPERTIES COMPILE_FLAGS "-fno-builtin") else() diff --git a/compiler-rt/lib/builtins/aarch64/sme-abi-vg.c b/compiler-rt/lib/builtins/aarch64/sme-abi-vg.c deleted file mode 100644 index 4b9ee8c1d382d..0000000000000 --- a/compiler-rt/lib/builtins/aarch64/sme-abi-vg.c +++ /dev/null @@ -1,18 +0,0 @@ -// 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 "../cpu_model/aarch64.h" - -struct FEATURES { - unsigned long long features; -}; - -extern struct FEATURES __aarch64_cpu_features; - -CONSTRUCTOR_ATTRIBUTE static void get_aarch64_cpu_features(void) { - if (__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED)) - return; - - __init_cpu_features(); -} diff --git a/compiler-rt/lib/interception/interception.h b/compiler-rt/lib/interception/interception.h index 0580d97edda68..3cb6b446638e0 100644 --- a/compiler-rt/lib/interception/interception.h +++ b/compiler-rt/lib/interception/interception.h @@ -37,7 +37,7 @@ #endif #define SIZE_T __sanitizer::usize -#define SSIZE_T __sanitizer::sptr +#define SSIZE_T __sanitizer::ssize typedef __sanitizer::sptr PTRDIFF_T; typedef __sanitizer::s64 INTMAX_T; typedef __sanitizer::u64 UINTMAX_T; diff --git a/compiler-rt/lib/interception/interception_win.cpp b/compiler-rt/lib/interception/interception_win.cpp index dc3018a675dee..b0fb263b62f15 100644 --- a/compiler-rt/lib/interception/interception_win.cpp +++ b/compiler-rt/lib/interception/interception_win.cpp @@ -418,7 +418,7 @@ static void *AllocateTrampolineRegion(uptr min_addr, uptr max_addr, ReportError( "interception_win: AllocateTrampolineRegion failed to find free memory; " "min_addr: %p, max_addr: %p, func_addr: %p, granularity: %zu\n", - (void *)min_addr, (void *)max_addr, granularity); + (void *)min_addr, (void *)max_addr, (void *)func_addr, granularity); return nullptr; #else return ::VirtualAlloc(nullptr, @@ -634,6 +634,9 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0xD284: // 84 D2 : test dl,dl return 2; + case 0xC1F6: // F6 C1 XX : test cl, XX + return 3; + // Cannot overwrite control-instruction. Return 0 to indicate failure. case 0x25FF: // FF 25 XX YY ZZ WW : jmp dword ptr ds:[WWZZYYXX] return 0; @@ -723,8 +726,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { return 7; } - switch (0x00FFFFFF & *(u32*)address) { - case 0x07c1f6: // f6 c1 07 : test cl, 0x7 + switch (0x00FFFFFF & *(u32 *)address) { case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax] case 0xc00b4d: // 4d 0b c0 : or r8, r8 case 0xc03345: // 45 33 c0 : xor r8d, r8d @@ -808,7 +810,6 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0x798141: // 41 81 79 XX YY YY YY YY : cmp DWORD PTR [r9+YY], XX XX XX XX case 0x7a8141: // 41 81 7a XX YY YY YY YY : cmp DWORD PTR [r10+YY], XX XX XX XX case 0x7b8141: // 41 81 7b XX YY YY YY YY : cmp DWORD PTR [r11+YY], XX XX XX XX - case 0x7c8141: // 41 81 7c XX YY YY YY YY : cmp DWORD PTR [r12+YY], XX XX XX XX case 0x7d8141: // 41 81 7d XX YY YY YY YY : cmp DWORD PTR [r13+YY], XX XX XX XX case 0x7e8141: // 41 81 7e XX YY YY YY YY : cmp DWORD PTR [r14+YY], XX XX XX XX case 0x7f8141: // 41 81 7f YY XX XX XX XX : cmp DWORD PTR [r15+YY], XX XX XX XX @@ -835,6 +836,10 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0x2444c7: // C7 44 24 XX YY YY YY YY // mov dword ptr [rsp + XX], YYYYYYYY return 8; + + case 0x7c8141: // 41 81 7c ZZ YY XX XX XX XX + // cmp DWORD PTR [reg+reg*n+YY], XX XX XX XX + return 9; } switch (*(u32*)(address)) { @@ -1247,7 +1252,7 @@ uptr InternalGetProcAddress(void *module, const char *func_name) { char function_name[256]; size_t funtion_name_length = _strlen(func); if (funtion_name_length >= sizeof(function_name) - 1) { - ReportError("interception_win: func too long: '%s'\n", func); + ReportError("interception_win: func too long: '%s'\n", (char *)func); InterceptionFailed(); } diff --git a/compiler-rt/lib/interception/tests/interception_win_test.cpp b/compiler-rt/lib/interception/tests/interception_win_test.cpp index cfa1b592f1e46..761c07d4288f7 100644 --- a/compiler-rt/lib/interception/tests/interception_win_test.cpp +++ b/compiler-rt/lib/interception/tests/interception_win_test.cpp @@ -801,11 +801,219 @@ const struct InstructionSizeData { size_t size; // hold instruction size or 0 for failure, // e.g. on control instructions u8 instr[16]; - size_t rel_offset; + size_t rel_offset; // filled just for instructions with two operands + // and displacement length of four bytes. const char *comment; } data[] = { - /* sorted list */ - {1, {0x50}, 0, "50 : push eax / rax"}, + // clang-format off + // sorted list + { 0, {0x70, 0x71}, 0, "70 XX : jo XX (short conditional jump)"}, + { 0, {0x71, 0x71}, 0, "71 XX : jno XX (short conditional jump)"}, + { 0, {0x72, 0x71}, 0, "72 XX : jb XX (short conditional jump)"}, + { 0, {0x73, 0x71}, 0, "73 XX : jae XX (short conditional jump)"}, + { 0, {0x74, 0x71}, 0, "74 XX : je XX (short conditional jump)"}, + { 0, {0x75, 0x71}, 0, "75 XX : jne XX (short conditional jump)"}, + { 0, {0x76, 0x71}, 0, "76 XX : jbe XX (short conditional jump)"}, + { 0, {0x77, 0x71}, 0, "77 XX : ja XX (short conditional jump)"}, + { 0, {0x78, 0x71}, 0, "78 XX : js XX (short conditional jump)"}, + { 0, {0x79, 0x71}, 0, "79 XX : jns XX (short conditional jump)"}, + { 0, {0x7A, 0x71}, 0, "7A XX : jp XX (short conditional jump)"}, + { 0, {0x7B, 0x71}, 0, "7B XX : jnp XX (short conditional jump)"}, + { 0, {0x7C, 0x71}, 0, "7C XX : jl XX (short conditional jump)"}, + { 0, {0x7D, 0x71}, 0, "7D XX : jge XX (short conditional jump)"}, + { 0, {0x7E, 0x71}, 0, "7E XX : jle XX (short conditional jump)"}, + { 0, {0x7F, 0x71}, 0, "7F XX : jg XX (short conditional jump)"}, + { 0, {0xE8, 0x71, 0x72, 0x73, 0x74}, 0, "E8 XX XX XX XX : call "}, + { 0, {0xE9, 0x71, 0x72, 0x73, 0x74}, 0, "E9 XX XX XX XX : jmp